The direct issue here is that decltype((*t.begin()))
for std::set<int>
gives you the type int const&
, and the type trait std::is_const<T>
checks if T
is some type U const
. A reference is not const.
You need to strip the reference first:
template <typename T>
concept IsConst = std::is_const_v<std::remove_reference_t<T>>;
That said, this isn't really a completely correct check for const-ness. Consider the range views::iota(0, 10)
which gives you a bunch of integers on demand. The reference type of this range is int
(not int&
, not int const&
, just int
). This is not a const
type, so your concept would say that such a range does not model IsIterableOfConst
(side-note: the term is range, not iterable). But such a range really is const - you cannot modify the contents of it.
So a closer answer would be:
template <typename T>
inline constexpr bool is_suitably_const = true;
template <typename T>
inline constexpr bool is_suitably_const<T&> = is_const_v<T>;
template <typename R>
concept RangeOfConst = range<R> && is_suitably_const<range_reference_t<R>>;
This would say that vector<int>
is not a RangeOfConst
, set<int>
and vector<int> const
are, as is iota_view<int>
.
But... it would also say that vector<bool>
is a RangeOfConst
, even though you can modify those! I'll leave that one as something to ponder for the future.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…