为什么当模板参数被用作另一个模板的模板参数时,不能推导出模板参数?
这个代码有什么错?
#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>::Type
是std::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>::Type
是std::map<double, double>
,编译器如何知道T
是SomeType
还是OtherType
? 它甚至不知道它有多少这样的选择,也不知道自己的选择 …
我只是为了思考实验而问你(假设它可以知道整套的选择 )。
编译器错误消息说的是什么:在TMap<T>::Type
, T
不能按照标准进行推导。 这样做的动机可能是在技术上不可能实现:编译器将不得不实例化所有可能的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声明
这是一件好事吗?