The following code is from http://www.pvv.org/~oma/PubQuiz_ACCU_Apr2014.pdf (#6, solution on page 34). The goal was to guess the output for the following.
#include <iostream>
template <template <typename> class>
struct X {
X() { std::cout << "1"; }
};
template<typename >
struct Y {};
template<typename T>
using Z = Y<T>;
template<>
struct X<Y> {
X() { std::cout << "2"; }
};
int main() {
X<Y> x1;
X<Z> x2;
}
The answer can be found on page 34. I don’t understand the second case with the alias template, why the primary template is chosen for X<Z>
instead of the fully specialized.
The correct answer should be "21" as written in the presentaton. My MinGW (gcc 5.1) prints "22" and http://ideone.com (which uses gcc 4.9.2) also prints "22". Clang from a friend on MacOS X prints "21". So I guess this is a bug in gcc.
Can anyone explain to me why "1" is printed for the X<Z>
and what paragraph from the standard gcc might failed to implement or not yet implemented?
I think it is
14.5.7 Alias templates
1 A template-declaration in which the declaration is an alias-declaration (Clause 7) declares the identifier to be a alias template. An alias template is a name for a family of types. The name of the alias template is a template-name.
The above means that Y
and Z
are different template-names, so they are different templates. What might confuse you/the compiler is that Y<T>
and Z<T>
will always yield an identical type.
Consider:
#include <type_traits>
template <typename>
struct W {};
template <template <typename> class>
struct X {};
template<typename>
struct Y {};
template<typename T>
using Z = Y<T>;
int main()
{
static_assert( std::is_same< Y<int>, Z<int> >::value, "Oops" );
static_assert( std::is_same< W<Y<int>>, W<Z<int>> >::value, "Oops" );
static_assert( ! std::is_same< X<Y>, X<Z> >::value, "Oops" );
}
Live example
The above works for Clang, but not for GCC.
EDIT: As pointed out by @T.C. there is an active CWG issue 1286 which suggests that Clang is doing what the standard currently says, but not what was intended.