Search code examples
c++templatesc++11template-aliases

How do template aliases affect template parameter deduction?


In C++03, template parameter deduction does not occur in some contexts. For example:

template <typename T> struct B {};

template <typename T>
struct A
{
    typedef B<T> type;
};

template <typename T>
void f(typename A<T>::type);

int main()
{
    B<int> b;
    f(b);  // ERROR: no match
}

Here, int is not deduced for T, because a nested type such as A<T>::type is a non-deduced context.

Had I written the function like this:

template <typename T> struct B {};

template <typename T>
void f(B<T>);

int main()
{
    B<int> b;
    f(b);
}

everything is fine because B<T> is a deduced context.

In C++11, however, template aliases can be used to disguise a nested type in syntax similar to the second example. For example:

template <typename T> struct B {};

template <typename T>
struct A
{
    typedef B<T> type;
};

template <typename T>
using C = typename A<T>::type;

template <typename T>
void f(C<T>);

int main()
{
    B<int> b;
    f(b);
}

Would template argument deduction work in this case? In other words, are template aliases a deduced context or a non-deduced context? Or do they inherit the deduced/non-deduced status of whatever they alias?


Solution

  • In other words, are template aliases a deduced context or a non-deduced context?

    They are as deducible as the equivalent code without using template aliases. For example

    template<typename T>
    using ref = T&;
    
    template<typename T>
    void f(ref<T> r);
    

    Now you can call f(x) and T will be deduced perfectly fine. At the definition time of f already, ref<T> is replaced by type T&. And T& is a deduced context.

    In your case C<T> is replaced by typename A<T>::type, and that is a non-deduced context for T, so T cannot be deduced.