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