'How to make an overload for templated functions for a custom container's iterator
This is a generic question about templating, I am using advance as an example. Assume there are reasons I can't use ADL or hidden friends here.
The definition of std::advance is:
template< class InputIt, class Distance >
constexpr void advance( InputIt& it, Distance n );
For the sake of argument, say I have a container H, with iterators which for some reason I want to overload std::advance for:
template <typename T, class Allocator=std::allocator<T>>
class H
{
// etc
class iterator;
};
How does one design an advance overload to match that iterator, and have C++ correctly select the overload when calling advance on H's iterator class? The code below does not work because only H is specified in the templating, not the iterator itself:
template< template <typename, class> class container, class T, class Allocator, class Distance >
constexpr void advance( container<T, Allocator>::iterator& it, Distance n );
I can't quite work out how to specify the iterator specifically in the template line.
Solution 1:[1]
A friend of mine came up with a solution based on tags (empty structs).
Basically, put a unique empty struct in the iterator class then build a C++20 concept using it, then use that to match in the template overload:
template <typename T, class A = std::allocator<T>>
class H
{
// etc
public:
class iterator
{
public:
struct cheat_tag {};
// etc
};
};
template<class T>
concept h_iterator = requires { typename T::cheat_tag; };
namespace std
{
template <h_iterator T, class D>
constexpr void advance(T&, D)
{
// etc
}
}
Provided you match the signature of the template you're trying to overload exactly, this should work.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
