Reputation:
I'm implementing my own version of ranges because they are not in the standard library yet. I got stuck on implementing std::iter_difference_t
.
The latest draft says:
The type
iter_difference_t<I>
denotes
incrementable_traits<I>::difference_type
ifiterator_traits<I>
names a specialization generated from the primary template, and
iterator_traits<I>::difference_type
otherwise.
It seems like the obvious implementation is to have a concept for the first case and have 2nd case take everything else. But I have no idea how to transform this from English to C++. Can someone provide the code?
Upvotes: 4
Views: 551
Reputation: 303517
Step 1. Be the owner of std::iterator_traits
. This lets you write something in the primary like:
template <typename T>
struct iterator_traits {
using __secret_am_i_the_primary_alias = iterator_traits;
};
Which you can check:
template <typename T>
concept is_iterator_primary = std::same_as<
typename iterator_traits<T>::__secret_am_i_the_primary_alias,
iterator_traits<T>>;
Step 2. Now it's pretty easy:
template <typename T>
struct iter_difference {
using type = typename iterator_traits<I>::difference_type;
};
template <is_iterator_primary T>
struct iter_difference<T> {
using type = typename incrementable_traits<I>::difference_type;
};
template <typename T>
using iter_difference_t = typename iter_difference<T>::type;
Upvotes: 3