为什么在将模板参数用作另一个模板的模板参数时,不能推导出模板参数?

时间:2011-05-19 15:11:32

标签: c++ templates parameters

此代码有什么问题?

#include <map>

template<typename T>
struct TMap
{
    typedef std::map<T, T> Type;
};

template<typename T>
T test(typename TMap <T>::Type &tmap_) { return 0.0; }

int _tmain(int argc, _TCHAR* argv[])
{
    TMap<double>::Type tmap;
    tmap[1.1] = 5.2;
    double d = test(tmap); //Error: could not deduce template argument for T
    return 0;
}

4 个答案:

答案 0 :(得分:82)

这是不可扣除的背景。这就是编译器无法推断出模板参数的原因。

想象一下,如果你有专门的TMap如下:

template <>
struct TMap<SomeType>
{
    typedef std::map <double, double> Type;
};

鉴于SomeTypeTMap<SomeType>::Type,编译器如何推断出std::map<double, double>类型?这不可以。 保证std::map中使用的类型 <{>> <{>> 1}}。编译器无法做出这种危险的假设。 type 参数之间可能没有任何关系。

此外,您可能还有TMap的另一个专门化定义为:

TMap

这使情况更糟。现在你有了以下内容:

  • template <> struct TMap<OtherType> { typedef std::map <double, double> Type; }; = TMap<SomeType>::Type
  • std::map<double, double> = TMap<OtherType>::Type

现在问问自己:鉴于std::map<double, double>TMap<T>::Type,编译器如何知道std::map<double, double>T还是SomeType?它甚至不知道它有多少这样的选择,也不知道选择本身......

我只是为了思考实验而问你(假设它可以知道完整的选择)。

答案 1 :(得分:4)

编译器错误消息的确切内容:in 根据{{​​1}} TMap<T>::TypeT不可推断 标准。这可能是因为它不是 技术上可以实现:编译器必须 实例化所有可能的TMap<T>以查看是否({和} 只有一个)与您传递的类型相匹配。还有一个 无限数量的TMap<T>

答案 2 :(得分:2)

即使你有:

TMap<SomeType>::Type = std::map<double, double>. 

但在你调用test(tmap)之前

TMap<double>::Type tmap;
tmap[1.1] = 5.2;
double d = test(tmap); 

您已将其声明为

TMap<double>::Type tmap;

为什么无法利用这些信息。 #typedef不仅仅是简单的字符串替换。

答案 3 :(得分:0)

我不会想到&#34;我们无法做到这一点&#34;论证是正确的。 如果我们稍微修改这个例子,编译器很乐意为我们推断出参数。

template<typename T>
struct TMap //...

template <class T>
struct tmap_t : TMap<T>::Type {};

template<typename T>
T test(tmap_t<T> tmap) // ...

tmap_t<double> tmap;  // ...
double d = test(tmap);  // compiles just fine.

我没有看到原始示例与我的示例之间存在巨大差异。这里的真正问题似乎是C ++以不同的方式处理typedef和类型声明

这是件好事吗?