Explanation behind C++ Quiz by Olve Maudal (alias

2019-04-22 20:38发布

问题:

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?

回答1:

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.