I would like to use std::ranges::iota_view for a custom data type that is "int" like in the same way I would use std::ranges::iota_view for an int. I couldn't figure out how to adjust the code based on gcc's error messages, which are posted below:
#include <ranges>
#include <limits>
struct IntLike {
IntLike(int val = {}) : m_val{val} {}
operator int() const { return m_val; }
IntLike& operator++() { ++m_val; return *this; }
IntLike operator++(int) { IntLike ret = *this; ++m_val; return ret; }
friend auto operator <=>(IntLike lhs, IntLike rhs) = default;
int m_val;
};
namespace std {
template<>
struct iterator_traits<IntLike> {
using difference_type = IntLike;
};
}
int main()
{
static_assert(std::same_as<std::iter_difference_t<int>, int>);
static_assert(std::same_as<std::iter_difference_t<IntLike>, IntLike>);
std::ranges::iota_view(0, 2);
std::ranges::iota_view(IntLike{0}, IntLike{2});
return 0;
}
Errors:
<source>:26:50: error: class template argument deduction failed:
26 | std::ranges::iota_view(IntLike{0}, IntLike{2});
| ^
<source>:26:50: error: no matching function for call to 'iota_view(IntLike, IntLike)'
In file included from <source>:1:
/opt/compiler-explorer/gcc-12.2.0/include/c++/12.2.0/ranges:617:7: note: candidate: 'template<class _Winc, class _Bound> iota_view(typename std::ranges::iota_view<_Winc, _Bound>::_Iterator, typename std::ranges::iota_view<_Winc, _Bound>::_Sentinel)-> std::ranges::iota_view<_Winc, _Bound> requires !(same_as<_Winc, _Bound>) && !(same_as<_Bound, std::unreachable_sentinel_t>)'
617 | iota_view(_Iterator __first, _Sentinel __last)
| ^~~~~~~~~
/opt/compiler-explorer/gcc-12.2.0/include/c++/12.2.0/ranges:617:7: note: template argument deduction/substitution failed:
<source>:26:50: note: couldn't deduce template parameter '_Winc'
The first template parameter W of iota_view requires it to model weakly_incrementable, which requires that its difference type must be signed-integer-like type, which includes signed integer type and signed integer-class type. The latter is an implementation-defined type with integer behavior, which cannot be defined by the user.
Since the difference type of IntLike is IntLike, which is not a signed-integer-like type, the constraint is not satisfied.
The simplest workaround is to define the difference_type of IntLike as ptrdiff_t which has enough width to accommodate the subtracted value of the maximum and minimum values of int.
namespace std {
template<>
struct iterator_traits<IntLike> {
using difference_type = ptrdiff_t;
};
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With