Olve Maudal的C++测验背后的解释(别名模板)

bug*_*nny 8 c++ alias gcc templates clang

以下代码来自http://www.pvv.org/~oma/PubQuiz_ACCU_Apr2014.pdf(#6,第34页的解决方案).目标是猜测以下输出.

#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;
}
Run Code Online (Sandbox Code Playgroud)

答案可以在第34页找到.我不理解别名模板的第二种情况,为什么选择主模板X<Z>而不是完全专业化.

正确答案应为"21",如本文所述.我的MinGW(gcc 5.1)打印"22",而http://ideone.com(使用gcc 4.9.2)也打印"22".来自MacOS X上的朋友的Clang打印"21".所以我猜这是gcc中的一个bug.

任何人都可以向我解释为什么打印"1" X<Z>并且标准gcc中的哪一段可能无法实现或尚未实现?

Dan*_*rey 4

我觉得是这样的

14.5.7 别名模板

1模板声明,其中声明别名声明(第 7 条),将标识符声明别名模板。别名模板是一系列类型的名称。别名模板的名称是template-name

上面的意思是YZ是不同的template-name,所以它们是不同的模板。可能会让您/编译器感到困惑的是,Y<T>并且Z<T>总是会产生相同的类型。

考虑:

#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" );
}
Run Code Online (Sandbox Code Playgroud)

实例

以上适用于 Clang,但不适用于 GCC。

编辑:正如 @TC 所指出的,有一个活跃的CWG 问题 1286,这表明 Clang 正在按照标准当前的规定进行操作,但没有按照预期进行。