std::invoke
std::invoke is used for calling function objects, like lambdas, methods, functions without knowing about type this function.
For example , before we needed to use pointer to function, pointer to method:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
int qwe(int x) { return x + 1; } class A { public: void aaa(int x) { std::cout << x << std::endl; } }; int main() { int(*func)(int) = &qwe; void(A::*qwe)(int) = &A::aaa; func(2); A a; (a.*qwe)(2); return 0; } |
with std::invoke it’s much more simpler:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
int qwe(int x) { return x + 1; } class A { public: void aaa(int x) { std::cout << x << std::endl; } }; int main() { A object; std::invoke(&qwe, 2); std::invoke(&A::aaa, object, 5); return 0; } |
std::invoke it’s universal interface for calling anything it’s callable.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
class Example { public: int x{ 10 }; void operator()(int x) { std::cout << "int() = " << x << std::endl; } }; int main() { Example obj; obj(5); return 0; } |
Example with lambda:
1 2 3 4 5 |
int main() { std::invoke([]() {std::cout << "lambda()"; }); return 0; } |
Example with template:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
template<typename func> class AddLogic { public: AddLogic(func f) :func_{ f } {} template<typename ... Args> decltype(auto) operator ()(Args&&... args) { // add some logic return std::invoke(func_, std::forward<Args>(args)...); } private: func func_; }; int main() { auto lambda = [](int x) { return 123;}; AddLogic<decltype(lambda)> logic{ lambda }; logic(8); return 0; } |
Here is standard document: n4169.
std::apply
std::apply is used to Invoke a Callable object with a tuple of arguments.
For example:
1 2 3 4 5 |
auto add = [] (int x, int y) { return x + y; }; std::apply(add, std::make_tuple( 1, 2 )); // == 3 |
std::make_from_tuple – Construct an object of type T, using the elements of the tuple t as the arguments to the constructor.
Due to guaranteed copy elision, T need not be movable.
For example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
#include <iostream> #include <tuple> struct Foo { Foo(int first, float second, int third) { std::cout << first << ", " << second << ", " << third << "\n"; } }; int main() { auto tuple = std::make_tuple(42, 3.14f, 0); std::make_from_tuple<Foo>(std::move(tuple)); } |