Использование std::apply в методе класса
Я пытаюсь скомпилировать следующее (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();
};
3 ответа
Я рекомендую использовать C++20 bind_front
, который более легкий и интуитивно понятный. Как и его имя, функции-члены требуют вызова определенного объекта класса, поэтому вам нужно привязать
this
указатель на
Foo::bar
.
void bar_apply()
{
std::apply(std::bind_front(&Foo::bar, this), std::tuple<int, double>(1, 5.0));
}
std::mem_fn(&Foo::bar)
не хранит экземпляр
Foo
как это сделала бы лямбда:
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));
Как указывали другие, вам нужен экземпляр для вызова функции-члена. Это вы можете доставить
std::apply
путем переноса вызова функции в лямбда-выражение или через аргументы кортежа.
Однако я бы посоветовал std::invoke
, который больше подходит для этой задачи. Таким образом, обертывание экземпляра не требуется.
#include <functional> // std::invoke
std::invoke(&Foo::bar, this, 1, 5.0);