[英]c++ function template specialization with a STL container
I'm learning STL and templates. 我正在学习STL和模板。 Here's my problem.
这是我的问题。 I wrote this function calculating sum of elements "between" two iterators:
我写了这个函数计算两个迭代器之间的元素之和:
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;
}
And this works fine (I know I can use std::accumulate
but this is for learning purposes). 这工作正常(我知道我可以使用
std::accumulate
但这是出于学习目的)。 Now, I would like to have the same functionality for std:map
but iterators there work differently than in the case of std::vector
and std::list
. 现在,我想为
std:map
相同的功能,但迭代器的工作方式与std::vector
和std::list
的情况不同。 Therefore, I'd like to write overloaded/specialized PartialSum
. 因此,我想编写重载/专用
PartialSum
。 What I tried and failed is this (minimal example): 我尝试过和失败的是这个(最小的例子):
template <typename T1, typename T2> double PartialSum(std::map<T1,T2>::iterator itBegin{
return 0.;
}
This is the error log: 这是错误日志:
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;
Since it's so simple I probably don't undersatnd something very fundamental. 由于它如此简单,我可能不会理解一些非常基本的东西。 Would be happy to hear your opinion :-)
很高兴听到你的意见:-)
Trying to formulate in another way. 试图以另一种方式制定。
Consider you have function 考虑一下你有功能
template<typename T>
T f(){
return T();
}
It's impossible here to automatically get T, so you need call it as f<T>()
. 这里不可能自动获得T,因此您需要将其称为
f<T>()
。 Same goes with 同样如此
template <typename T>
int f(typename type<T>::inner){
//
}
For example, if you have 例如,如果你有
struct type{
typedef int inner;
}
It's easily to see here, that if you call f(0)
it's impossible to get T. 很容易看到这里,如果你调用
f(0)
就不可能得到T.
You may say that's possible to get it in that particular case with map
, but how will you define it? 您可能会说在
map
中使用该特定情况可以获得它,但您将如何定义它?
You should read c++ standard to read which type should be deducable. 你应该阅读c ++标准来阅读哪些类型应该是可以推断的。
In your case you may call in following way 在您的情况下,您可以通过以下方式致电
PartialSum<std::string, int>(m.begin());
BTW, It seems, that map is just uncommon case, you may try to do something more general, that will work with any iterator type. 顺便说一句,看起来,地图只是不常见的情况,你可能会尝试做一些更通用的事情,这将适用于任何迭代器类型。 You may see
std::accumulate
sources to get some ideas. 你可能会看到
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;
}
Apart from the problem that T1 and T2 are not deducible, there is another problem that you're missing the typename
keyword on a dependent name 除了T1和T2不可推导的问题之外,还有另一个问题,即您在从属名称上缺少
typename
关键字
template<typename T1, typename T2>
void MyFunction(typename std::map<T1, T2>::iterator it /*, ...*/)
// ^^^^^^^^^
You see, a dependent name is a name dependent on the template arguments. 您看,依赖名称是依赖于模板参数的名称。 Indeed, there could theoretically be such types T1 and T2 for which the name map::iterator is not a type but is, say, a static data member.
实际上,理论上可以存在类型为T1和T2的类型,其名称map :: iterator不是类型,而是静态数据成员。 The compiler will always assume a data member unless you explicitly specify that it is a type.
除非您明确指定它是一种类型,否则编译器将始终采用数据成员。
You should simply do something like this 你应该简单地做这样的事情
template<class ValueType, class IteratorType, class Func>
ValueType partialSum(IteratorType first, IteratorType last, ValueType startingValue = ValueType(), Func func = std::plus<ValueType>())
And this will cover all cases. 这将涵盖所有情况。 To sum a map you will need to provide func that adds two pairs.
要对地图求和,您需要提供添加两对的func。
When you dereference a std::map<T1, T2>::iterator
, you get a std::pair<const T1, T2>
, where the .first
element is the key, and the .second
element is the value. 当取消引用
std::map<T1, T2>::iterator
,就会得到一个std::pair<const T1, T2>
其中所述.first
元件是关键,和.second
元件是值。
General structure like this: (code untested, even uncompiled) 像这样的一般结构:(代码未经测试,甚至未编译)
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;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.