下面是一个例子:
struct wrapper {
int& ref;
constexpr wrapper(int& ref) : ref(ref) {}
};
template <auto&& X>
void fun1() {}
template <wrapper X>
void fun2() {
fun1<X>();
}
int main() {
static int val = 22;
fun2<val>();
}
字符串fun2<X>()
接受一个类作为非类型模板参数,而fun1<X>()
接受一个对传递给它的任何对象的转发引用。
上面的fails to compile in GCC with the error shown below but compiles just fine in Clang。
<source>:11:12: error: the address of 'wrapper{val}' is not a valid template argument
11 | fun1<X>();
| ~~~~~~~^~
型
这里哪个编译器是正确的?这应该是两个编译器中的一个错误吗?
我试图改变template <wrapper X>
到template <const wrapper& X>
,但无济于事,因为它fails on both GCC and Clang .
1条答案
按热度按时间ergxz8rk1#
您的代码是有效的。这可能是一个GCC错误。我已经提交了一个错误报告,请参阅**GCC Bug 113242 - g++ rejects-valid template argument of class type containing an lvalue reference**。
对于引用或指针类型的非类型 template-parameter,或者对于类类型或其子对象的非类型 template-parameter 中的引用或指针类型的每个非静态数据成员,引用或指针值不应引用或作为以下对象的地址:
typeid
表达式([expr.typeid])的结果,__func__
变量([dcl.fct.def.general]),或引用
auto&& X
引用的对象wrapper X
不属于这些类型,因此它应该是一个有效的模板参数。请注意,在
main
中发生的事情实际上是:字符串
还要注意,
fun1<X>()
中的unqualified-idX
是const wrapper
([expr. expr.id.unqual] p2)类型的左值。因此,引用绑定是直接的,不涉及临时变量。示例二
两个编译器都正确地拒绝
型
.因为
fun2<val>()
使X
绑定到临时wrapper
对象,该对象是在对fun2
的函数调用中创建的。