非类型模板参数的占位符类型在模板模板参数的情况下是否可以互换

Are placeholders types of non-type template parameters interchangeable in case of template template parameter

本文关键字:参数 类型 互换 是否 占位符 情况下      更新时间:2023-10-16

考虑一个简单的例子:

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();
}

[clang] 似乎处理了decltype(auto)占位符的想法,尽管在模板模板参数声明中使用了auto没有问题。

[GCC] 另一方面 - 不是很好:

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


像往常一样 - 根据标准,哪些行为是预期的?或者也许一切皆有可能并且代码格式不正确(这次我想不是,但不能明确排除)?

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

这里的原始答案Foo<Bar>格式不正确,我现在实际上认为它的格式很好。但最终,基于叮当错误。


我实际上认为即使是Foo<Bar>也是格式错误的。遵循P0522的新规则是:

当模板参数至少与模板参数

A一样专业时,模板参数PP模板参数匹配

哪里:

模板模板参数P至少与模板模板参数

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

  • 两个函数模板中的每一个都具有相同的模板参数,分别为PA
  • 每个函数模板都有一个函数参数,其类型是X的专用化,模板参数对应于相应函数模板中的模板参数,其中,对于函数模板的模板参数列表中的每个模板参数PP,形成相应的模板参数AA。如果PP声明了一个参数包,则AA是包扩展PP...([temp.variadic]);否则,AAid 表达式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

此处的所有类型都是有效的(因此最后一个语句不适用)。现在,通常当我们进行部分排序时,它是在重载解析或选择类模板专用化的上下文中,在这种情况下,我们正在寻找的是"更专业"的函数模板,其中FG更专业,如果F至少与G一样专业,而G至少不像F那样专业。

但在这种情况下,我们不关心哪个更专业。我们只需要P至少像A一样专业.所有这些都意味着演绎必须从A成功到P。那么如果我们合成一些具有一些值V的独特类型U,我们可以从X<V>中推断出X<I>吗?是的。因此,P至少和A一样专业,所以模板参数Bar与模板参数TT匹配。


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

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