std::invoke,std::invoke_r(3)
πΈ NAME πΈ
std::invoke, std::invoke_r β okay so these are the β¨ universal callable-glueβ¨ functions. Manual name is C++ Standard Libary (yes bestie, that's how it's spelled on the tin, no cap, we're leaving it π
).
π Synopsis π
Defined in header <functional>
template< class F, class... Args >
std::invoke_result_t<F, Args...> (1) (since C++17)
(constexpr since C++20)
invoke( F&& f, Args&&... args ) noexcept(/* see below */);
template< class R, class F, class... Args >
constexpr R (2) (since C++23)
invoke_r( F&& f, Args&&... args ) noexcept(/* see below */);
- Calls the Callable object
fwith the parametersargsas if byINVOKE(std::forward<F>(f), std::forward<Args>(args)...). This overload only shows up in overload resolution ifstd::is_invocable_v<F, Args...>istrueβ like, it literally won't even be in the room otherwise π€ - Calls the Callable object
fwith the parametersargsas if byINVOKE<R>(std::forward<F>(f), std::forward<Args>(args)...). This overload only participates in overload resolution ifstd::is_invocable_r_v<R, F, Args...>istrue. Same energy, different gatekeeping πͺβ¨
π¦ Parameters π¦
fβ the Callable object getting invoked, bestie. it's the star of the show.argsβ the arguments you're passing tof. feed the icon what it needs π
π Return value π
- The value returned by
f. simple. clean. slay. - The value returned by
f, implicitly converted toR, ifRis not (possibly cv-qualified)void. None otherwise β so if it'svoid, you get literally nothing back and that's fine π
π₯ Exceptions π₯
noexceptspecification:noexcept(std::is_nothrow_invocable_v<F, Args...>)noexceptspecification:noexcept(std::is_nothrow_invocable_r_v<R, F, Args...>)
π Possible implementation π
invoke (1)
namespace detail
{
template<class>
constexpr bool is_reference_wrapper_v = false;
template<class U>
constexpr bool is_reference_wrapper_v<std::reference_wrapper<U>> = true;
template<class T>
using remove_cvref_t = std::remove_cv_t<std::remove_reference_t<T>>;
template<class C, class Pointed, class Object, class... Args>
constexpr decltype(auto) invoke_memptr(Pointed C::* member, Object&& object,
Args&&... args)
{
using object_t = remove_cvref_t<Object>;
constexpr bool is_member_function = std::is_function_v<Pointed>;
constexpr bool is_wrapped = is_reference_wrapper_v<object_t>;
constexpr bool is_derived_object = std::is_same_v<C, object_t>
|| std::is_base_of_v<C, object_t>;
if constexpr (is_member_function)
{
if constexpr (is_derived_object)
return (std::forward<Object>(object) .* member)
(std::forward<Args>(args)...);
else if constexpr (is_wrapped)
return (object.get() .* member)(std::forward<Args>(args)...);
else
return ((*std::forward<Object>(object)) .* member)
(std::forward<Args>(args)...);
}
else
{
static_assert(std::is_object_v<Pointed> && sizeof...(args) == 0);
if constexpr (is_derived_object)
return std::forward<Object>(object) .* member;
else if constexpr (is_wrapped)
return object.get() .* member;
else
return (*std::forward<Object>(object)) .* member;
}
}
} // namespace detail
template<class F, class... Args>
constexpr std::invoke_result_t<F, Args...> invoke(F&& f, Args&&... args)
noexcept(std::is_nothrow_invocable_v<F, Args...>)
{
if constexpr (std::is_member_pointer_v<detail::remove_cvref_t<F>>)
return detail::invoke_memptr(f, std::forward<Args>(args)...);
else
return std::forward<F>(f)(std::forward<Args>(args)...);
}
invoke_r (2)
template<class R, class F, class... Args>
requires std::is_invocable_r_v<R, F, Args...>
constexpr R invoke_r(F&& f, Args&&... args)
noexcept(std::is_nothrow_invocable_r_v<R, F, Args...>)
{
if constexpr (std::is_void_v<R>)
std::invoke(std::forward<F>(f), std::forward<Args>(args)...);
else
return std::invoke(std::forward<F>(f), std::forward<Args>(args)...);
}
β¨ Notes β¨
Feature-test macro vibes, iykyk π§:
__cpp_lib_invokeβ value201411L, std(C++17), featurestd::invoke,(1)__cpp_lib_invoke_rβ value202106L, std(C++23), featurestd::invoke_r,(2)
π Example π
// Run this code
#include <functional>
#include <iostream>
#include <type_traits>
struct Foo
{
Foo(int num) : num_(num) {}
void print_add(int i) const { std::cout << num_ + i << '\n'; }
int num_;
};
void print_num(int i)
{
std::cout << i << '\n';
}
struct PrintNum
{
void operator()(int i) const
{
std::cout << i << '\n';
}
};
int main()
{
std::cout << "invoke a free function: ";
std::invoke(print_num, -9);
std::cout << "invoke a lambda: ";
std::invoke([](){ print_num(42); });
std::cout << "invoke a member function: ";
const Foo foo(314159);
std::invoke(&Foo::print_add, foo, 1);
std::cout << "invoke (i.e., access) a data member num_: "
<< std::invoke(&Foo::num_, foo) << '\n';
std::cout << "invoke a function object: ";
std::invoke(PrintNum(), 18);
#if defined(__cpp_lib_invoke_r)
auto add = [](int x, int y){ return x + y; };
std::cout << "invoke a lambda converting result to float: ";
auto ret = std::invoke_r<float>(add, 11, 22);
static_assert(std::is_same<decltype(ret), float>());
std::cout << std::fixed << ret << "\ninvoke print_num: ";
std::invoke_r<void>(print_num, 44);
#endif
}
π Possible output π
invoke a free function: -9
invoke a lambda: 42
invoke a member function: 314160
invoke (i.e., access) a data member num_: 314159
invoke a function object: 18
invoke a lambda converting result to float: 33.000000
invoke print_num: 44
π«Ά See also π«Ά
mem_fnβ creates a function object out of a pointer to a member (function template)(C++11)result_ofβ deduces the result type of invoking a callable object with a set of arguments (class template)(C++11)(removed in C++20)invoke_resultβ same deduction mission, class template energy(C++17)is_invocable,is_invocable_r,is_nothrow_invocable,is_nothrow_invocable_rβ checks if a type can be invoked (as if bystd::invoke) with the given argument types (class template)(C++17)applyβ calls a function with a tuple of arguments (function template)(C++17)
π Category π
- conditionally noexcept (the whole personality tbh)
aaaand that's the whole page bestie π
β¨ sourced straight from http://cppreference.com, version dated 2024.06.10 β std::invoke,std::invoke_r(3), no cap, go invoke something iconic ππ¦π
π¦ where this page comes from
- nixpkgs unstable: stdman 2024.07.05
- opensuse-leap 16.0: stdman 2024.07.05-bp160.1.9 Β· MIT
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms