我希望构造函数接受任何具有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());
我可以在这做什么?
答案 0 :(得分: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_same
替换为std::is_convertible
,如果您不打算修改输入,请检查const MyClass*
。
答案 1 :(得分: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_assert
个条件为std::is_same
的{{1}}个sbabbi的答案。由此产生的用户体验优于纯SFINAE,因为错误消息显示“请传递随机访问迭代器”,而不是“未发现过载。”