我正在学习STL和模板。这是我的问题。我写了这个函数计算“两个迭代器之间的元素之和:
”template <typename Iter> double PartialSum(Iter itBegin, Iter itEnd){
if (itBegin == itEnd) return 0.;
double dSum = 0;
while(itBegin != itEnd){
dSum += (*itBegin);
++itBegin;
}
return dSum;
}
这很好用(我知道我可以使用std::accumulate
,但这是出于学习目的)。现在,我想为std:map
提供相同的功能,但迭代器的工作方式与std::vector
和std::list
的工作方式不同。因此,我想编写重载/专用PartialSum
。我尝试过和失败的是这个(最小的例子):
template <typename T1, typename T2> double PartialSum(std::map<T1,T2>::iterator itBegin{
return 0.;
}
这是错误日志:
Main.cpp(42): error: nontype "std::map<_Key, _Tp, _Compare, _Alloc>::iterator [with _Key=T1, _Tp=T2, _Compare=std::less<T1>, _Alloc=std::allocator<std::pair<const T1, T2>>]" is not a type name template <typename T1, typename T2> double PartialSum(std::map<T1,T2>::iterator itBegin){ Main.cpp(83): error: no instance of overloaded function "PartialSum" matches the argument list argument types are: (std::_Rb_tree_iterator<std::pair<const std::string, int>>) std::cout<<"Map partial sum: "<<PartialSum(myMap.begin())<<std::endl;
由于它如此简单,我可能不会忽略一些非常基本的东西。很高兴听到你的意见: - )
答案 0 :(得分:2)
尝试以另一种方式制定。
考虑你有功能
template<typename T>
T f(){
return T();
}
此处无法自动获取T,因此您需要将其称为f<T>()
。与
template <typename T>
int f(typename type<T>::inner){
//
}
例如,如果你有
struct type{
typedef int inner;
}
这里很容易看到,如果你打电话给f(0)
,就不可能得到T.
您可以说在map
的特定情况下可以获得它,但您将如何定义它?
你应该阅读c ++标准来阅读哪种类型应该是可以推断的。
在您的情况下,您可以通过以下方式致电
PartialSum<std::string, int>(m.begin());
std::accumulate
来源以获得一些想法。
template<typename _InputIterator, typename _Tp, typename _BinaryOperation>
inline _Tp
accumulate(_InputIterator __first, _InputIterator __last, _Tp __init,
_BinaryOperation __binary_op)
{
// concept requirements
__glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
__glibcxx_requires_valid_range(__first, __last);
for (; __first != __last; ++__first)
__init = __binary_op(__init, *__first);
return __init;
}
答案 1 :(得分:1)
除了T1和T2无法推导的问题之外,还有另一个问题,就是你错过了从属名称上的typename
关键字
template<typename T1, typename T2>
void MyFunction(typename std::map<T1, T2>::iterator it /*, ...*/)
// ^^^^^^^^^
您看,依赖名称是依赖于模板参数的名称。实际上,理论上可以存在类型为T1和T2的类型,其名称map :: iterator不是类型,而是静态数据成员。除非您明确指定它是一种类型,否则编译器将始终采用数据成员。
你应该做这样的事情
template<class ValueType, class IteratorType, class Func>
ValueType partialSum(IteratorType first, IteratorType last, ValueType startingValue = ValueType(), Func func = std::plus<ValueType>())
这将涵盖所有情况。要对地图求和,您需要提供添加两对的func。
答案 2 :(得分:-2)
当您取消引用std::map<T1, T2>::iterator
时,会得到std::pair<const T1, T2>
,其中.first
元素是关键字,.second
元素是值。
这样的一般结构:(代码未经测试,甚至未编译)
template <typename T1, typename T2> double PartialSum(std::map<T1,T2>::iterator itBegin, std::map<T1,T2>::iterator itEnd)
{
double dSum = 0;
while(itBegin != itEnd){
dSum += (itBegin->second);
++itBegin;
}
return dSum;
}