我想知道是否有办法创建一个模板函数,该函数引用特定类型的任何集合。例如:
class Bob
{
public:
int age;
int height;
}
template<class T>
void functionWhichIteratesOverBobs(T &bobs)
{
int totalAge = 0;
for(auto &bob: bobs)
{
totalAge += bob.age;
}
}
基本上有一种方法可以在模板函数的定义中要求T有一个begin()和end()函数,它将迭代器返回给T.
我已经看到了以下问题,但这需要一个起点和终点的功能,即
std::vector<Bob> bobs;
functionWhichIteratesOverBobs(bob.begin(), bob.end());
当我想要的是:
std::vector<Bob> bobs;
functionWhichIteratesOverBobs(bobs);
Function that takes an STL iterator over ANY container of a elements of a specific type
答案 0 :(得分:1)
如果您希望保持过载设置未受污染,请使用表达式SFINAE,如下所示:
template<class T>
void functionWhichIteratesOverBobs(T &bobs)
-> decltype(std::begin(bobs), std::end(bobs), void()) {
// [..Range based for over bobs..]
}
请记住,如果给出错误的参数,您显示的函数模板不会在没有错误的情况下实例化,所以这当前是多余的 - 直到您开始重载functionWhichIteratesOverBobs
。
答案 1 :(得分:0)
C ++概念Container的成员类型value_type
是所包含元素的类型,因此您可以像使用迭代器一样使用SFINAE - 它甚至更简单,因为您不需要使用iterator_traits
:
template<class T>
auto functionWhichIteratesOverBobs(T &bobs)
-> std::enable_if_t<std::is_same_v<typename T::value_type, Bob>>
{
// ...
}
请注意,这不适用于原始数组;如果您希望这些工作,您可以使用decltype(std::begin(bobs))
和iterator_traits
:
template<class T>
auto functionWhichIteratesOverBobs(T &bobs) -> std::enable_if_t<std::is_same_v<
typename std::iterator_traits<decltype(std::begin(bobs))>::value_type, Bob>>
{
// ...
}
答案 2 :(得分:0)
是。这是可能的。
作为Ed S. comment,只需使用您在问题中编写的相同功能。如果bobs
没有begin()
和end()
,编译器会通过生成错误通知您。
Demo