【问题标题】:How do I differentiate an lvalue and rvalue member function pointer for overloaded functions?如何区分重载函数的左值和右值成员函数指针?
【发布时间】:2015-04-18 16:39:30
【问题描述】:

我知道我可以这样做来区分右值函数名称和左值函数指针:

template <typename RET_TYPE, typename...ARGs>
void takeFunction(RET_TYPE(& function)(ARGs...))
{
    cout << "RValue function" << endl;
}

template <typename RET_TYPE, typename...ARGs>
void takeFunction(RET_TYPE(*& function)(ARGs...))
{
    cout << "LValue function" << endl;
}

void function()
{
}

void testFn()
{
    void(*f)() = function;
    takeFunction(function);
    takeFunction(f);
}

我希望对成员函数做同样的事情。但是,它似乎没有翻译:

struct S;
void takeMemberFunction(void(S::&function)()) // error C2589: '&' : illegal token on right side of '::'
{
    cout << "RValue member function" << endl;
}

void takeMemberFunction(void(S::*&function)())
{
    cout << "LValue member function" << endl;
}

struct S
{
    void memberFunction()
    {
    }
};

void testMemberFn()
{
    void(S::*mf)() = &S::memberFunction;
    takeMemberFunction(S::memberFunction);
    takeMemberFunction(mf);
}

为什么?

我知道的另一种方法是对常规函数执行此操作:

void takeFunction(void(*&& function)())
{
    cout << "RValue function" << endl;
}

void takeFunction(void(*& function)())
{
    cout << "LValue function" << endl;
}

void function()
{
}

void testFn()
{
    void(*f)() = function;
    takeFunction(&function);
    takeFunction(f);
}

这确实转化为成员函数:

struct S;
void takeMemberFunction(void(S::*&&function)())
{
    cout << "RValue member function" << endl;
}

void takeMemberFunction(void(S::*&function)())
{
    cout << "LValue member function" << endl;
}

struct S
{
    void memberFunction()
    {
    }
};

void testMemberFn()
{
    void(S::*mf)() = &S::memberFunction;
    takeMemberFunction(&S::memberFunction); // error C2664: 'void takeMemberFunction(void (__thiscall S::* &)(void))' : cannot convert argument 1 from 'void (__thiscall S::* )(void)' to 'void (__thiscall S::* &)(void)'
    takeMemberFunction(mf);
}

但我想知道我的第一个示例没有翻译的差异。

【问题讨论】:

  • “这不起作用” :(
  • @LightningRacisinObrit:嗯?不是有用的评论。
  • 实际上,如果您将其阅读为“'这不起作用'不是有用的问题描述”。希望是在不解释显而易见的情况下推动您改进它!
  • 函数名的右值是从什么时候开始的?
  • 如果您真的阅读了 [basic.lval] 引用,您会看到“左值 [...] 指定函数或对象”。此外,[conv.fptr]/p1:“函数类型 T 的左值可以转换为“指向 T 的指针”类型的纯右值。结果是指向函数的指针。” [expr.prim.general]/p8:“一个 identifier 是一个 id-expression,前提是它已被适当地声明(第 7 条)。[...] 类型"

标签: c++ c++11 visual-c++


【解决方案1】:

我猜这是一个 Visual C++ 错误,如 gcc 和 clang 上的以下代码(基本上是您的问题)compiles for me,我认为没有理由期望它不会:

struct S;

void bar(void (S::*& f)() ) {
    std::cout << "lvalue" << std::endl;
}
void bar(void (S::*&& p)() ) {
    std::cout << "rvalue" << std::endl;
}

struct S {
    void foo() { }  
};

int main() {
    void (S::*f)();

    bar(f);        // prints lvalue
    bar(&S::foo);  // prints rvalue
}

有关您问题的其他部分,请参阅Why doesn't reference-to-member exist in C++?

【讨论】:

  • @Angew 是的,也包含了我自己的链接,它使用了这两种编译器。我相信链接的问题可以很好地解决另一部分问题。
  • 是的,确实如此。我发表评论时它不存在:-)
  • @Angew 你太快了,伙计。打败我 10 秒 :) (在证明部分我的意思是,我添加的另一部分是为了回应你的评论)
  • 不是因为它不是。令人失望,我认为与常规函数的解析方式不一致。呃,好吧。 ://
  • 顺便说一句,这不是编译器中的错误。这是一个错字造成的。
猜你喜欢
  • 1970-01-01
  • 2012-10-03
  • 1970-01-01
  • 2016-03-13
  • 1970-01-01
  • 1970-01-01
  • 2018-09-12
  • 1970-01-01
  • 2016-02-26
相关资源
最近更新 更多