Why can't a template argument be output if it is used as a template parameter for another template?

What is wrong with 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; } 
+49
c ++ parameters templates
May 19 '11 at
source share
4 answers

This is not a deduced context. This is why the template argument cannot be deduced by the compiler.

Just imagine if you had a specialized TMap as follows:

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

How would the compiler SomeType type, given that TMap<SomeType>::Type is std::map<double, double> ? It can't. It does not guarantee that the type you use in std::map is also a TMap type. The compiler cannot make this dangerous assumption. There can be no connection between type arguments.

In addition, you may have another TMap specialization defined as:

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

This makes the situation worse. Now you have 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 does the compiler know if there is T SomeType or OtherType ? He cannot even know how many such options he has, and he cannot know the choice itself ...

I just ask you for the sake of a thought experiment (assuming that he can know the full range of options).

+77
May 19 '11 at 15:15
source share

Exactly what the compiler error message reports: TMap<T>::Type , T not output according to the standard. The motivation for this is probably that it is not technically feasible to implement: the compiler will have to create all possible TMap<T> to see if one (and only one) matches the type that you passed. And there is an infinite number of TMap<T> .

+4
May 19, '11 at 15:17
source share

Even you have:

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

But before you call the test (tmap)

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

You already declared it as

 TMap<double>::Type tmap; 

why this information cannot be used. #typedef is not just a string replacement.

+2
Dec 29 '15 at 2:42 on
source share

I do not think that β€œwe cannot do this” argument is correct. If we change this example a bit, the compiler will happily output the 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 do not see a huge difference between the original example and mine. The real issue here seems to be that C ++ handles typedefs and type declarations differently

This is a good thing?

0
Aug 05 '17 at 15:58
source share



All Articles