Причины использования std::invoke для вызова объекта std::function

#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? Или это приводит к ненужным накладным расходам на производительность?

Лично я бы использовал auto func = [&](const auto& var) { myObject.printMessage(var); }. Тогда вы используете его как func("some message");

NathanOliver 24.08.2024 19:06

Интересная запись в блоге Рэймонда Чена: Функция std::invoke делает больше, чем просто вызов функций.

wohlstad 24.08.2024 19:09

@3CxEZiVlQ Но если fun имеет тип std::function, то мне тоже не нужно заботиться о том, как вызвать, верно?

Mathieu 24.08.2024 19:10

Обман и статья объясняют, что я имею в виду.

3CxEZiVlQ 24.08.2024 19:13

@3CxEZiVlQ Можете ли вы привести простой пример кода? Это может ответить на мой вопрос

Mathieu 24.08.2024 19:13
std::invoke — это внутренняя реализация std::function. Да, объект, в котором установлен std::function, является вызываемым объектом, поэтому вы можете использовать std::invoke для его вызова. Но нет причин это делать.
Pete Becker 24.08.2024 19:29

@NathanOliver - конечно, но это привязывает вызов к одному myObject, поэтому он уже, чем код в вопросе, который можно вызывать с разными объектами.

Pete Becker 24.08.2024 19:31
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
8
62
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Здесь нет рассуждений std::invokestd::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!");

Другие вопросы по теме