【问题标题】:Can an rvalue reference bind to a function?右值引用可以绑定到函数吗?
【发布时间】:2013-03-13 11:03:22
【问题描述】:

我用 GCC、Clang、ICC 和 VS 测试了以下代码:

void f() {}
  
void g(void (&&)()) { }

int main() {
    g(f);
}

正如我们所见,g 采用右值引用,但 f 是左值,通常,右值引用不能绑定到左值。这正是 ICC 抱怨的原因:

error: an rvalue reference cannot be bound to an lvalue

VS 也会报错,但还有一个原因:

error C2664: 'void h(void (__cdecl &&)(void))' : cannot convert parameter 1 from 'void (__cdecl *)(void)' to 'void (__cdecl &&)(void)'

这表明 VS 会立即执行函数到指针的转换,而不是直接将引用绑定到 f。值得一提的是,如果我将g(f) 替换为g(&f),那么四个编译器会产生同样的错误。

最后,GCC 和 Clang 接受了代码,我相信他们是正确的。我的推理是基于 8.5.3/5

对“cv1 T1”类型的引用由“cv2 T2”类型的表达式初始化为

——如果引用是左值引用 [...]

— 否则,[...] 引用应为右值引用

     - 如果初始化表达式是一个 [...] 函数左值 [...]

     然后引用绑定到初始化表达式的值 [...]

我的解释是否正确(即 Clang 和 GCC 因给定原因而合规)?

【问题讨论】:

    标签: c++ function c++11 language-lawyer rvalue-reference


    【解决方案1】:

    我的解释正确吗[...]?

    是的。

    由于您引用的标准段落,您的解释是正确的。第 13.3.3.1.4/3 段关于引用绑定的进一步确认:

    除了隐式对象参数,参见 13.3.1,标准转换序列不能 如果它需要将一个左值引用而不是对非易失性 const 类型的引用绑定到 一个右值或将一个右值引用绑定到一个左值而不是一个函数左值。 [...]

    第 13.3.3.2/3 段包含进一步(间接)确认:

    [...] 标准转换序列 S1 是比标准转换序列 S2 更好的转换序列 if

    ——[...]

    — S1 和 S2 是引用绑定 (8.5.3),S1 将左值引用绑定到函数左值,S2 将右值引用绑定到函数左值。 [例子

    int f(void(&)()); // #1
    int f(void(&&)()); // #2
    void g();
    int i1 = f(g); // calls #1
    

    结束示例 ]

    【讨论】:

    • 确实如此。我之前测试过,所有四个编译器都是兼容的。
    猜你喜欢
    • 1970-01-01
    • 2022-11-30
    • 2022-06-12
    • 2014-03-29
    • 2014-01-02
    • 1970-01-01
    • 1970-01-01
    • 2014-10-31
    相关资源
    最近更新 更多