Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use iota_view for custom IntLike types?

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'
like image 367
MarkB Avatar asked Nov 28 '25 04:11

MarkB


1 Answers

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;
    };
}
like image 64
康桓瑋 Avatar answered Nov 29 '25 22:11

康桓瑋



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!