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?
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.
Imagine this:
template <typename T> struct Foo { typedef T type; }
template <> struct Foo<char> { typedef int type; }
template <typename T> using mytype = typename Foo<T>::type;
template <typename T> void f(mytype<T>);
Now if I want int n; f(n);
, how could I decide whether I want T = int
or T = char
? The whole problem, which is unaffected by template aliases, is that you cannot deduce backwards to all the things that could possibly define something.
I think the relevant quote in the C++ standard is 14.5.7 [temp.alias] paragraph 2:
When a template-id refers to the specialization of an alias template, it is equivalent to the associated type obtained by substitution of its template-arguments for the template-parameters in the type-id of the alias template. [ Note: An alias template name is never deduced. — end note ]
There is an example following the quote which effectively spells out that it is pointless to use an alias template in a function template and hoping to deduce the template argument. This apparently applies even for situation which don't involve nested types.
来源:https://stackoverflow.com/questions/8775202/how-do-template-aliases-affect-template-parameter-deduction