Last active
April 11, 2026 10:20
-
-
Save talybin/9d250de408025bc6221b976d0b6e74f8 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <iostream> | |
| #include <functional> | |
| #include <any> | |
| namespace detail | |
| { | |
| // Like std::decay but preserves reference qualifiers: | |
| // arrays -> pointer, functions -> function pointer, strips cv but NOT ref. | |
| template <class T> | |
| using transform_arg_t = std::conditional_t< | |
| std::is_array_v<std::remove_reference_t<T>> || std::is_function_v<std::remove_reference_t<T>>, | |
| std::decay_t<T>, | |
| std::remove_cv_t<T> | |
| >; | |
| // Get function signature to be stored in std::any | |
| template <class T> | |
| struct fn_signature : fn_signature<decltype(std::function(std::declval<T>()))> {}; | |
| template <class T> | |
| struct fn_signature<std::function<T>> : fn_signature<T> {}; | |
| template <class R, class... Args> | |
| struct fn_signature<R(Args...)> { | |
| using type = std::function<R(transform_arg_t<Args>...)>; | |
| }; | |
| template <class T> | |
| using fn_signature_t = typename fn_signature<T>::type; | |
| } // namespace detail | |
| struct function_any | |
| { | |
| function_any() = default; | |
| template <class F, | |
| std::enable_if_t<!std::is_same_v<std::decay_t<F>, function_any>, int> = 0, | |
| class = detail::fn_signature_t<std::decay_t<F>> | |
| > | |
| function_any(F&& f) | |
| : fn(detail::fn_signature_t<F>(std::forward<F>(f))) | |
| { } | |
| explicit operator bool() const noexcept { return fn.has_value(); } | |
| template <class R = void, class... Args> | |
| R operator()(Args&&... args) const | |
| { | |
| using F = detail::fn_signature_t<R(Args...)>; | |
| return std::any_cast<F>(fn)(std::forward<Args>(args)...); | |
| } | |
| private: | |
| std::any fn; | |
| }; | |
| int main() | |
| { | |
| function_any fn; | |
| std::cout << "--- Testing three arguments ---\n"; | |
| fn = [](const char* str, int& i, int* buf) { | |
| std::cout << str << '\n'; | |
| i = 42; | |
| buf[1] = 71; | |
| }; | |
| int buf[3] = { 100, 200, 300 }; | |
| int x = 10; | |
| fn("foobar", x, buf); | |
| std::cout << "x: " << x << '\n'; | |
| for (int b : buf) | |
| std::cout << b << '\n'; | |
| std::cout << "--- Testing one argument ---\n"; | |
| fn = [](double val) { | |
| std::cout << val << '\n'; | |
| }; | |
| fn(3.14); | |
| std::cout << "--- Testing return value ---\n"; | |
| fn = [](int a, int b) { return a + b; }; | |
| int result = fn.operator()<int>(3, 4); // result == 7 | |
| std::cout << "result: " << result << '\n'; | |
| } |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Output: