web-dev-qa-db-fra.com

Qu'est-ce que std :: invoke en c ++?

Je viens de lire sur std::thread et std::bind que j'ai rencontré avec le concept Callable et std::invoke.

Je lis à propos de std::invoke le cppreference mais je n'ai pas compris ce qu'il disait. Voici ma question:
Quel est std::invoke, std::function, std::bind et le concept Callable? Et quelle est la relation entre eux?

19
user3397145

std::invoke Prend quelque chose qui peut être appelé, et des arguments pour l'appeler, et fait l'appel. std::invoke( f, args... ) est une légère généralisation de la frappe f(args...) qui gère également quelques cas supplémentaires.

Quelque chose appelable inclut un pointeur ou une référence de fonction, un pointeur de fonction membre, un objet avec une operator(), ou un pointeur vers des données de membre.

Dans les cas membres, le premier argument est interprété comme this. Les arguments restants sont ensuite passés à () (Sauf dans le cas du pointeur vers les données des membres).

INVOKE était un concept du standard C++; C++ 17 a simplement exposé un std::invoke Qui le fait directement. Je soupçonne qu'il a été exposé en partie parce qu'il est utile lors de la réalisation d'autres métaprogrammations, en partie parce que chaque bibliothèque standard contient déjà une implémentation d'INVOKE et l'exposer était fondamentalement gratuit, et en partie parce qu'il facilite la discussion sur INVOKE quand c'est une chose concrète .

24

Un objet Callable est, à part les détails spécifiques à C++, "quelque chose qui peut être appelé". Cela n'a pas besoin d'être une fonction: C++ a un certain nombre de types qui peuvent être appelés, et les parcourir chaque fois que n'importe lequel pourrait apparaître (lire: code générique) est problématique et trop répétitif.

C'est à cela que sert std::invoke - il permet d'appeler sans effort un objet générique qui peut être appelé (qui, selon C++ 17, satisfait le concept Callable).

Prenons un exemple simple:

void foo() { std::cout << "hello world\n"; };

template <bool b>
struct optionally_callable
{
        std::enable_if_t<b> operator() ()  {   std::cout << "hi again\n";   }
};

int main()
{
    auto c = [] { std::cout << "hi from lambda\n" ;};

    std::invoke(foo);
    std::invoke(c);

    auto o = optionally_callable<true>{};
    //auto o2 = optionally_callable<false>{};

    std::invoke(o);

}

o2 Est pas appelable, c'est-à-dire std::is_invocable<decltype(o2)>::value est false.

6
edmz