When working with generic callables in modern C++, functions such as std::invoke make it possible to execute a wide variety of callable objects through a single interface. Lambdas, function pointers, and member functions can all be invoked using the same mechanism. However, situations often arise where the returned value must match a specific type. Traditionally, this requirement meant calling std::invoke and then converting the result afterward. While functional, this introduces an extra step and can make the intent less explicit.
For instance, the following example calls a lambda and manually converts the result to an integer:
#include <iostream>
#include <functional>
int main() {
auto lambda = [](double x) {
return x * 2.7;
};
int val = static_cast<int>(std::invoke(lambda, 5.0));
std::cout << val << std::endl; // 13
return 0;
}
In this case, the lambda returns a double, but the final value is expected to be an int. The conversion is performed explicitly after the invocation. Although straightforward, this pattern separates the call from the intended result type.
Since C++23, the standard library provides std::invoke_r, which allows specifying the desired return type directly as part of the invocation. The function performs the call and converts the result to the requested type in a single operation.
#include <iostream>
#include <functional>
int main() {
auto lambda = [](double x) {
return x * 2.7;
};
int val = std::invoke_r<int>(lambda, 5.0);
std::cout << val << std::endl; // 13
return 0;
}
Here, std::invoke_r<int> ensures that the result of the callable is returned as an int. The conversion happens automatically, making the code shorter and clearer.
Leave a Comment
Cancel reply