Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // CPPTestApp.cpp : This file contains the 'main' function. Program execution begins and ends there.
- //
- #include <functional>
- #include <iostream>
- #include <typeindex>
- #include <boost/type_index.hpp>
- #include <type_traits>
- class IDelegate
- {
- public:
- virtual void invoke() { }
- template<typename T>
- T const& getArgument(size_t index) const
- {
- return *static_cast<T const*>(getArgumentHelper(index));
- }
- template<typename T>
- T const& getResult() const
- {
- return *static_cast<T const*>(getResultHelper());
- }
- virtual bool hasResult() const = 0;
- virtual size_t getArgumentsCount() const = 0;
- virtual const std::type_info &getResultType() const = 0;
- virtual const std::type_info& getArgumentType(size_t index) const = 0;
- protected:
- virtual void const* getArgumentHelper(size_t index) const = 0;
- virtual void const* getResultHelper() const = 0;
- };
- template <typename T, typename... Args>
- class Delegate : public IDelegate
- {
- template<typename TFunc, typename TRet, typename... Args>
- struct ResultValue
- {
- void assign(std::function<TFunc> f, std::tuple<Args...> args)
- {
- _result = std::apply(f, args);
- }
- const TRet* getResultImpl() const
- {
- return &_result;
- }
- bool hasResultImpl() const { return true; }
- const std::type_info &getResultTypeImpl() const
- {
- return typeid(TRet);
- }
- private:
- TRet _result;
- };
- template<typename TFunc, typename... Args>
- struct ResultValue<TFunc, void, Args...>
- {
- void assign(std::function<TFunc> f, std::tuple<Args...> args)
- {
- std::apply(f, args);
- }
- const std::false_type* getResultImpl() const { return {}; }
- bool hasResultImpl() const { return false; }
- const std::type_info& getResultTypeImpl() const
- {
- return typeid(void);
- }
- };
- std::function<T> _f;
- std::tuple<Args...> _args;
- ResultValue<T, std::invoke_result_t<T, Args...>, Args...> _result;
- public:
- Delegate(T& f, Args &...args) :
- _f(f),
- _args(args...) { }
- void invoke() final
- {
- _result.assign(_f, _args);
- }
- size_t getArgumentsCount() const override
- {
- return sizeof...(Args);
- }
- bool hasResult() const override
- {
- return _result.hasResultImpl();
- }
- const std::type_info &getResultType() const override { return _result.getResultTypeImpl(); }
- const std::type_info& getArgumentType(size_t index) const override { return GetArgumentTypeHelper<0>(index, _args); }
- protected:
- void const* getArgumentHelper(size_t index) const override
- {
- return GetArgumentHelper<0>(index, _args);
- }
- void const* getResultHelper() const override
- {
- return _result.getResultImpl();
- }
- private:
- template<size_t index>
- static void const* GetArgumentHelper(size_t i, std::tuple<Args...> const& args)
- {
- if constexpr (sizeof...(Args) > index)
- {
- if (index == i)
- {
- return &std::get<index>(args);
- }
- else
- {
- return GetArgumentHelper<index + 1>(i, args);
- }
- }
- else
- {
- throw std::runtime_error("index out of bounds");
- }
- }
- template<size_t index>
- static const type_info &GetArgumentTypeHelper(size_t i, std::tuple<Args...> const& args)
- {
- if constexpr (sizeof...(Args) > index)
- {
- if (index == i)
- {
- return GetArgumentTypeInfoHelper2(std::get<index>(args));
- }
- else
- {
- return GetArgumentTypeHelper<index + 1>(i, args);
- }
- }
- else
- {
- throw std::runtime_error("index out of bounds");
- }
- }
- template<typename T>
- static const type_info &GetArgumentTypeInfoHelper2(T argument)
- {
- return typeid(T);
- }
- };
- void a() { std::cout << "a called;\n"; }
- void b(int x) { std::cout << "b called with " << x << "\n"; }
- float c(int x, float y) { std::cout << "c called with " << x << ", " << y << "\n"; return 999; }
- void print_arg(IDelegate *d, size_t index)
- {
- std::cout << index << "-th argument is " << d->getArgumentType(index).name() << ", it's value: ";
- if(d->getArgumentType(index) == typeid(int))
- {
- std::cout << d->getArgument<int>(index);
- }
- else if (d->getArgumentType(index) == typeid(float))
- {
- std::cout << d->getArgument<float>(index);
- }
- std::cout << '\n';
- }
- int main()
- {
- int i;
- float f;
- std::vector<IDelegate*> calls_queue;
- calls_queue.push_back(new Delegate(a));
- i = 42;
- auto t = new Delegate(b, i);
- auto r = t->getArgument<int>(0);
- calls_queue.push_back(t);
- i = 21;
- f = 0.999;
- calls_queue.push_back(new Delegate(c, i, f));
- for(auto &d : calls_queue)
- {
- d->invoke();
- for (auto i = 0; i < d->getArgumentsCount(); i++)
- {
- print_arg(d, i);
- }
- if (d->hasResult())
- {
- std::cout << "Result true type: " << d->getResultType().name() << '\n';
- std::cout << "Result (as int): " << d->getResult<int>() << '\n';
- }
- }
- };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement