我希望交换迭代器指向的2个值。所以我想专门用于获取迭代器的模板函数。你能告诉我,我怎么能这样做?
非迭代器的函数:
template <typename T>
void exch(T &a, T &b)
{
T c( std::move(a) );
a = std::move(b);
b = std::move(c);
}
迭代器的函数:
template <typename It>
void exch(It &a, It &b)
{
auto c( std::move(*a) );
*a = std::move(*b);
*b = std::move(c);
}
当然,有两个函数我收到错误:
/projects/DFSTL/main.cpp:17:6:错误:重新定义'template void exch(It&amp;,It&amp;)'
答案 0 :(得分:2)
答案 1 :(得分:2)
我建议不要这样做 - 交换a
和b
,并交换a
和b
间接引用的内容,这是超载的诱人之处。但如果你这样做,你最终会得到非常奇怪的行为。
如果必须,第一步将涉及编写自己的is_iterator
特征类。这可以通过各种方法完成。适用于某些编译器的一种方法是使用std::iterator_traits<It>::iterator_category
的SFINAE分辨率,并检查input_iterator_tag
或output_iterator_tag
是否是该类型的基础。
您通常需要检测void*
和cv变体。这仍然是实现定义的行为,因为非迭代器上的std::iterator_traits
生成实现定义的结果。
更复杂的方法是检查迭代器的每个类型公理并测试它们,如果所有传递都说它是迭代器。
获得is_iterator<T>
后,您可以使用SFINAE:
template <class T, class=std::enable_if_t< !is_iterator<std::decay_t<T>>{} >>
void exch(T &a, T &b) {
using std::swap;
swap(a,b);
}
迭代器的函数:
template <class It, class=std::enable_if_t< is_iterator<std::decay_t<It>>{} >>
void exch(It a, It b) {
using std::iter_swap;
iter_swap(a,b);
}
请注意,我在启用了ADL的上下文中调用了swap
和iter_swap
std::
,而不是手动实现它。这允许在其封闭命名空间中专门化自己的swap
的类型自动获得更优化的解决方案。