一个右值引用绑定到一个函数? [英] Can an rvalue reference bind to a function?

查看:368
本文介绍了一个右值引用绑定到一个函数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

  void f(){} 

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

int main(){
g(f);
}

正如我们所看到的, g 采用右值引用,但 f 是一个左值,一般来说,右值引用不能绑定到左值。这正是ICC抱怨的

 错误:右值引用不能绑定到左值

VS也会发生错误,但是出于其他原因:

 错误C2664:'void h(void(__cdecl&&)(void))'无法将参数1从'void(__cdecl * )(void)'to'void(__cdecl&&)(void)'

对我来说VS正在立即执行一个函数到指针的转换,而不是直接绑定到 f 的引用。值得一提的是,如果我用 g(& f)替换 g(f),那么四个编译器非常相同的错误。



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


对类型cv1 T1的引用由类型cv2 T2 as



- 如果引用是一个左值引用[...] ..] 引用应为右值引用



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



   那么引用绑定到初始化器表达式的值 [...]


解决方案


是我的解释正确[...]。


$ b

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


除了隐式对象参数,参见13.3 .1,如果需要将除了对非易失性const类型的引用之外的其他lvalue引用绑定到
an rvalue 或者将右值引用绑定到左值,标准转换序列不能为
函数lvalue
之外的 [...]


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



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



[...]



- S1和S2是参考绑定(8.5.3),S1绑定一个左值引用到函数左值,S2绑定右值引用函数lvalue 。 [示例

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

- end example ] b $ b


I tested the following code with GCC, Clang, ICC and VS:

void f() {}

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

int main() {
    g(f);
}

As we can see, g takes an rvalue reference but f is an lvalue and, in general, rvalue references cannot be bound to lvalues. That's exactly what ICC complains about:

error: an rvalue reference cannot be bound to an lvalue

VS also gives an error but for another reason:

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

This suggests to me that VS is immediately performing a function-to-pointer conversion rather than directly bind the reference to f. It's worth mentioning that if I replace g(f) with g(&f) then the four compilers yield this very same error.

Finally, GCC and Clang accept the code and I believe they are correct. My reasoning is based on 8.5.3/5

A reference to type "cv1 T1" is initialized by an expression of type "cv2 T2" as

— If the reference is an lvalue reference [...]

— Otherwise, [...] the reference shall be an rvalue reference.

     — If the initializer expression is a [...] function lvalue [...]

     then the reference is bound to the value of the initializer expression [...]

Is my interpretation correct (that is, Clang and GCC are compliant for the given reason)?

解决方案

Is my interpretation correct [...]?

Yes.

Your interpretation is correct because of the Paragraph of the Standard that you quoted. A further confirmation comes from Paragraph 13.3.3.1.4/3 on reference binding:

Except for an implicit object parameter, for which see 13.3.1, a standard conversion sequence cannot be formed if it requires binding an lvalue reference other than a reference to a non-volatile const type to an rvalue or binding an rvalue reference to an lvalue other than a function lvalue. [...]

Paragraph 13.3.3.2/3 contains a further (indirect) confirmation:

[...] Standard conversion sequence S1 is a better conversion sequence than standard conversion sequence S2 if

— [...]

— S1 and S2 are reference bindings (8.5.3) and S1 binds an lvalue reference to a function lvalue and S2 binds an rvalue reference to a function lvalue. [ Example:

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

end example ]

这篇关于一个右值引用绑定到一个函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆