Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Explanation behind C++ Quiz by Olve Maudal (alias template)

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?

like image 842
bugybunny Avatar asked May 14 '15 16:05

bugybunny


1 Answers

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.

like image 187
Daniel Frey Avatar answered Sep 19 '22 14:09

Daniel Frey