另一个decltype(auto)
模板模板参数问题。这次我能够创建的最小代码重现错误如下:
template <template <decltype(auto)> class TT, decltype(auto) V>
void foo(TT<V>) {
};
template <decltype(auto)>
struct Bar{};
int x;
int main() {
foo(Bar<(x)>{});
}
[clang]中的结果为:
prog.cc:11:5: error: no matching function for call to 'foo'
foo(Bar<(x)>{});
^~~
prog.cc:2:6: note: candidate template ignored: substitution failure [with TT = Bar]: non-type template argument is not a constant expression
void foo(TT<V>) {
^
1 error generated.
[gcc]接受代码。
根据我的理解,代码格式正确,并且clang在解释方面存在错误,但在向lvvm提交错误之前需要确认。我是对的吗?
答案 0 :(得分:1)
根据错误,clang对于推导模板模板参数没有问题,该模板也符合标准 - [temp.arg.template]/3(empasis mine):
当P为时,模板参数与模板模板参数P匹配 至少与模板参数A 一样专业。如果P包含a 参数包,然后A也匹配P,如果每个A的模板 参数匹配相应的模板参数 P.的模板参数列表两个模板参数匹配 对于非类型,属于同一类型(类型,非类型,模板) 模板参数,它们的类型是等价的([temp.over.link]), 并且对于模板模板参数,它们各自对应 模板参数以递归方式匹配。当P的时候 template-parameter-list包含一个模板参数包 模板参数包将匹配零个或多个模板参数或 模板参数包在A的template-parameter-list中 与P中的模板参数包相同的类型和形式(忽略 这些模板参数是否为模板参数包)
现在让我们确保推导出Bar<(x)>{}
作为参考。这由[dcl.type.auto.deduct]/5和[dcl.type.simple]/4涵盖。
最后让我们检查一下我们是否真的可以使用带有链接的变量的引用作为模板参数[temp.arg.nontype]/2:
非类型模板参数的模板参数应为a 转换模板参数类型的常量表达式。 对于引用或指针类型的非类型模板参数, 常量表达式的值不应引用(或指针 类型,不得是地址:
- 子对象
- 临时对象,
- 字符串文字,
- typeid表达式的结果,或
- 预定义的 func__变量。
[注意:如果template-argument表示一组重载 函数(或指向此类的指针或成员指针),匹配 从集合中选择函数([over.over])。 - 结束说明]
推断出的论证符合要求。这使代码格式良好,并提出了clang的错误。