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

这个代码有什么错?

#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; } 

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

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

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

如果TMap<SomeType>::Typestd::map<double, double> ,编译器会如何推导出SomeType TMap<SomeType>::Type ? 这不可以。 不能保证在std::map使用的类型也是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>::Typestd::map<double, double> ,编译器如何知道TSomeType还是OtherType ? 它甚至不知道它有多少这样的选择,也不知道自己的选择

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

编译器错误消息说的是什么:在TMap<T>::TypeT不能按照标准进行推导。 这样做的动机可能是在技术上不可能实现:编译器将不得不实例化所有可能的TMap<T> ,以便查看是否有一个(并且只有一个)匹配您传递的类型。 并且有无数的TMap<T>

即使你有:

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

但是在你打电话测试之前(tmap)

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

你已经声明为

 TMap<double>::Type tmap; 

为什么这个信息不能被利用。 #typedef不只是简单的字符串替换。

我不认为“我们做不到”这个说法是正确的。 如果我们稍微修改一下这个例子,编译器会很高兴地为我们推理。

 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和type声明

这是一件好事吗?