如何接受泛型迭代器
How to accept generic iterators?
我希望构造函数接受任何具有x
特征并引用类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());
我能在这里做什么?
怎么样:
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_same
替换为 std::is_convertible
,如果您不打算修改输入,请检查const MyClass*
。
迭代器通常由值接受,然后通过委托给其他函数来区分。
例如
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 *
传递随机访问迭代器,请使用带有std::is_same
条件的几个static_assert
作为 sbbabi 的答案。生成的用户体验比纯 SFINAE 更好,因为错误消息显示"请传递随机访问迭代器",而不是"未找到重载"。
相关文章:
- 在 stl 映射和列表 (c++) 上进行迭代的泛型循环
- 后缀运算符链表泛型节点迭代器
- 声明一个模板函数,该函数接收两个泛型迭代器作为参数
- 声明泛型迭代器
- 定义用于迭代不同容器类型的泛型转换迭代器
- 泛型"out of bounds"、"past end"迭代器
- C++泛型迭代器
- 泛型/多态迭代器
- 如何接受泛型迭代器
- C#指针、迭代器和泛型
- 模板泛型树类的模板迭代器的c++操作符重载
- 在泛型类中获取泛型容器的迭代器:如何
- 从泛型函数返回迭代器
- 使用迭代器的泛型构造函数
- 泛型迭代器/指针初始化
- 为泛型函数定义自定义迭代器特征
- 为泛型数据类型创建自己的迭代器
- c++迭代器在一个泛型函数中列出
- 泛型c++多维迭代器
- 如何将基于泛型迭代器的算法与基于实现的算法结合起来?