将任何类型的std::vector传递给函数

3

给定:

template<typename T> class A {  
  B b;
  std::vector<T> vec1;
  std::vector<T> vec2;
}

我希望B有一个成员函数fill(),它接受对这两个向量的引用,并根据包含在b中的某些信息填充vec2的T值。
一种实现方法是为每个可能的参数T重载fill():

fill(const std::vector<float>& a, std::vector<float>& b)

等等,但这将意味着很多不必要的重复,因为操作对于每个可能的T都是相同的。在fill()内部,我可以使用vector::value_type进行计算,但我不知道如何声明它,以便它接受每种std::vector。显而易见的方法是使用带有模板的自由函数。有更简单的方法吗?

4个回答

5

模板化B。

template<typename T> class B {
  void fill(const std::vector<T>& a, std::vector<T>& b) { }
};

template<typename T> class A {  
  B<T> b;
  std::vector<T> vec1;
  std::vector<T> vec2;
}

如果您不想将B模板化,那么请将fill函数模板化:
class B {
  template<typename T>
  void fill(const std::vector<T>& a, std::vector<T>& b) {}
};

1
更多信息:B是继承层次结构中的一部分,具有纯虚函数,并包装在基类的智能指针中。 用户需要使用与A相同的类型实例化B(这增加了错误的可能性),并且对于类的用户来说并不明显,因此我宁愿避免这种情况。 - pmr
我明白重构大型层次结构是一件痛苦的事情,但你也可以尝试使用策略类作为模板参数,而不是传递智能指针,并且显然(根据你的描述)以灵活性为代价牺牲类型安全性。 - Ben Collins

5
您已经得到了许多答案,但我必须在某种程度上与它们不同意。我的直觉反应是,您根本不应该将vector传递给b::fill。相反,您应该传递一个迭代器(或者可能是一对迭代器)。其余部分大体上是正确的:这仍然意味着fill应该是一个模板成员函数。当您调用它时,您可能需要传递一个std::back_insert_iterator,通常使用std::back_inserter获得。

您所说的一部分似乎自相矛盾:如果b::fill修改vec1vec2,它们可能不应该作为const引用传递。诚然,当应用于容器时,const的含义并不完全是其通常的含义,但事实仍然存在,即将对传递内容进行修改的函数传递给const引用似乎是错误的。


1
同意我赞同应该传递迭代器范围而不是容器的观点。他还应该了解迭代器类型擦除。Thomas Becker拥有any_iterator类,Adobe Public Library也是如此。 - David Joyner
关于对const的引用:只有第二个向量将被修改。 关于使用迭代器:填充操作将会相当繁重(大量插入),并且可以从vector::reserve(int)中受益。我如何通过std::back_inserter获得这种性能提升? - pmr
reserve是vector的一个成员函数(也是其中一个构造函数),它不会创建对象。你可以使用reserve()函数,然后再使用back_insert将元素插入到其中。这样做的结果是在预先分配的空间中构造(或赋值给)对象,这正是你想要的。(对于需要大量构造但轻量级赋值的对象,你可以创建所需大小的向量,而不使用back_inserter) - Oren S
很不幸,没有 -- 插入迭代器没有理由不能将 reserve 传递给底层容器,但它在当前的接口中未定义。 - Jerry Coffin

4
模板化填充:
class B {
public:
  template<typename T>
  void fill(const std::vector<T>& a, std::vector<T>& b)
  { /*...*/ }
  //...
};

(从您的描述中可以看出,b 应该是一个 const std::vector<T>&。)

2
你可以将B定义为模板类,将fill定义为模板函数(在非模板类B内部),或者使用标准的std::transform/std::copy/std::fill(它们已经是模板函数)来填充你的向量。(所有这些都位于头文件中。)

之前不知道非模板类中也可以使用模板成员函数。目前最好的选择是使用std::transform。 - pmr

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接