Chris@16
|
1 /*
|
Chris@16
|
2 Helper class used by variadic implementation of variadic boost::signals2::signal.
|
Chris@16
|
3
|
Chris@16
|
4 Author: Frank Mori Hess <fmhess@users.sourceforge.net>
|
Chris@16
|
5 Begin: 2009-05-27
|
Chris@16
|
6 */
|
Chris@16
|
7 // Copyright Frank Mori Hess 2009
|
Chris@16
|
8 // Use, modification and
|
Chris@16
|
9 // distribution is subject to the Boost Software License, Version
|
Chris@16
|
10 // 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
Chris@16
|
11 // http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
12
|
Chris@16
|
13 // For more information, see http://www.boost.org
|
Chris@16
|
14
|
Chris@16
|
15 #ifndef BOOST_SIGNALS2_DETAIL_VARIADIC_SLOT_INVOKER_HPP
|
Chris@16
|
16 #define BOOST_SIGNALS2_DETAIL_VARIADIC_SLOT_INVOKER_HPP
|
Chris@16
|
17
|
Chris@16
|
18 #include <boost/mpl/size_t.hpp>
|
Chris@16
|
19 #include <boost/signals2/detail/variadic_arg_type.hpp>
|
Chris@16
|
20
|
Chris@16
|
21 // if compiler has std::tuple use it instead of boost::tuple
|
Chris@16
|
22 // because boost::tuple does not have variadic template support at present.
|
Chris@16
|
23 #ifdef BOOST_NO_CXX11_HDR_TUPLE
|
Chris@16
|
24 #include <boost/tuple/tuple.hpp>
|
Chris@16
|
25 #define BOOST_SIGNALS2_TUPLE boost::tuple
|
Chris@16
|
26 #define BOOST_SIGNALS2_GET boost::get
|
Chris@16
|
27 #else
|
Chris@16
|
28 #include <tuple>
|
Chris@16
|
29 #define BOOST_SIGNALS2_TUPLE std::tuple
|
Chris@16
|
30 #define BOOST_SIGNALS2_GET std::get
|
Chris@16
|
31 #endif
|
Chris@16
|
32
|
Chris@16
|
33 namespace boost
|
Chris@16
|
34 {
|
Chris@16
|
35 namespace signals2
|
Chris@16
|
36 {
|
Chris@16
|
37 namespace detail
|
Chris@16
|
38 {
|
Chris@16
|
39 template<unsigned ... values> class unsigned_meta_array {};
|
Chris@16
|
40
|
Chris@16
|
41 template<typename UnsignedMetaArray, unsigned n> class unsigned_meta_array_appender;
|
Chris@16
|
42
|
Chris@16
|
43 template<unsigned n, unsigned ... Args>
|
Chris@16
|
44 class unsigned_meta_array_appender<unsigned_meta_array<Args...>, n>
|
Chris@16
|
45 {
|
Chris@16
|
46 public:
|
Chris@16
|
47 typedef unsigned_meta_array<Args..., n> type;
|
Chris@16
|
48 };
|
Chris@16
|
49
|
Chris@16
|
50 template<unsigned n> class make_unsigned_meta_array;
|
Chris@16
|
51
|
Chris@16
|
52 template<> class make_unsigned_meta_array<0>
|
Chris@16
|
53 {
|
Chris@16
|
54 public:
|
Chris@16
|
55 typedef unsigned_meta_array<> type;
|
Chris@16
|
56 };
|
Chris@16
|
57
|
Chris@16
|
58 template<> class make_unsigned_meta_array<1>
|
Chris@16
|
59 {
|
Chris@16
|
60 public:
|
Chris@16
|
61 typedef unsigned_meta_array<0> type;
|
Chris@16
|
62 };
|
Chris@16
|
63
|
Chris@16
|
64 template<unsigned n> class make_unsigned_meta_array
|
Chris@16
|
65 {
|
Chris@16
|
66 public:
|
Chris@16
|
67 typedef typename unsigned_meta_array_appender<typename make_unsigned_meta_array<n-1>::type, n - 1>::type type;
|
Chris@16
|
68 };
|
Chris@16
|
69
|
Chris@16
|
70 template<typename R>
|
Chris@16
|
71 class call_with_tuple_args
|
Chris@16
|
72 {
|
Chris@16
|
73 public:
|
Chris@16
|
74 typedef R result_type;
|
Chris@16
|
75
|
Chris@16
|
76 template<typename Func, typename ... Args, std::size_t N>
|
Chris@16
|
77 R operator()(Func &func, BOOST_SIGNALS2_TUPLE<Args...> args, mpl::size_t<N>) const
|
Chris@16
|
78 {
|
Chris@16
|
79 typedef typename make_unsigned_meta_array<N>::type indices_type;
|
Chris@16
|
80 typename Func::result_type *resolver = 0;
|
Chris@16
|
81 return m_invoke(resolver, func, indices_type(), args);
|
Chris@16
|
82 }
|
Chris@16
|
83 private:
|
Chris@16
|
84 template<typename T, typename Func, unsigned ... indices, typename ... Args>
|
Chris@16
|
85 R m_invoke(T *, Func &func, unsigned_meta_array<indices...>, BOOST_SIGNALS2_TUPLE<Args...> args) const
|
Chris@16
|
86 {
|
Chris@16
|
87 return func(BOOST_SIGNALS2_GET<indices>(args)...);
|
Chris@16
|
88 }
|
Chris@16
|
89 template<typename Func, unsigned ... indices, typename ... Args>
|
Chris@16
|
90 R m_invoke(void *, Func &func, unsigned_meta_array<indices...>, BOOST_SIGNALS2_TUPLE<Args...> args) const
|
Chris@16
|
91 {
|
Chris@16
|
92 func(BOOST_SIGNALS2_GET<indices>(args)...);
|
Chris@16
|
93 return R();
|
Chris@16
|
94 }
|
Chris@101
|
95 // This overload is redundant, as it is the same as the previous variadic method when
|
Chris@101
|
96 // it has zero "indices" or "Args" variadic template parameters. This overload
|
Chris@101
|
97 // only exists to quiet some unused parameter warnings
|
Chris@101
|
98 // on certain compilers (some versions of gcc and msvc)
|
Chris@101
|
99 template<typename Func>
|
Chris@101
|
100 R m_invoke(void *, Func &func, unsigned_meta_array<>, BOOST_SIGNALS2_TUPLE<>) const
|
Chris@101
|
101 {
|
Chris@101
|
102 func();
|
Chris@101
|
103 return R();
|
Chris@101
|
104 }
|
Chris@16
|
105 };
|
Chris@16
|
106
|
Chris@16
|
107 template<typename R, typename ... Args>
|
Chris@16
|
108 class variadic_slot_invoker
|
Chris@16
|
109 {
|
Chris@16
|
110 public:
|
Chris@16
|
111 typedef R result_type;
|
Chris@16
|
112
|
Chris@16
|
113 variadic_slot_invoker(Args & ... args): _args(args...)
|
Chris@16
|
114 {}
|
Chris@16
|
115 template<typename ConnectionBodyType>
|
Chris@16
|
116 result_type operator ()(const ConnectionBodyType &connectionBody) const
|
Chris@16
|
117 {
|
Chris@16
|
118 result_type *resolver = 0;
|
Chris@16
|
119 return m_invoke(connectionBody,
|
Chris@16
|
120 resolver);
|
Chris@16
|
121 }
|
Chris@16
|
122 private:
|
Chris@16
|
123 template<typename ConnectionBodyType>
|
Chris@16
|
124 result_type m_invoke(const ConnectionBodyType &connectionBody,
|
Chris@16
|
125 const void_type *) const
|
Chris@16
|
126 {
|
Chris@16
|
127 return call_with_tuple_args<result_type>()(connectionBody->slot.slot_function(), _args, mpl::size_t<sizeof...(Args)>());
|
Chris@16
|
128 }
|
Chris@16
|
129 template<typename ConnectionBodyType>
|
Chris@16
|
130 result_type m_invoke(const ConnectionBodyType &connectionBody, ...) const
|
Chris@16
|
131 {
|
Chris@16
|
132 return call_with_tuple_args<result_type>()(connectionBody->slot.slot_function(), _args, mpl::size_t<sizeof...(Args)>());
|
Chris@16
|
133 }
|
Chris@16
|
134 BOOST_SIGNALS2_TUPLE<Args& ...> _args;
|
Chris@16
|
135 };
|
Chris@16
|
136 } // namespace detail
|
Chris@16
|
137 } // namespace signals2
|
Chris@16
|
138 } // namespace boost
|
Chris@16
|
139
|
Chris@16
|
140 #endif // BOOST_SIGNALS2_DETAIL_VARIADIC_SLOT_INVOKER_HPP
|