【问题标题】:error C2783 Could not deduce template arguments错误 C2783 无法推断模板参数
【发布时间】:2012-11-14 10:19:56
【问题描述】:

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

我正在尝试创建一个函数,它需要两个迭代器指向同一个容器。我会找到它们之间的元素之和。我为像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 (iter1,iter2),则编译正常。

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

【问题讨论】:

  • 尝试让 Sum 的模板类型成为迭代器,而不是迭代器的内容类型。
  • 然后它与我为向量和其他顺序容器编写的一般 sum 函数发生冲突: template double Sum(const T& input_begin,const T& input_end)
  • 然后在这里为特定的迭代器类型专门化你的通用总和。

标签: c++ templates


【解决方案1】:

错误其实挺清楚的,如下模板:

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 类型不能从调用位置的参数推导出来。这在标准中是这样定义的,如果您考虑一下(在一般情况下),这是有道理的。

考虑到你有sometemplate&lt;T&gt;::nested_type 而不是std::map&lt;&gt;::const_iterator,并且调用位置的参数是int。如果编译器必须推断类型,它必须为所有可能的类型 T 在 Universe(无限集)中实例化 sometemplate,并找出其中的嵌套类型 nested_typeint 的 typedef .

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


委托提取值

这是提供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 简单得多。

【讨论】:

  • 所有类型的集合远非无限,编译器可能有它们的列表。问题是每个像这样的“间接”都会将复杂性乘以类型的数量。
  • @Dani:一旦有了模板,类型集合无限的,只考虑基本类型int 和容器std::vector(忽略分配器类型),您可以拥有:intstd::vector&lt;int&gt;std::vector&lt;std::vector&lt;int&gt;&gt; ... 并且您可以嵌套任意数量的类型,从一个基本类型和一个模板中产生无限数量的类型。正如您所说,它还涉及复杂性的非线性增长,但即使是线性的也是难以处理的。
  • 我为向量和其他顺序容器编写的一般求和函数已经仅在迭代器上进行了模板化。只是为了处理我编写的重载版本的地图。 (我的通用函数): template double Sum(const T& input_begin,const T& input_end) @Jason:我已经将 sum 函数重写为一个普通的重载函数,没有模板。那是你的意思吗? double Sum(const std::map<:string>::const_iterator& input_begin,const std::map<:string>::const_iterator& input_end) 它工作正常。试图了解整个事情。
  • @CPlusPlus-Killing-me-softly:您可以使用 SFINAE 提供第二个函数,该函数仍然仅在迭代器上进行模板化,并且仅在迭代器是映射的迭代器时使用(或者至少通过启发式方法足够接近,例如value_typestd::pair&lt;T,U&gt;)
  • ... 或者您可以将获取值委托给第二个函数,您有一个模板(专业化),该函数采用std::pair&lt;&gt;
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-22
  • 1970-01-01
  • 2013-12-09
  • 1970-01-01
  • 2013-02-18
相关资源
最近更新 更多