Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't the template argument be deduced when it is used as template parameter to another template?

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; } 
like image 655
Johnas Avatar asked May 19 '11 15:05

Johnas


People also ask

Can a template be a template parameter?

A template argument for a template template parameter is the name of a class template. When the compiler tries to find a template to match the template template argument, it only considers primary class templates. (A primary template is the template that is being specialized.)

What is template argument deduction?

Template argument deduction is used when selecting user-defined conversion function template arguments. A is the type that is required as the result of the conversion. P is the return type of the conversion function template.

Why do we use template template parameter?

Why we use :: template-template parameter? Explanation: It is used to adapt a policy into binary ones.

CAN default arguments be used with the template?

You cannot give default arguments to the same template parameters in different declarations in the same scope. The compiler will not allow the following example: template<class T = char> class X; template<class T = char> class X { };


2 Answers

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:

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.

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

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<OtherType>::Type = std::map<double, 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...

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

like image 58
Nawaz Avatar answered Sep 20 '22 17:09

Nawaz


Exactly what the compiler error message says: in TMap<T>::Type, T is not deduceable according to the standard. The motivation for this is probably that it isn't technically possible to implement: the compiler would have to instantiate all possible TMap<T> in order to see if one (and only one) matched the type you passed. And there is an infinite number of TMap<T>.

like image 25
James Kanze Avatar answered Sep 18 '22 17:09

James Kanze