考虑一个简单的例子:
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();
}
尽管在模板模板参数声明中使用 auto
没有问题,[clang]似乎也处理了 decltype(auto)
占位符的想法 .
另一方面[gcc] - 不是很好:
prog.cc:6:13:错误:'x'的值在常量表达式中不可用
通常 - 根据标准预期哪种行为?或许一切皆有可能,而且代码格式不正确(这次我想不是,但不能明确地排除它)?
PS . 很抱歉再次破坏其中一个编译器;)
1 回答
这里的原始答案是
Foo<Bar>
形成不良,我现在认为它的结构良好 . 但最终,clang bug基于 .我实际上认为即使Foo <Bar>也是不正确的 . 遵循P0522的新规则是:
哪里:
这意味着要验证
Foo<Bar>
本身是否正常,我们合成:这里的所有类型都是有效的(因此最后一个语句在重载决策或选择类模板特化的上下文中都没有't apply). Now, typically when we do partial ordering it',在这种情况下我们要查找的是"more specialized"函数模板,其中
F
是more specialized thanG
如果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) >
- 我不确定它是否有效 .也就是说,我不确定这个案例是否已被考虑过 - 我没有看到任何措辞,并且值得提出一个问题 .