迭代器的C ++模板特化

时间:2014-11-30 22:59:12

标签: c++ templates c++11 swap

我希望交换迭代器指向的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;)'

2 个答案:

答案 0 :(得分:2)

这些模板函数看起来都与编译器完全相同。这就是你得到编译器错误的原因。

您是否尝试过使用此功能:std::swap()

它看起来像你想要的 - 并且专门针对交换有意义的所有STL容器类型。

答案 1 :(得分:2)

我建议不要这样做 - 交换ab,并交换ab间接引用的内容,这是超载的诱人之处。但如果你这样做,你最终会得到非常奇怪的行为。

如果必须,第一步将涉及编写自己的is_iterator特征类。这可以通过各种方法完成。适用于某些编译器的一种方法是使用std::iterator_traits<It>::iterator_category的SFINAE分辨率,并检查input_iterator_tagoutput_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的上下文中调用了swapiter_swap std::,而不是手动实现它。这允许在其封闭命名空间中专门化自己的swap的类型自动获得更优化的解决方案。