I finally found a really nice example explaining the problem.

I'd like to summarize the main points. Assume the existence of the following metafunction:

template<typename T>  
struct map_of {  
    using type = std::map<T, T>;
};

The following function seems therefore reasonable:

template<typename U>  
U f(typename map_of<U>::type const& m) {  
    return U();
}

Unfortunately, this will not compile. To understand this, consider the following specialization:

template<>  
struct map_of<int> {  
    using type = std::map<double, double>;
};

Now:

How could the compiler understand that U in f<U>() should be substitued with int givent that map_of<int>::type is std::map<double, double>?

Simply, it cannot. This is even more evident if I define a second specialization:

template<>  
struct map_of<char> {  
    using type = std::map<double, double>;
};

At this point, we have a one-to-many relationship between std::map<double, double> and map_of<char> and map_of<int>.

In the same post, @kerrek-sb summarizes the issue as follows:

This is essentially an inverse-function problem. Given an output value, you're asking for the input point at which your function takes that value. However, functions aren't invertible in general, so the question doesn't even exist unless you require your function to be an invertible one.

In the template scenario, the corresponding requirement would be that all templates have globally unique member names; a requirement that C++ does not make.