【问题标题】:Template template partial specialization only working with -std=c++1z with g++模板模板部分特化仅适用于 -std=c++1z 和 g++
【发布时间】:2017-06-23 17:12:42
【问题描述】:

我发现下面这段代码:

#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 编译时打印correct。其他版本的g++clang++ 或其他std 标志无法正确生成。

这是当前实现的一个错误,并且这段代码不应该打印任何东西,还是在 C++17 中发生了一些变化,使得这段代码可以按我的预期工作?

【问题讨论】:

  • 有趣的事实:如果你让Y 接受可变数量的参数,它将在-std=c++1z 上为clang 打印correct 而在-std=c++17 上为gcc 打印任何内容:)
  • 仍然在此处打印correctg++-7..

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


【解决方案1】:

这是在 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&lt;A&gt; 显然没问题,但 X&lt;B&gt; 格式不正确,因为 B 采用两个模板参数(不管是否默认!),X&lt;C&gt; 格式不正确,因为 P 需要一个模板参数并且C 需要一个包(即使你可以只用一个参数形成一个C!)

新的措辞将匹配的概念放宽到更有意义的概念 - 如果模板模板参数至少与参数一样专用。这使得X&lt;B&gt;X&lt;C&gt; 都可以工作。

因此,在 C++17 中,X&lt;std::vector&lt;double&gt;&gt; 应该选择专业化。但在 C++17 之前,它应该选择主要的。 gcc 正在做正确的事情。

【讨论】:

  • 看一眼那篇论文,就好像它是关于非类型模板参数的,但这里不是这种情况。您能否更具体/更详细地说明这在这种情况下的相关性?
  • @xaxxon 再看一眼?它根本不是关于非类型模板参数 - 它是关于模板模板。 FD&lt;SD&gt;() 的例子正是 OP 正在做的事情。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-06-13
  • 1970-01-01
  • 2012-11-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多