6

我被这个错误困住了。我也找到了一种解决方法,但这有点扼杀了锻炼的全部目的。

我正在尝试创建一个函数,它需要两个指向同一个容器的迭代器。我会找到它们之间的元素之和。我为像vector这样的顺序容器创建了通用函数,效果很好。我为关联容器重载了相同的函数。这是给出错误的那个。

map<string,double> myMap;
myMap["B"]=1.0;
myMap["C"]=2.0;
myMap["S"]=3.0;
myMap["G"]=4.0;
myMap["P"]=5.0;

map<string,double>::const_iterator iter1=myMap.begin();
map<string,double>::const_iterator iter2=myMap.end();

cout<<"\nSum of map using the iterator specified range is: "<<Sum(iter1,iter2)<<"\n"; 
//Above line giving error. Intellisense is saying: Sum, Error: no instance of overloaded function "Sum" matches the argument list.

//function to calculate the sum is listed below (It appears in a header file with <map> header included):
template <typename T1,typename T2>
double Sum(const typename std::map<T1,T2>::const_iterator& input_begin,const typename std::map<T1,T2>::const_iterator& input_end)
{
double finalSum=0;
typename std::map<T1,T2>::const_iterator iter=input_begin;

for(iter; iter!=input_end; ++iter)
{
    finalSum=finalSum+ (iter)->second;
}

return finalSum;
}

编译错误为:1>c:\documents and settings\ABC\my documents\visual studio 2010\projects\demo.cpp(41): error C2783: 'double Sum(const std::map::const_iterator &,const std ::map::const_iterator &)' : 无法推导出 'T1' 的模板参数

解决方法:

如果调用 Sum(iter1,iter2) 替换为 Sum < string,double > (iter1,iter2),则编译正常。

我是否首先尝试按照 C++ 标准做一些不可能的事情?

4

1 回答 1

7

错误其实很明显,在下面的模板中:

template <typename T1,typename T2>
double Sum(const typename std::map<T1,T2>::const_iterator& input_begin,
           const typename std::map<T1,T2>::const_iterator& input_end)

类型T1T2不能从调用地点的参数推导出来。这在标准中是这样定义的,如果您考虑一下(在一般情况下),这是有道理的。

考虑一下,而不是std::map<>::const_iterator你有sometemplate<T>::nested_type,并且调用地点的论点是一个int. 如果编译器必须推断类型,它必须实例化宇宙sometemplate中所有可能的类型T(无限集),并找出其中嵌套类型nested_type是 typedef to的类型int

正如有人在评论中指出的那样,您可以更改模板,以便无需在地图的键和值类型上进行模板化,而是只需使用迭代器。


委托提取价值

Sum这是提供可以同时处理顺序容器和关联容器的单一实现的解决方法。

namespace detail {
template <typename T> T valueOf( T const & t ) { return t; }
template <typename K, typename V>
V valueOf( std::pair<const K, V> const & p ) {
   return p.second;
}
}
template <typename Iterator>
double Sum( Iterator begin, Iterator end ) {
  double result = 0;
  for (; begin != end; ++begin) {
     result += detail::valueOf(*begin);
  }
  return result;
}

我还没有测试过代码,但应该这样做。这可能比在Sum模板上使用 SFINAE 简单得多。

于 2012-11-26T21:30:00.340 回答