【发布时间】:2012-08-31 03:44:33
【问题描述】:
对于我的 C++ 类(尚未涵盖 Boost)的练习,我无法编写一个模板化方法来接受两个迭代器来对 STL 容器中的数值求和。
考虑以下示例:
#include <iostream>
#include <iterator>
#include <vector>
template<typename T>
double Sum(const T & c) {
return 42.0; // implementation stubbed
}
// need help writing this method signature to accept two iterators
template<typename T>
double Sum(const typename T::const_iterator & begin,
const typename T::const_iterator & end) {
return 43.0; // another implementation stub
}
int main() {
std::vector<double> v;
v.push_back(3.14);
v.push_back(2.71);
v.push_back(1.61); // sums to 7.46
std::cout << Sum(v) << ' ' // line 23
<< Sum(v.begin(), v.end()) // line 24
<< '\n';
}
我希望这段代码能输出42 43,但编译失败。
g++ 给我的错误是:
test_exercise2.cpp: In function ‘int main()’:
test_exercise2.cpp:24: error: no matching function for call to ‘Sum(__gnu_cxx::__normal_iterator<double*, std::vector<double, std::allocator<double> > >, __gnu_cxx::__normal_iterator<double*, std::vector<double, std::allocator<double> > >)’
如果我注释掉第 24 行,我会得到 42 作为输出,正如预期的那样。
无论是否存在第二个模板化方法,我都会收到相同的错误消息,因此由于某种原因,它无法将第 24 行的调用解析为我编写的第二个方法。
对于接受两个迭代器的方法,我必须有什么签名?
我之所以坚持这一点是因为我需要支持对std::map<K, V> 的第二个元素求和。这将需要另外两个重载来调用 ->second 而不是取消引用迭代器:
1.template<typename K, typename V> double Sum(const std::map<K, V> & m);(这个没问题)
2. 另一个涉及地图上的迭代器。
如果我能弄清楚如何为std::list 和std::map 指定迭代器的传递,我觉得我将能够为std::map 编写方法。我可以接受使用模板模板的解决方案。
编辑:问题的准确措辞(省略非贡献性句子)。
“上一个练习”中的容器是std::vector<double>、std::list<double>、std::map<std::string, double>。
创建一个名为 Sum() 的模板函数,它接受模板 参数 T 作为输入并返回一个双精度值。模板参数将 成为一个容器。
- 在实现中获取一个迭代器 (T::const_iterator) 用于结束。然后创建一个循环迭代容器 T 并添加所有 价值观。最后返回总和。
- 在主程序中,为与上一个练习不同的容器调用 Sum() 函数。
创建的 Sum() 函数计算完整的总和 容器。还要创建一个计算总和的 Sum() 函数 两个迭代器之间。然后该函数使用模板参数 用于迭代器类型并接受两个迭代器,开始和结束 迭代器。
【问题讨论】:
-
您是否需要为采用两个迭代器的
Sum重载提供特化?您是否被告知 SFINAE 是什么? concrete 类型的地图是否需要专业化? (提示:你不能有函数模板的部分特化) -
是的,作业指定了需要两个迭代器的
Sum重载。该课程没有教授 SFINAE 是什么,但我很高兴了解它。 -
SFINAE 是 Substitution Failure Is Not An Error 的首字母缩写词,这意味着如果编译器开始将模板视为重载决议的候选者,但在执行类型推断时,将类型替换为模板失败(无法替换),模板将被丢弃,但这不会导致编译错误。在更广泛的意义上,该术语用于指代使用语言的该功能通过强制替换错误来启用/禁用模板的技术。
-
回到你的问题,你应该重新审视需求。我不太确定你认为他们在问什么和他们真正在问什么是一回事。对于初学者来说,模板函数不能部分特化(只能完全特化,即你可以特化
std::map<int,double>,但你不能特化std::map<T,U>,其中T和U是未绑定的类型。我并不是说它不能完成,只是如果没有解释 SFINAE,解决方案可能超出了课程的范围。 -
哦,真的吗?嗯,知道这会很有用。由于其他原因,我实际上认为这是一个糟糕的问题,所以我感谢你指出我应该阅读的内容,所以我会去做。在不久的将来,我可能只发布一个与此作业有关的问题。
标签: c++ templates stl iterator