I am trying to learn the concept of concepts in c++ and for this I wanted to create a type that is std::weakly_incrementable.
The concept is as follow :
template< class I >
concept weakly_incrementable =
std::movable<I> &&
requires(I i) {
typename std::iter_difference_t<I>;
requires /*is-signed-integer-like*/<std::iter_difference_t<I>>;
{ ++i } -> std::same_as<I&>; // not required to be equality-preserving
i++; // not required to be equality-preserving
};
I understand from this that my type has to
I
so look something like :
struct I {
void operator*() {}
I& operator++() { return *this; }
void operator++(int){}
};
However it is not clear what the type requirement asks for exacactly
typename std::iter_difference_t<I>;
requires /*is-signed-integer-like*/<std::iter_difference_t<I>>;
In the end, looking at examples I found that I need the following
struct I {
using difference_type = int; // needed because of type requirement
void operator*() {}
I& operator++() { return *this; }
void operator++(int){}
};
but how do I guess or understand from the documentation that I need to define a type called difference_type
and not iter_difference_t
or something else?
std::iter_difference_t
is an alias template defined in the standard library.
The requirement typename std::iter_difference_t<I>;
is asking that std::iter_difference_t<I>
is a valid type, and requires /*is-signed-integer-like*/<std::iter_difference_t<I>>;
is asking that that type is signed-integer-like, which is described later on in the page.
std::iter_difference_t<I>
is std::iterator_traits<I>::difference_type
if you specialize std::iterator_traits<I>
, otherwise it is std::incrementable_traits<I>::difference_type
.
std::incrementable_traits<I>
by default has a difference_type
member that is either typename I::difference_type
if that exists or std::make_signed_t<decltype(std::declval<I>() - std::declval<I>())>
if there is an operator-
.
So there are 4 distinct ways to define std::iter_difference_t
.
Specialize std::iterator_traits<I>
:
struct I { I& operator++() { return *this; } void operator++(int) {} };
template<>
struct std::iterator_traits<I> {
using difference_type = int;
};
static_assert(std::weakly_incrementable<I>);
Specialize std::incrementable_triats<I>
:
struct I { I& operator++() { return *this; } void operator++(int) {} };
template<>
struct std::incrementable_traits<I> {
using difference_type = int;
};
static_assert(std::weakly_incrementable<I>);
Provide a member difference_type
, like you did
Provide an operator-
:
struct I { I& operator++() { return *this; } void operator++(int) {} };
int operator-(const I&, const I&);
static_assert(std::weakly_incrementable<I>);