Advertisement
Guest User

Untitled

a guest
Feb 3rd, 2022
37
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.64 KB | None | 0 0
  1. // CPPTestApp.cpp : This file contains the 'main' function. Program execution begins and ends there.
  2. //
  3.  
  4. #include <functional>
  5. #include <iostream>
  6. #include <typeindex>
  7. #include <boost/type_index.hpp>
  8. #include <type_traits>
  9.  
  10. class IDelegate
  11. {
  12. public:
  13.     virtual void invoke() { }
  14.     template<typename T>
  15.     T const& getArgument(size_t index) const
  16.     {
  17.         return *static_cast<T const*>(getArgumentHelper(index));
  18.     }
  19.     template<typename T>
  20.     T const& getResult() const
  21.     {
  22.         return *static_cast<T const*>(getResultHelper());
  23.     }
  24.     virtual bool hasResult() const = 0;
  25.     virtual size_t getArgumentsCount() const = 0;
  26.     virtual const std::type_info &getResultType() const = 0;
  27.     virtual const std::type_info& getArgumentType(size_t index) const = 0;
  28. protected:
  29.     virtual void const* getArgumentHelper(size_t index) const = 0;
  30.     virtual void const* getResultHelper() const = 0;
  31. };
  32. template <typename T, typename... Args>
  33. class Delegate : public IDelegate
  34. {
  35.     template<typename TFunc, typename TRet, typename... Args>
  36.     struct ResultValue
  37.     {
  38.         void assign(std::function<TFunc> f, std::tuple<Args...> args)
  39.         {
  40.             _result = std::apply(f, args);
  41.         }
  42.         const TRet* getResultImpl() const
  43.         {
  44.             return &_result;
  45.         }
  46.         bool hasResultImpl() const { return true; }
  47.         const std::type_info &getResultTypeImpl() const
  48.         {
  49.             return typeid(TRet);
  50.         }
  51.     private:
  52.         TRet _result;
  53.     };
  54.     template<typename TFunc, typename... Args>
  55.     struct ResultValue<TFunc, void, Args...>
  56.     {
  57.         void assign(std::function<TFunc> f, std::tuple<Args...> args)
  58.         {
  59.             std::apply(f, args);
  60.         }
  61.         const std::false_type* getResultImpl() const { return {}; }
  62.         bool hasResultImpl() const { return false; }
  63.         const std::type_info& getResultTypeImpl() const
  64.         {
  65.             return typeid(void);
  66.         }
  67.     };
  68.     std::function<T> _f;
  69.     std::tuple<Args...> _args;
  70.     ResultValue<T, std::invoke_result_t<T, Args...>, Args...> _result;
  71. public:
  72.     Delegate(T& f, Args &...args) :
  73.         _f(f),
  74.         _args(args...) { }
  75.     void invoke() final
  76.     {
  77.         _result.assign(_f, _args);
  78.  
  79.     }
  80.     size_t getArgumentsCount() const override
  81.     {
  82.         return sizeof...(Args);
  83.     }
  84.     bool hasResult() const override
  85.     {
  86.         return _result.hasResultImpl();
  87.     }
  88.     const std::type_info &getResultType() const override { return _result.getResultTypeImpl(); }
  89.     const std::type_info& getArgumentType(size_t index) const override { return GetArgumentTypeHelper<0>(index, _args); }
  90. protected:
  91.     void const* getArgumentHelper(size_t index) const override
  92.     {
  93.         return GetArgumentHelper<0>(index, _args);
  94.     }
  95.     void const* getResultHelper() const override
  96.     {
  97.         return _result.getResultImpl();
  98.     }
  99. private:
  100.     template<size_t index>
  101.     static void const* GetArgumentHelper(size_t i, std::tuple<Args...> const& args)
  102.     {
  103.         if constexpr (sizeof...(Args) > index)
  104.         {
  105.             if (index == i)
  106.             {
  107.                 return &std::get<index>(args);
  108.             }
  109.             else
  110.             {
  111.                 return GetArgumentHelper<index + 1>(i, args);
  112.             }
  113.         }
  114.         else
  115.         {
  116.             throw std::runtime_error("index out of bounds");
  117.         }
  118.     }
  119.     template<size_t index>
  120.     static const type_info &GetArgumentTypeHelper(size_t i, std::tuple<Args...> const& args)
  121.     {
  122.         if constexpr (sizeof...(Args) > index)
  123.         {
  124.             if (index == i)
  125.             {
  126.                 return GetArgumentTypeInfoHelper2(std::get<index>(args));
  127.             }
  128.             else
  129.             {
  130.                 return GetArgumentTypeHelper<index + 1>(i, args);
  131.             }
  132.         }
  133.         else
  134.         {
  135.             throw std::runtime_error("index out of bounds");
  136.         }
  137.     }
  138.     template<typename T>
  139.     static const type_info &GetArgumentTypeInfoHelper2(T argument)
  140.     {
  141.         return typeid(T);
  142.     }
  143. };
  144. void a() { std::cout << "a called;\n"; }
  145. void b(int x) { std::cout << "b called with " << x << "\n"; }
  146. float c(int x, float y) { std::cout << "c called with " << x << ", " << y << "\n"; return 999; }
  147. void print_arg(IDelegate *d, size_t index)
  148. {
  149.     std::cout << index << "-th argument is " << d->getArgumentType(index).name() << ", it's value: ";
  150.     if(d->getArgumentType(index) == typeid(int))
  151.     {
  152.         std::cout << d->getArgument<int>(index);
  153.     }
  154.     else if (d->getArgumentType(index) == typeid(float))
  155.     {
  156.         std::cout << d->getArgument<float>(index);
  157.     }
  158.     std::cout << '\n';
  159. }
  160. int main()
  161. {
  162.     int i;
  163.     float f;
  164.     std::vector<IDelegate*> calls_queue;
  165.     calls_queue.push_back(new Delegate(a));
  166.     i = 42;
  167.     auto t = new Delegate(b, i);
  168.     auto r = t->getArgument<int>(0);
  169.     calls_queue.push_back(t);
  170.     i = 21;
  171.     f = 0.999;
  172.     calls_queue.push_back(new Delegate(c, i, f));
  173.     for(auto &d : calls_queue)
  174.     {
  175.         d->invoke();
  176.         for (auto i = 0; i < d->getArgumentsCount(); i++)
  177.         {
  178.             print_arg(d, i);
  179.         }
  180.         if (d->hasResult())
  181.         {
  182.             std::cout << "Result true type: " << d->getResultType().name() << '\n';
  183.             std::cout << "Result (as int): " << d->getResult<int>() << '\n';
  184.         }
  185.     }
  186. };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement