Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #pragma once
- #include <tuple>
- #include <utility>
- #include <cstddef>
- namespace fn
- {
- namespace
- {
- template<size_t N>
- using index = std::integral_constant<size_t, N>;
- const index<0> _1;
- const index<1> _2;
- const index<2> _3;
- const index<3> _4;
- const index<4> _5;
- const index<5> _6;
- const index<6> _7;
- const index<7> _8;
- }
- namespace details
- {
- template<size_t... Indices>
- struct index_list
- {
- using next = index_list<Indices..., sizeof...(Indices)>;
- };
- template<size_t N>
- struct make_index_list_impl
- {
- using type = typename make_index_list_impl<N - 1>::type::next;
- };
- template<>
- struct make_index_list_impl<0>
- {
- using type = index_list<>;
- };
- template<size_t N>
- using make_index_list = typename make_index_list_impl<N>::type;
- template<typename F, typename... BaseArgs>
- class binder_t
- {
- private:
- F func;
- std::tuple<BaseArgs...> func_baseargs;
- make_index_list<sizeof...(BaseArgs)> indices = make_index_list<sizeof...(BaseArgs)>();
- public:
- binder_t(F&& func, BaseArgs&&... args)
- : func(std::move(func))
- , func_baseargs(std::move(args)...)
- {}
- binder_t(const binder_t& other) = default;
- binder_t& operator=(binder_t other)
- {
- swap(other);
- return *this;
- }
- void swap(binder_t& other)
- {
- std::swap(func, other.func);
- std::swap(func_baseargs, other.func_baseargs);
- }
- //template<typename... FinalArgs, size_t... Indices>
- //auto call_func(F& func, std::tuple<FinalArgs...> final_args, const index_list<Indices...>&) ->
- // decltype(func(std::get<Indices>(final_args)...))
- //{
- // return func(std::get<Indices>(final_args)...);
- //}
- template<typename... FinalArgs, typename... Args>
- auto call_func(F& func, Args... args) ->
- decltype(func(args...))
- {
- return func(args...);
- }
- template<typename T, typename... Args>
- std::tuple<T, Args...> make_tuple(const T& value, const std::tuple<Args...>& tuple) const
- {
- return std::tuple_cat(std::make_tuple(value), tuple);
- }
- template<typename... NewArgs>
- std::tuple<> calc_full_args(const std::tuple<NewArgs...>&) const
- {
- return std::make_tuple();
- }
- template<typename... NewArgs, typename T, typename... R>
- auto calc_full_args(const std::tuple<NewArgs...>& cur_args, const T& val, const R&... rest) ->
- decltype(make_tuple(val, calc_full_args(cur_args, rest...))) const
- {
- return make_tuple(val, calc_full_args(cur_args, rest...));
- }
- template<typename... NewArgs, size_t N, typename... R>
- auto calc_full_args(const std::tuple<NewArgs...>& cur_args, index<N>, const R&... rest) ->
- decltype(make_tuple(std::get<N>(cur_args), calc_full_args(cur_args, rest...))) const
- {
- return make_tuple(std::get<N>(cur_args), calc_full_args(cur_args, rest...));
- }
- template<typename... NewArgs, size_t... Indices>
- auto calc_full_args(const std::tuple<NewArgs...>& cur_args, index_list<Indices...>) ->
- decltype(calc_full_args(cur_args, std::get<Indices>(func_baseargs)...)) const
- {
- return calc_full_args(cur_args, std::get<Indices>(func_baseargs)...);
- }
- //template<typename... NewArgs>
- //auto operator()(NewArgs... args) ->
- // decltype(call_func(func, calc_full_args(std::make_tuple(args...), indices), indices))
- //{
- // return call_func(func, calc_full_args(std::make_tuple(args...), indices), indices);
- //}
- template<typename... NewArgs>
- auto operator()(NewArgs... args) ->
- decltype(0)
- {
- calc_full_args(std::make_tuple(args...), indices);
- return 0;
- }
- };
- } // namespace details
- template<typename F, typename... Args>
- details::binder_t<F, Args...> bind(F func, Args... args)
- {
- return details::binder_t<F, Args...>(std::move(func), std::move(args)...);
- }
- // function implementation
- class bad_function_call : public std::exception
- {};
- template<typename T>
- class function;
- template<typename R, typename... Args>
- class function<R(Args...)>
- {
- private:
- struct function_wrapper_base
- {
- virtual ~function_wrapper_base(){}
- virtual function_wrapper_base* copy() = 0;
- virtual R operator()(Args&&...) = 0;
- };
- template<typename Functor>
- struct function_wrapper : function_wrapper_base
- {
- function_wrapper(const Functor& func)
- : func(func)
- {}
- function_wrapper(const function_wrapper&) = default;
- function_wrapper* copy() override
- {
- return new function_wrapper(func);
- }
- R operator()(Args&&...args) override
- {
- return func(std::forward<Args>(args)...);
- }
- Functor func;
- };
- function_wrapper_base* func_base;
- public:
- function()
- : func_base(nullptr)
- {}
- template<typename Functor>
- function(Functor func)
- : func_base(new function_wrapper<Functor>(func))
- {}
- function(nullptr_t)
- : func_base(nullptr)
- {}
- function(const function& other)
- : func_base(other.copy())
- {}
- function(function&& other)
- : function()
- {
- swap(other);
- }
- function_wrapper_base* copy() const
- {
- if (!func_base)
- return nullptr;
- return func_base->copy();
- }
- function& operator=(function other)
- {
- swap(other);
- return *this;
- }
- template<typename Functor>
- function& operator=(const Functor& func)
- {
- function tmp(func);
- swap(tmp);
- return *this;
- }
- void swap(function& other)
- {
- std::swap(func_base, other.func_base);
- }
- bool is_empty() const
- {
- return func_base == nullptr;
- }
- operator bool() const
- {
- return !is_empty();
- }
- R operator()(Args&&... args) const
- {
- if (is_empty())
- throw bad_function_call();
- return (*func_base)(std::forward<Args>(args)...);
- }
- ~function()
- {
- delete func_base;
- }
- };
- template<typename R, typename... Args>
- void swap(function<R(Args...)>& one, function<R(Args...)>& other)
- {
- one.swap(other);
- }
- } // namespace fn
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement