c++ - result_of 没有为 mem_fn 定义类型

标签 c++ c++14 pointer-to-member result-of

我有以下代码:

#include <functional>

struct X {
    int get() const& {
        return 42;
    }
};

template<typename Func>
std::result_of_t<Func(X)> Apply(Func fn) {
    X x;
    return fn(x);
}

int main(void) {
    Apply([](X const& x){return x.get();});
    //Apply(std::mem_fn(&X::get)); // does not compile
}

第一次调用 Apply 编译正常,但如果我取消注释第二次调用,我会得到以下编译错误:

main.cpp:16:5: error: no matching function for call to 'Apply'
    Apply(std::mem_fn(&X::get)); // does not compile
    ^~~~~
main.cpp:10:27: note: candidate template ignored: substitution failure [with Func = std::_Mem_fn<int (X::*)() const &>]: no type named 'type' in 'std::result_of<std::_Mem_fn<int (X::*)() const &> (X)>'
std::result_of_t<Func(X)> Apply(Func fn) {
                          ^

我以某种方式期望这两个调用可以互换使用,并且 std::mem_fn 只是“会做正确的事”。谁能解释一下,这里发生了什么?

最佳答案

问题出在这里:

int get() const& {
//            ^^^

您的成员函数是左值引用限定的。在你的 Apply() 中:

template<typename Func>
std::result_of_t<Func(X)> Apply(Func fn) {
    return fn(X{});
}

您正在使用右值调用它。这给我们带来了这两个表达方式之间的[令我非常惊讶]的区别:

X{}.get();        // ok
(X{}.*&X::get)(); // ill-formed

特别是指向成员的指针运算符上,成员指针的引用限定符根据对象的值类别进行检查。来自 [expr.mptr.oper]:

In a .* expression whose object expression is an rvalue, the program is ill-formed if the second operand is a pointer to member function with ref-qualifier &. In a .* expression whose object expression is an lvalue, the program is ill-formed if the second operand is a pointer to member function with ref-qualifier &&.

所以第一个表达式没问题,get()const& 限定的,但右值可以绑定(bind)到它。第二个表达方式不行——规则只是明确禁止它。

所以你看到的行为是完全正确的 - mem_fn 是通过直接调用成员函数定义的,它在右值上是错误的,所以 Apply 被从过载集。如果不是,那么实例化主体将是一个硬错误。

lambda 起作用的原因是临时 X 绑定(bind)到 lambda 的引用参数。 get() 然后在左值函数参数上调用 - 而不是在传递给它的临时参数上。但即使没有它,直接在临时对象上调用 get() 仍然没问题。

关于c++ - result_of 没有为 mem_fn 定义类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42113821/

相关文章:

c++ - Arduino 整数错误

c++ - 用于存储通用 lambda 的通用 std::function

c++ - 在 C++ 中使用超时处理程序实现定时器

不使用 std::bind、std::function 或 boost 的 C++ 多成员函数回调

c++ - 为什么括号被消除歧义为 std::istream_iterator 的函数声明?

c++ - 关于C++中智能指针的问题

c++ - 在声明 "std::vector<X> f();"中, "std::vector<X>"是实例化吗?

c++ - 在 vector 声明中初始化对象

c++ - XPATH在C++ Boost中使用

C++ 指向成员函数的指针、声明