【问题标题】:Overloading on valueness (rvalue/lvalue) of a function type [closed]重载函数类型的价值(右值/左值)[关闭]
【发布时间】:2015-06-29 22:21:41
【问题描述】:

是否可以调用一个对函数进行右值引用的函数?例如:

#include <iostream>    

void foo(void(&f)(int))
{
    std::cout << "A" << std::endl;
}

void foo(void(&&f)(int))
{
     std::cout << "B" << std::endl;
}

我可以调用打印“B”的foo 的重载吗?

【问题讨论】:

  • “那么这里:blahblahblah” 嗯,请问什么?你真的问过问题吗??你想究竟是什么?请详细说明,edit您的问题。这是一个披着Gimme teh codez plz的请求吗?
  • 你尝试了什么?您为什么不更加努力地编写所需的文本呢? (顺便说一句,函数指针的右值引用?)
  • void f(int); struct wrap{using T=void(&amp;&amp;)(int); operator T(){return f;}}; foo(wrap{})gcc 中工作,在clang 中失败。
  • @0x499602D2 这很有趣...我想知道为什么它在 gcc 中编译而不在 clang 中。
  • @rubix_addict 我认为 gcc clang 在这里是错误的。在 gcc 中,应该调用左值重载,因为即使它的返回类型是右值引用,运算符函数的结果也应该是左值。而且 clang 甚至没有尝试调用 wrap 的操作符函数(它应该这样做)。

标签: c++ c++11


【解决方案1】:

这是不可能的。

当您有两个这样的候选函数时,采用左值引用函数类型的重载总是优先于右值引用重载。函数在所有情况下都被视为左值,因此转换为左值引用是最强的。以下是一些标准措辞([over.ics.rank]/p3.2.4):

标准转换序列S1是比标准转换序列S2更好的转换序列如果

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

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

——结束示例]


我在此处提供的评论中的代码在 gcc 中调用了重载 #2,并被 clang 拒绝。

void foo(void(&)(int)); // #1
void foo(void(&&)(int)); // #2

void f(int);
struct wrap {
    using T = void(&&)(int);
    operator T() { return f; }
};

int main() {
    foo(wrap{}); // Calls #2 in gcc, error in clang
}

Clang 错误是:

void (int) 类型的非const 左值引用不能绑定到wrap 类型的临时对象

由于上面的引用,GCC 显然是错误的,但 Clang 也是错误的。运算符函数的结果是一个左值,因此它应该绑定到左值重载,但似乎 clang 没有尝试转换。一个更简单的例子是:

void (&r)(int) = wrap{}; // OK in gcc, error in clang

所以这看起来像是 Clang 和 GCC 中的一个错误。

【讨论】:

  • 我认为您没有正确阅读参考兼容性规则。 wrap{}.operator T() 是函数类型void (int) 的左值,用于初始化对void (int) 的左值引用。
  • MSVC(2013 和 2015 预发行版)编译您的示例并正确选择左值引用重载。 2013 年的 IntelliSense 不同意,但 2015 年的 IntelliSense 也接受代码。
  • 这是 GCC 中的错误吗?可以举报吗?
  • @T.C.我认为运算符函数调用的值类别是一个左值表达式,但它的 type 仍然是一个右值引用。由于其类型(右值引用)与参数(左值引用)不兼容,隐式转换失败。这不是正确的解释吗?
  • 不,表达式实际上没有引用类型。见 [expr]/p5。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多