2

我正在尝试编译以下内容(g++-11.2,C++20),但我得到:

error: no matching function for call to '__invoke(std::_Mem_fn<void (Foo::*)(int, double)>, std::__tuple_element_t<0, std::tuple<int, double> >, std::__tuple_element_t<1, std::tuple<int, double> >)'
 1843 |       return std::__invoke(std::forward<_Fn>(__f),

代码:

#include <iostream>
#include <tuple>

struct Foo
{
    void bar(const int x, const double y) 
    {  
        std::cout << x << " " << y << std::endl;
    }  


    void bar_apply()
    {  
        // fails
        std::apply(std::mem_fn(&Foo::bar), std::tuple<int, double>(1, 5.0));
    }  
};


int main()
{
    Foo foo;
    foo.bar_apply();
};
4

3 回答 3

5

我推荐使用 C++20 bind_front,它更轻量级和直观。就像它的名字一样,成员函数需要一个特定的类对象来调用,所以你需要将指针绑定 到.thisFoo::bar

void bar_apply()
{  
  std::apply(std::bind_front(&Foo::bar, this), std::tuple<int, double>(1, 5.0));
}

演示。

于 2021-10-24T05:18:55.297 回答
2

正如其他人指出的那样,您需要一个实例来调用成员函数。这可以std::apply通过将函数调用包装到 lambda 表达式或通过元组参数来实现。

但是,我会建议std::invoke,这更适合这项任务。通过这种方式,不需要实例包装。

#include <functional> // std::invoke

std::invoke(&Foo::bar, this, 1, 5.0);
于 2021-10-24T05:05:29.243 回答
1

std::mem_fn(&Foo::bar)不会Foo像捕获 lambda 那样存储实例:

std::apply([this](int x, double y) { return bar(x,y); },
           std::tuple<int, double>(1, 5.0));

因此,您需要在调用mem_fn对象时提供实例:

std::apply(std::mem_fn(&Foo::bar), std::tuple<Foo*, int, double>(this, 1, 5.0));

或更简单,使用make_tuple

std::apply(std::mem_fn(&Foo::bar), std::make_tuple(this, 1, 5.0));
于 2021-10-24T05:02:16.177 回答