在C++20中,是否可以通过非类型模板参数将类类型对象绑定到引用?

2w3rbyxf  于 9个月前  发布在  其他
关注(0)|答案(1)|浏览(114)

下面是一个例子:

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 .

ergxz8rk

ergxz8rk1#

您的代码是有效的。这可能是一个GCC错误。我已经提交了一个错误报告,请参阅**GCC Bug 113242 - g++ rejects-valid template argument of class type containing an lvalue reference**。
对于引用或指针类型的非类型 template-parameter,或者对于类类型或其子对象的非类型 template-parameter 中的引用或指针类型的每个非静态数据成员,引用或指针值不应引用或作为以下对象的地址:

  • 临时对象([class.temporary]),
  • 一个字符串文字对象([lex.string]),
  • typeid表达式([expr.typeid])的结果,
  • 预定义的__func__变量([dcl.fct.def.general]),或
  • 一个子对象([intro.object]),属于上述对象之一。
  • [临时参数非类型] p3
    引用auto&& X引用的对象wrapper X不属于这些类型,因此它应该是一个有效的模板参数。
    请注意,在main中发生的事情实际上是:
int main() {
    static int val = 22;       // OK, obviously
    constexpr int& ref = val;  // OK, can bind reference to static storage duration object
    constexpr wrapper w = ref; // OK, can create object containing such reference
    fun2<w>();                 // OK, but GCC errors in fun2's definition
}

字符串
还要注意,fun1<X>()中的unqualified-id Xconst wrapper([expr. expr.id.unqual] p2)类型的左值。因此,引用绑定是直接的,不涉及临时变量。

示例二

两个编译器都正确地拒绝

template <const wrapper& X>
void fun2() { /* ... */ }

int main() {
    static int val = 22;
    fun2<val>();
}


.因为fun2<val>()使X绑定到临时wrapper对象,该对象是在对fun2的函数调用中创建的。

相关问题