Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #pragma once
- #include <functional>
- #include <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 return_type = R;
- using type = R(Args...);
- template <class T>
- using set_rtype = T(Args...);
- };
- // Any value auto cast
- struct any_value : std::any
- {
- using std::any::any;
- template <class T>
- operator T() {
- return std::any_cast<T>(*this);
- }
- };
- // std::any or void will accept any function
- template <class R = any_value>
- struct any_function
- {
- any_function() = default;
- template <class F>
- any_function(F&& fn)
- {
- using fn_sign = fn_signature<F>;
- using cast_sign = typename fn_sign::template set_rtype<R>;
- fn_ = std::function<cast_sign>([fn = std::forward<F>(fn)](auto&&... args) -> R
- {
- if constexpr (std::is_same_v<R, void>)
- fn(std::forward<decltype(args)>(args)...);
- else if constexpr (std::is_same_v<typename fn_sign::return_type, void>) {
- fn(std::forward<decltype(args)>(args)...);
- return { };
- }
- else
- return fn(std::forward<decltype(args)>(args)...);
- });
- }
- template <class... Args>
- R operator()(Args&&... args) const
- {
- using fn_type = std::function<R(Args...)>;
- if (auto fn = std::any_cast<fn_type>(&fn_))
- return (*fn)(std::forward<Args>(args)...);
- else
- throw std::bad_function_call();
- }
- private:
- std::any fn_;
- };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement