模板模板部分专业化仅适用于 -std=c++1z 和 g++

Template template partial specialization only working with -std=c++1z with g++

我发现了下面这段代码:

#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;
}

仅在使用 g++-7-std=c++1z 编译时打印 correctg++clang++ 或其他 std 标志的其他版本无法生成正确的。

这是当前实现的错误吗,这段代码不应打印任何内容,或者是 C++17 中的某些更改使这段代码按我预期的方式工作?

这是在 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 正在做正确的事。