#include <iostream>
#include <functional>
#include <string>
#include <utility>
class MyClass {
public:
void printMessage(const std::string &message) const {
std::cout << "Message: " << message << std::endl;
}
};
int main() {
// Create an instance of MyClass
MyClass myObject;
// Example using std::function and std::invoke
std::function<void(const MyClass&, const std::string&)> func =
&MyClass::printMessage;
std::invoke(func, myObject, "Hello from std::invoke!");
// Example using std::function and its operator()
func(myObject, "Hello from operator() of std::function!");
// Example without std::function (direct member function pointer)
void (MyClass::*memberFuncPtr)(const std::string&) const = &MyClass::printMessage;
(myObject.*memberFuncPtr)("Hello from manual member function pointer!");
return 0;
}
Я понимаю, что std::invoke
— это хорошая оболочка, особенно в контексте указателей на функции-члены.
Мой вопрос: если я использую std::function
, есть ли причина использовать std::invoke
(вместо std::function::operator()
для вызова вызываемого std::function
? Или это приводит к ненужным накладным расходам на производительность?
Возможный дубликат: Когда использовать std::invoke вместо простого вызова вызываемого объекта?.
Интересная запись в блоге Рэймонда Чена: Функция std::invoke делает больше, чем просто вызов функций.
@3CxEZiVlQ Но если fun
имеет тип std::function
, то мне тоже не нужно заботиться о том, как вызвать, верно?
Обман и статья объясняют, что я имею в виду.
@3CxEZiVlQ Можете ли вы привести простой пример кода? Это может ответить на мой вопрос
std::invoke
— это внутренняя реализация std::function
. Да, объект, в котором установлен std::function
, является вызываемым объектом, поэтому вы можете использовать std::invoke
для его вызова. Но нет причин это делать.
@NathanOliver - конечно, но это привязывает вызов к одному myObject
, поэтому он уже, чем код в вопросе, который можно вызывать с разными объектами.
Здесь нет рассуждений std::invoke
std::function
, вы уже вручную определили std::function
аргументы шаблона.
std::invoke
полезен, когда вас не волнует, как ссылается на объект, является ли это ссылкой или указателем.
// Create an instance of MyClass
MyClass myObject;
MyClass* myObjectPtr = &myObject;
// Example using std::function and std::invoke
std::function<void(const MyClass&, const std::string&)> func1 =
&MyClass::printMessage;
std::function<void(const MyClass*, const std::string&)> func2 =
&MyClass::printMessage;
func1(myObject, "Hello from operator() of std::function!");
func2(myObjectPtr, "Hello from operator() of std::function!");
// Do not compile
// func1(myObjectPtr, "Hello from operator() of std::function!");
// func2(myObject, "Hello from operator() of std::function!");
auto func3 = &MyClass::printMessage; // less typing
std::invoke(func3, myObject, "Hello from std::invoke!");
std::invoke(func3, myObjectPtr, "Hello from std::invoke!");
Лично я бы использовал
auto func = [&](const auto& var) { myObject.printMessage(var); }
. Тогда вы используете его какfunc("some message");