将迭代器传递给类函数

Passing iterators to class functions

本文关键字:类函数 迭代器      更新时间:2023-10-16

我正在尝试创建一个新的模板化类"CrazyBucket",它必须包含多个T类型的值。

我想为这个类创建一个构造函数,它可以接受任何 2 个正向迭代器作为其参数,并将这些值(T类型)复制到类实例。

构造 函数:

CrazyBucket< T >::CrazyBucket( iterator< forward_iterator_tag, T > start,  iterator< forward_iterator_tag, T > end )
{ ... }

但是当我试图用它来称呼它时,

vector< int > vec;
vec.push_back( 4 );
CrazyBucket< int > bucket( vec.begin(), vec.end() );

我收到以下错误,

candidate constructor not viable: no known conversion from 'iterator' (aka '__wrap_iter<pointer>') to 'std::iterator<std::forward_iterator_tag, int>' for 1st argument

非常感谢

有关如何定义构造函数的任何帮助。

提前谢谢。

您可以使用 SFINAE 以我认为接近您想要的方式排除不匹配的类型。

#include <iostream>
#include <iterator>
#include <vector>
template<class T>
class CrazyBucket
{
public:
    template<class It, typename = typename std::enable_if<
        std::is_same< typename std::iterator_traits<It>::value_type,T>::value>::type>
    CrazyBucket(It beg, It end)
    {
        std::cout << __PRETTY_FUNCTION__ << 'n';
    }
};
int main()
{
    std::vector<int> vInt;
    CrazyBucket<int> cbOK(vInt.begin(), vInt.end());
    int ar[10];
    CrazyBucket<int> cbAlsoOK(ar, ar+10);
    // uncomment for failure test case.
    //std::vector<double> vDbl;
    //CrazyBucket<int> cbFail(vDbl.begin(), vDbl.end());
}

还通过静态断言完成:

template<class It>
CrazyBucket(It beg, It end)
{
    static_assert(std::is_same<T, typename std::iterator_traits<It>::value_type>::value,
       "failed to match iterator value type");
    std::cout << __PRETTY_FUNCTION__ << 'n';
}

两者都是限制性的,你应该知道这可能不是你心目中的最终目标。例如,short的迭代自然会存储为int而不会丢失数据,但这种 SFINAE 会抛弃它。这也可以通过更多的扩展来克服,但到那时,我认为你需要考虑它最终是否真的值得。

无论如何,祝你好运。

它真的必须是构造函数吗?在我看来,问题是您需要一个专门的构造函数,这在标准中是不可能的。如果可以将初始化延迟到成员函数,则以下方法将起作用:

template<class T>
struct CrazyContainer {
  template<class U>
  void init(U first,U last) {
    for(auto it=first;it!=last;it++) {
      // do stuff with 'it'
    }
  }
};
main() {
  std::vector<int> vec;
  CrazyContainer<int> f;
  f.init(vec.begin(),vec.end());
}

我期待着看看是否有其他人可以想出一种通过构造函数允许这样做的方法。

编辑:感谢 Sebastian 指出模板化构造函数像模板化方法一样工作:

template<class T>
struct CrazyContainer {
  template<class U>
  CrazyContainer(U first,U last) {
    for(auto it=first;it!=last;it++) {
      // do stuff
    }
  }
};

main() {
  std::vector<int> v;
  std::set<int> s;
  CrazyContainer<int> cv(v.begin(),v.end());
  CrazyContainer<int> cs(s.begin(),s.end());
}