variadic_slot_invoker.hpp 4.8 KB

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