What is wrong with the following piece of code?
#include
template
struct A {
struct X { K p; };
struct Y { K q; }
The argument K
in const typename A<K>::X
is not deducible. Basically, everything left of a ::
is not deducible (if ::
separates a nested-name).
It's trivial to see why it makes no sense to ask for deduction by running through this thought experiment:
struct A { typedef int type; }
struct B { typedef int type; }
template <typename T> void foo(typename T::type);
foo(5); // is T == A or T == B ??
There's no one-to-one mapping from types to nested types: Given any type (such as int
), there could be many ambient types of which it is a nested type, or there needn't be any.
Firstly, using ::
for referencing a nested struct is not correct. The right way is to use A<K>.x
, where x
is a member of type X<K>
. But for this to work, you need to declare two members x
, y
of type X<K>
and Y<K>
, respectively.
Secondly, I think that a good practice is to separate the template declarations of struct X
and struct Y
from the declaration of struct A in order to avoid the nested struct declaration.
In short, I would rewrite your code as followings:
template<class K>
struct X {
K p;
};
template<class K>
struct Y {
K q;
};
template<class K>
struct A {
X<K> x;
Y<K> y;
};
template<class K>
void foo(const X<K>& x, const Y<K>& y) {
std::cout << "A" << std::endl;
}
int main() {
A<float> a;
foo(a.x, a.y);
return 0;
}
template<typename K>
void foo(const typename A<K>::X& x, const typename A<K>::Y& y) {
std::cout << "A" << std::endl;
}
K
cannot been deduced, since it's in non-deduced
context.
n3337 14.8.2.5/4
In certain contexts, however, the value does not participate in type deduction, but instead uses the values of template arguments that were either deduced elsewhere or explicitly specified. If a template parameter is used only in non-deduced contexts and is not explicitly specified, template argument deduction fails.
n3337 14.8.2.5/5
The non-deduced contexts are:
— The nested-name-specifier of a type that was specified using a qualified-id.