2

我希望构造函数接受任何具有xtrait 和引用 class的迭代器y

Class(std::iterator<std::random_access_iterator_tag, MyClass*> it);

但是当我尝试传递这样的迭代器时,编译失败并显示Candidate constructor not viable: no known conversion from 'iterator' (aka '__deque_iterator<value_type, pointer, reference, __map_pointer, difference_type, __block_size>') to 'std::iterator<std::random_access_iterator_tag, MyClass *>'.

插入代码:

std::deque<MyClass*> collection_with_random_access_iterator{};
Class tmp(collection_with_random_access_iterator.begin());

我可以在这里做什么?

4

2 回答 2

3

关于什么:

template<class Iterator>
Class(Iterator it,
  typename std::enable_if<
          std::is_same<
                  typename std::iterator_traits<Iterator>::value_type,
                  MyClass*
          >::value //checks for value_type
          &&
          std::is_base_of<
                  std::random_access_iterator_tag,
                  typename std::iterator_traits<Iterator>::iterator_category
          >::value //checks for iterator category
    >::type * = 0);

编辑你也应该考虑用 替换第一个std::is_samestd::is_convertible并检查const MyClass*你是否不打算修改输入。

于 2013-09-07T10:21:29.023 回答
1

迭代器通常按值接受,然后通过委托给其他函数来区分。

例如,

    template< typename iterator >
    Class( iterator it ) {
        init_class( * it, typename std::iterator_traits< iterator >::category() );
    }

    template< typename iterator >
    void init_class( iterator it, std::random_access_iterator_tag ) {
        for ( int i = 0; i != 42; i +=3 ) {
            do_something( it[ i ] );
        }
    }

    void do_something( MyClass * ) { … }
};

传递错误的迭代器会导致函数内部出现错误,这对用户来说可能很神秘。但这就是标准库实现中通常发生的情况,也是在发明 SFINAE 之前最初使用迭代器的方式。如果有常见的用户错误,您可以专门捕获它们并引导用户查看特定的错误/评论。

如果不需要选择不同的行为,但想确保用户通过了随机访问迭代器MyClass *,请使用带条件的几个static_assertsstd::is_same作为 sbabbi 的答案。由此产生的用户体验比纯 SFINAE 更好,因为错误消息显示“请传递随机访问迭代器”,而不是“未找到重载”。

于 2013-09-07T11:17:50.603 回答