summaryrefslogtreecommitdiffstats
blob: 6d9227efb81c9faea3885ab9d7c35aa6da7f7b05 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
/*
  Helper class used by variadic implementation of variadic boost::signals2::signal.

  Author: Frank Mori Hess <fmhess@users.sourceforge.net>
  Begin: 2009-05-27
*/
// Copyright Frank Mori Hess 2009
// Use, modification and
// distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)

// For more information, see http://www.boost.org

#ifndef BOOST_SIGNALS2_DETAIL_VARIADIC_SLOT_INVOKER_HPP
#define BOOST_SIGNALS2_DETAIL_VARIADIC_SLOT_INVOKER_HPP

#if defined(_MSVC_VER)
# pragma warning(push)
# pragma warning(disable:4100) // unreferenced formal parameter
#endif

#include <boost/mpl/size_t.hpp>
#include <boost/signals2/detail/variadic_arg_type.hpp>

// if compiler has std::tuple use it instead of boost::tuple
// because boost::tuple does not have variadic template support at present.
#ifdef BOOST_NO_CXX11_HDR_TUPLE
#include <boost/tuple/tuple.hpp>
#define BOOST_SIGNALS2_TUPLE boost::tuple
#define BOOST_SIGNALS2_GET boost::get
#else
#include <tuple>
#define BOOST_SIGNALS2_TUPLE std::tuple
#define BOOST_SIGNALS2_GET std::get
#endif

namespace boost
{
  namespace signals2
  {
    namespace detail
    {
      template<unsigned ... values> class unsigned_meta_array {};

      template<typename UnsignedMetaArray, unsigned n> class unsigned_meta_array_appender;

      template<unsigned n, unsigned ... Args>
        class unsigned_meta_array_appender<unsigned_meta_array<Args...>, n>
      {
      public:
        typedef unsigned_meta_array<Args..., n> type;
      };

      template<unsigned n> class make_unsigned_meta_array;

      template<> class make_unsigned_meta_array<0>
      {
      public:
        typedef unsigned_meta_array<> type;
      };

      template<> class make_unsigned_meta_array<1>
      {
      public:
        typedef unsigned_meta_array<0> type;
      };

      template<unsigned n> class make_unsigned_meta_array
      {
      public:
        typedef typename unsigned_meta_array_appender<typename make_unsigned_meta_array<n-1>::type, n - 1>::type type;
      };

      template<typename R>
        class call_with_tuple_args
      {
      public:
        typedef R result_type;

        template<typename Func, typename ... Args, std::size_t N>
        R operator()(Func &func, BOOST_SIGNALS2_TUPLE<Args...> args, mpl::size_t<N>) const
        {
          typedef typename make_unsigned_meta_array<N>::type indices_type;
          typename Func::result_type *resolver = 0;
          return m_invoke(resolver, func, indices_type(), args);
        }
      private:
        template<typename T, typename Func, unsigned ... indices, typename ... Args>
          R m_invoke(T *, Func &func, unsigned_meta_array<indices...>, BOOST_SIGNALS2_TUPLE<Args...> args) const
        {
          return func(BOOST_SIGNALS2_GET<indices>(args)...);
        }
        template<typename Func, unsigned ... indices, typename ... Args>
          R m_invoke(void *, Func &func, unsigned_meta_array<indices...>, BOOST_SIGNALS2_TUPLE<Args...> args) const
        {
          func(BOOST_SIGNALS2_GET<indices>(args)...);
          return R();
        }
      };

      template<typename R, typename ... Args>
        class variadic_slot_invoker
      {
      public:
        typedef R result_type;

        variadic_slot_invoker(Args & ... args): _args(args...)
        {}
        template<typename ConnectionBodyType>
          result_type operator ()(const ConnectionBodyType &connectionBody) const
        {
          result_type *resolver = 0;
          return m_invoke(connectionBody,
            resolver);
        }
      private:
        template<typename ConnectionBodyType>
        result_type m_invoke(const ConnectionBodyType &connectionBody,
          const void_type *) const
        {
          return call_with_tuple_args<result_type>()(connectionBody->slot.slot_function(), _args, mpl::size_t<sizeof...(Args)>());
        }
        template<typename ConnectionBodyType>
          result_type m_invoke(const ConnectionBodyType &connectionBody, ...) const
        {
          return call_with_tuple_args<result_type>()(connectionBody->slot.slot_function(), _args, mpl::size_t<sizeof...(Args)>());
        }
        BOOST_SIGNALS2_TUPLE<Args& ...> _args;
      };
    } // namespace detail
  } // namespace signals2
} // namespace boost

#if defined(_MSVC_VER)
# pragma warning(pop)
#endif

#endif // BOOST_SIGNALS2_DETAIL_VARIADIC_SLOT_INVOKER_HPP