3

我正在学习 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::vectorand的情况不同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;

由于它是如此简单,我可能不会低估一些非常基本的东西。很高兴听到你的意见:-)

4

3 回答 3

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;
}
于 2013-04-17T16:38:27.597 回答
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。

于 2013-04-17T16:42:20.157 回答
-2

当您取消引用 astd::map<T1, T2>::iterator时,您会得到 a 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;
}
于 2013-04-17T16:07:00.817 回答