模板模板部分特化仅与-std = c ++ 1z一起使用g ++

时间:2017-06-23 17:12:42

标签: c++ templates g++ c++17 clang++

我发现以下一段代码:

#include <iostream>
#include <vector>

template <typename T>
struct X : std::false_type {};

template <template <typename> class Y, typename U>
struct X<Y<U>> : std::true_type {};

int main() {
  if (X<int>())
    std::cout << "wrong\n";

  if (X<std::vector<double>>())
    std::cout << "correct\n";

  return 0;
}

仅在correctg++-7一起编译时才打印-std=c++1z。其他版本的g++clang++或其他std标记无法生成正确的内容。

这是当前实现的错误,并且此代码不应该打印任何内容,或者是否在C ++ 17中发生了变化,这使得此代码按预期工作?

1 个答案:

答案 0 :(得分:10)

这是在C ++ 17中采用P0522的结果,其动机来自以下示例:

template <template <int> class> void FI();
template <template <auto> class> void FA();
template <auto> struct SA { /* ... */ };
template <int> struct SI { /* ... */ };
FI<SA>();  // OK; error before this paper
FA<SI>();  // error

template <template <typename> class> void FD();
template <typename, typename = int> struct SD { /* ... */ };
FD<SD>();  // OK; error before this paper (CWG 150)

以前,[temp.arg.template]中的措辞要求模板模板参数完全匹配。所以给出:

template <template <class > class P> class X;

template <class T> class A;
template <class T, class U=T> class B;
template <class... > class C;

X<A>显然没问题,但是X<B>格式不正确,因为B需要两个模板参数(无论是否有一个默认!)而且X<C>格式不正确因为P需要一个模板参数而C需要一个包(即使您只能使用一个参数形成C!)

如果模板模板参数至少与参数一样专用,那么新措辞就会放松匹配的想法。这使X<B>X<C>都有效。

因此,在C ++ 17中,X<std::vector<double>>应该选择专门化。但在C ++ 17之前,它应该选择主要的。 gcc正在做正确的事。