There is a new library feature in the C++17 standard, it is std::invoke
which is a useful feature to uniformly invoke callable entities. In this post, we explain what std::invoke
is and how we can use it in examples. First, let’s remind ourselves about what is a callable object and what is a functor in modern C++.
Table of Contents
What is callable object and what is functor in modern C++?
A callable object (some call it a functor) is an object that can be used as a function or function pointer by using the operator()
. This term is not the same as a function term in programming. We can pass many arguments with them; thus, we don’t need to define many global variables, we can use these kinds of variables in the scope that we use.
Here you can find more details about it.
What is std::invoke in C++ 17?
The std::invoke
call is a library feature in C++ 17 that allows invoking a method at run time and improved in C++20 and C++23 with invoke_r
. It is defined in the <functional>
header and useful to write libraries with the same behavior as the standard’s magic INVOKE rule. You can use std::invoke
to call a function or method, a lambda expression, or a member function, or can be used to access a data member, or you can use to invoke a function object.
In C++17 it is defined as below,
1 2 3 4 |
template< class F, class... Args > std::invoke_result_t< F, Args... > invoke( F&& f, Args&&... args ) noexcept(); |
In C++20 it is defined as below,
1 2 3 4 |
template< class F, class... Args > constexpr std::invoke_result_t< F, Args... > invoke( F&& f, Args&&... args ) noexcept(); |
And since C++23, there is invoke_r and it is defined as below,
1 2 3 |
template< class R, class F, class... Args > constexpr R invoke_r( F&& f, Args&&... args ) noexcept(); |
How can we use std::invoke with a parametric function in C++17?
Here is a simple std::invoke
example with a parametric function.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
#include <iostream> int myf(int x, int y) { return x*x+y*y; } int main() { int z = std::invoke(myf, 1, 2); std::cout << z << std::endl; system("pause"); return 0; } |
How can we use std::invoke with a lambda in C++17?
Here is a simple std::invoke
example with a lambda.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
#include <iostream> auto total_area = [] (int a, int b) -> int { return a*b; }; int main() { // invoke a lambda std::cout << std::invoke(total_area, 3,4) << std::endl; system("pause"); return 0; } |
How can we use std::invoke with a function object in C++17?
Here is a simple std::invoke
example with a function object.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
#include <iostream> class myfunc { public: void operator()(int x) const { std::cout << x << std::endl; } }; int main() { // invoke a function object std::invoke( myfunc(), 45 ); // invoke a function of an object myfunc f; std::invoke( f, 27); system("pause"); } |
How can we use std::invoke with a struct in C++17?
Here is a simple std::invoke
example with a struct that invokes a member function.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
#include <iostream> struct myst { int val_; myst(int val) : val_(val){ } int multiply(int n) const { return val_ * n; } }; int main() { const myst obj(5); std::cout << std::invoke( &myst::multiply, obj, 7 ) << std::endl; system("pause"); return 0; } |
How can we use std::invoke with a method of an object in C++17?
Here is a simple std::invoke
example with a class object that invokes a method of that object.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
#include <iostream> class myclass { public: void operator()(int x) { std::cout << x << std::endl; } }; int main() { // invoke a class method myclass myobj(5); std::cout << std::invoke( myobj.multiply,7 ) << std::endl; system("pause"); return 0; } |
As you see the std::invoke
is used to support the caller of a code part that is passing any callable object such as function, method, function object, struct, lambda, etc. Note that C++17 brings std::is_invocable
, std::is_invocable_r
, std::is_nothrow_invocable
, std::is_nothrow_invocable_r
that traits to reason about invocability and invocation results.
In addition to std::invoke
, in C++ Builder and Delphi programming languages there is System::Rtti::Invoke method for the RTTI (Run Time Type Information) Objects. Invoke methods are useful when the actual method is not known at compile time but is rather looked up at run time.
For more details about this feature in C++17 standard, please see these papers; N4169
C++ Builder is the easiest and fastest C and C++ compiler and IDE for building simple or professional applications on the Windows operating system. It is also easy for beginners to learn with its wide range of samples, tutorials, help files, and LSP support for code. RAD Studio’s C++ Builder version comes with the award-winning VCL framework for high-performance native Windows apps and the powerful FireMonkey (FMX) framework for UIs.
There is a free C++ Builder Community Edition for students, beginners, and startups; it can be downloaded from here. For professional developers, there are Professional, Architect, or Enterprise versions of C++ Builder and there is a trial version you can download from here.