Search code examples
c++templatesparameterstemplate-argument-deduction

Why can't T be deduced from Template<T>::Type?


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

Solution

  • 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).