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

时间:2021-12-15 16:30:45

What is wrong in this code?

这段代码有什么问题?

#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 个解决方案

#1


80  

That is non-deducible context. That is why the template argument cannot be deduced by the compiler.

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

Just imagine if you might have specialized TMap as follows:

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

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

How would the compiler deduce the type SomeType, given that TMap<SomeType>::Type is std::map<double, double>? It cannot. It's not guaranteed that the type which you use in std::map is also the type in TMap. The compiler cannot make this dangerous assumption. There may not any relation between the type arguments, whatsoever.

鉴于TMap :: Type是std :: map ,编译器如何推导SomeType类型?这不可以。不能保证您在std :: map中使用的类型也是TMap中的类型。编译器无法做出这种危险的假设。类型参数之间可能没有任何关系。 ,double>

Also, you might have another specialization of TMap defined as:

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

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

This makes the situation even worse. Now you've the following:

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

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

  • TMap<OtherType>::Type = std::map<double, double>.
  • TMap :: Type = std :: map ,double>

Now ask yourself: given TMap<T>::Type is std::map<double, double>, how would the compiler know whether T is SomeType or OtherType? It cannot even know how many such choices it has, neither can it know the choices themselves...

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

I'm just asking you for the sake of thought-experiment (assuming it can know the complete set of choices).

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

#2


4  

Exactly what the compiler error message says: inTMap<T>::Type, T is not deduceable according to thestandard. The motivation for this is probably that it isn'ttechnically possible to implement: the compiler would have toinstantiate all possible TMap<T> in order to see if one (andonly one) matched the type you passed. And there is aninfinite number of TMap<T>.

正是编译器错误消息所说的:inTMap :: Type,T不能根据标准推断出来。这样做的动机可能是技术上不可能实现:编译器必须实例化所有可能的TMap ,以便查看一个(只有一个)是否与您传递的类型匹配。并且有无限数量的TMap

#3


2  

Even you have:

即使你有:

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

But before you call test(tmap)

但在你调用test(tmap)之前

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

You already have it declared as

你已经宣布它为

TMap<double>::Type tmap;

why this information can not be utilized. #typedef is not just simple string replacement.

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

#4


0  

I don't think "we can't do this" argument is correct.If we slightly modify this example, the compiler is happily deducing arguments for us.

我不认为“我们不能这样做”这个论点是正确的。如果我们稍微修改这个例子,编译器很乐意为我们推断出参数。

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.

I don't see a huge difference between the original example and mine. The real issue here seems that C++ treats typedefs and type declarations differently

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

Is this a good thing?

这是一件好事吗?

#1


80  

That is non-deducible context. That is why the template argument cannot be deduced by the compiler.

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

Just imagine if you might have specialized TMap as follows:

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

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

How would the compiler deduce the type SomeType, given that TMap<SomeType>::Type is std::map<double, double>? It cannot. It's not guaranteed that the type which you use in std::map is also the type in TMap. The compiler cannot make this dangerous assumption. There may not any relation between the type arguments, whatsoever.

鉴于TMap :: Type是std :: map ,编译器如何推导SomeType类型?这不可以。不能保证您在std :: map中使用的类型也是TMap中的类型。编译器无法做出这种危险的假设。类型参数之间可能没有任何关系。 ,double>

Also, you might have another specialization of TMap defined as:

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

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

This makes the situation even worse. Now you've the following:

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

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

  • TMap<OtherType>::Type = std::map<double, double>.
  • TMap :: Type = std :: map ,double>

Now ask yourself: given TMap<T>::Type is std::map<double, double>, how would the compiler know whether T is SomeType or OtherType? It cannot even know how many such choices it has, neither can it know the choices themselves...

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

I'm just asking you for the sake of thought-experiment (assuming it can know the complete set of choices).

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

#2


4  

Exactly what the compiler error message says: inTMap<T>::Type, T is not deduceable according to thestandard. The motivation for this is probably that it isn'ttechnically possible to implement: the compiler would have toinstantiate all possible TMap<T> in order to see if one (andonly one) matched the type you passed. And there is aninfinite number of TMap<T>.

正是编译器错误消息所说的:inTMap :: Type,T不能根据标准推断出来。这样做的动机可能是技术上不可能实现:编译器必须实例化所有可能的TMap ,以便查看一个(只有一个)是否与您传递的类型匹配。并且有无限数量的TMap

#3


2  

Even you have:

即使你有:

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

But before you call test(tmap)

但在你调用test(tmap)之前

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

You already have it declared as

你已经宣布它为

TMap<double>::Type tmap;

why this information can not be utilized. #typedef is not just simple string replacement.

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

#4


0  

I don't think "we can't do this" argument is correct.If we slightly modify this example, the compiler is happily deducing arguments for us.

我不认为“我们不能这样做”这个论点是正确的。如果我们稍微修改这个例子,编译器很乐意为我们推断出参数。

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.

I don't see a huge difference between the original example and mine. The real issue here seems that C++ treats typedefs and type declarations differently

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

Is this a good thing?

这是一件好事吗?