在模板模板参数

时间:2017-09-19 20:25:28

标签: c++ templates language-lawyer c++17

考虑一个简单的例子:

int x;

template <template <auto> class TT>
struct Foo {
   void foo() {
      TT<(x)> tt;
      static_cast<void>(tt);
   }
};

template <decltype(auto)>
struct Bar { };


int main() {
    Foo<Bar> foobar;
    foobar.foo();
}
尽管在模板模板参数声明中使用decltype(auto)没有问题,

[clang]似乎也处理了auto占位符的概念。

另一方面,

[gcc] - 不太好:

  

prog.cc:6:13:错误:'x'的值在常量表达式中不可用

通常 - 根据标准预期哪种行为?或许一切皆有可能,而且代码格式不正确(这次我想不是,但不能明确地排除它)?

PS。很抱歉再次破坏其中一个编译器;)

1 个答案:

答案 0 :(得分:7)

这里的原始答案Foo<Bar>格式不正确,我现在认为它的格式正确。但最终,基于clang bug。

我实际上认为即使Foo<Bar>格式不正确。 P0522之后的新规则是:

  当P至少与模板一样专业时, template-argument 匹配模板 template-parameter P参数 A

其中:

  

模板 template-parameter P至少与模板 template-argument A一样专业,如果给出以下重写根据函数模板的部分排序规则([temp.func.order]),两个函数模板,对应P的函数模板至少与对应A的函数模板一样专用。给定一个发明的类模板X,其模板参数列表为A(包括默认参数):

     
      
  • 两个功能模板中的每一个分别具有相同的模板参数PA
  •   
  • 每个函数模板都有一个函数参数,其类型是X的特化,其模板参数对应于各个函数模板中的模板参数,其中,模板参数中的每个模板参数PP在功能模板的列表中,形成了相应的模板参数AA。如果PP声明参数包,则AA是包扩展PP...([temp.variadic]);否则,AA id-expression PP
  •   
     

如果重写产生无效类型,则P至少不如A那么专业。

这意味着要验证Foo<Bar>本身是否合适,我们合成:

template <decltype(auto) I> struct X;

template <auto I>           void __f(X<I> ); // P
template <decltype(auto) I> void __f(X<I> ); // A

此处的所有类型均有效(因此最后一条语句不适用)。现在,通常当我们进行部分排序时,它是在重载决策或选择类模板特化的上下文中,在这种情况下,我们正在寻找的是"more specialized"函数模板,其中F是{ {3}} G如果F至少与G一样专业,而G至少与F一样专业。

但在这种情况下,我们并不关心哪种更专业。我们只需要P至少与A一样专业。这意味着扣除必须从AP成功。因此,如果我们合成一些具有某些值U的唯一类型V,我们是否可以从X<I>中推导出X<V>?是。因此,P至少与A一样专业,因此模板参数Bar与模板参数TT匹配。

现在,通过这一点,我会说这是一个铿锵的错误。模板 template-parameter template <auto>,这是我们应该用来验证表达式的。对于非类型模板参数auto,我们尝试使用x作为值 - 但x不是有效的常量表达式,因此这应该失败。 clang似乎直接使用template <decltype(auto) > - 我不确定是否有效。

那就是说,我不确定这个案子是否已被考虑过 - 我没有看到任何措辞,并且值得提出一个问题。