概念 as_same 身份失败

Concept as_same identity fail

我有一个很好的类型特征来检查类型 T 是否是迭代器:

我尝试做同样的事情,但有概念。我的第一次尝试是:

template<typename T>
concept isIterator = requires(T a) {
    { typename std::iterator_traits<T>::difference_type{} }   ->   std::same_as<typename std::iterator_traits<T>::difference_type>;
    { typename std::iterator_traits<T>::pointer{} }           ->   std::same_as<typename std::iterator_traits<T>::pointer>;
    { typename std::iterator_traits<T>::value_type{} }        ->   std::same_as<typename std::iterator_traits<T>::value_type>;
    { typename std::iterator_traits<T>::iterator_category{} } ->   std::same_as<typename std::iterator_traits<T>::iterator_category>;
    // this line trigger the assert for
    //  static_assert(is_iterator_v<std::vector<int>::iterator>);
    //  static_assert(is_iterator_v<int*>);
    { typename std::iterator_traits<T>::reference{} }         ->   std::same_as<typename std::iterator_traits<T>::reference>;

};

// default case
template <class T>
struct is_iterator : std::false_type
{
};


// specialization
template <isIterator It>
struct is_iterator<It> : std::true_type
{
};

template <class T>
constexpr bool is_iterator_v = is_iterator<T>::value;

演示:https://wandbox.org/permlink/shrJpZPIlS0pXKak

但它失败了:

static_assert(is_iterator_v<std::vector<int>::iterator>);
static_assert(is_iterator_v<int*>);

并继续:

static_assert(is_iterator_v<std::vector<int>::const_iterator>);
static_assert(is_iterator_v<std::list<double>::const_iterator>);
static_assert(!is_iterator_v<std::list<double>>);
static_assert(!is_iterator_v<int>);

我有两个问题:

  1. 为什么我的概念与 std::vector<int>::iteratorint* 不匹配?
  2. static_assert(is_iterator_v<std::vector<int>::const_iterator>); 有效但引用不是默认构造的,那么它如何通过 { typename std::iterator_traits<T>::reference{} } 要求? Thx @cpplearner

注意:我知道我可以做到:

template<typename T>
concept isIterator = requires(T a) {
     typename std::iterator_traits<T>::difference_type;
     typename std::iterator_traits<T>::pointer;
     typename std::iterator_traits<T>::value_type;
     typename std::iterator_traits<T>::iterator_category;
     typename std::iterator_traits<T>::reference;
};

它的效果很好,但我想了解为什么我的第一次尝试失败了。

它因 std::vector<int>::iteratorint* 而失败,因为:

  • std::iterator_traits<int*>::reference == int&
  • std::iterator_traits<const int*>::reference == int&
  • int&{} 不编译(const int&{} 编译)

所以 { typename std::iterator_traits<T>::reference{} } 对这些类型失败。它可以用 :

修复
 { std::declval<typename std::iterator_traits<T>::reference>() }         ->   std::same_as<typename std::iterator_traits<T>::reference>;