Boost.Signals2 を Boost.Parameter を使用して定義する
Boost.Signals2 の signal は、以下の様に複数のテンプレート引数が存在します。
template<typename Signature, // Function type R (T1, T2, ..., TN) typename Combiner = boost::signals2::optional_last_value<R>, typename Group = int, typename GroupCompare = std::less<Group>, typename SlotFunction = boost::function<Signature>, typename ExtendedSlotFunction = boost::function<R (const connection &, T1, T2, ..., TN)>, typename Mutex = boost::signals2::mutex> class signal;
しかし、これだと、Group を float 型にして定義したい場合に、
typedef signal< void(), boost::signals2::optional_last_value<void>, // これも定義しなければならない float > group_float_signal;
となってしまい、Combiner もユーザ側で定義し直さなければなりません。
と、いうことで、これをどうにかしたかったので、Boost.Parameter を使用してラップしてみました。
[ソース]
#define BOOST_PARAMETER_MAX_ARITY 10 #include <boost/signals2/signal.hpp> #include <boost/parameter.hpp> #include <functional> BOOST_PARAMETER_TEMPLATE_KEYWORD(combiner) BOOST_PARAMETER_TEMPLATE_KEYWORD(group) BOOST_PARAMETER_TEMPLATE_KEYWORD(group_compare) BOOST_PARAMETER_TEMPLATE_KEYWORD(slot_functon) BOOST_PARAMETER_TEMPLATE_KEYWORD(extended_slot_function) BOOST_PARAMETER_TEMPLATE_KEYWORD(mutex) typedef boost::parameter::parameters< boost::parameter::optional<tag::combiner>, boost::parameter::optional<tag::group>, boost::parameter::optional<tag::group_compare>, boost::parameter::optional<tag::slot_functon>, boost::parameter::optional<tag::extended_slot_function>, boost::parameter::optional<tag::mutex> > class_signature; namespace detail{ using namespace boost; using namespace boost::signals2; template< typename Signature, typename Arg0 = parameter::void_, typename Arg1 = parameter::void_, typename Arg2 = parameter::void_, typename Arg3 = parameter::void_, typename Arg4 = parameter::void_, typename Arg5 = parameter::void_ > struct signal_impl{ typedef typename class_signature::bind< Arg0, Arg1, Arg2, Arg3, Arg4, Arg5 >::type args; typedef typename boost::function_traits<Signature>::result_type result_type; typedef typename parameter::binding< args, tag::combiner, optional_last_value< typename boost::function_traits<Signature>::result_type > >::type combiner; typedef typename parameter::binding<args, tag::group, int>::type group; typedef typename parameter::binding< args, tag::group_compare, std::less<group> >::type group_compare; typedef typename parameter::binding< args, tag::slot_functon, boost::function<Signature> >::type slot_functon; typedef typename parameter::binding< args, tag::extended_slot_function, typename signals2::detail::extended_signature< function_traits<Signature>::arity, Signature >::function_type >::type extended_slot_function; typedef typename parameter::binding< args, tag::mutex, boost::signals2::mutex >::type mutex; typedef signals2::signal< Signature, combiner, group, group_compare, slot_functon, extended_slot_function, mutex > type; }; } // namespace detai; template< typename Signature, typename Combiner = boost::parameter::void_, typename Group = boost::parameter::void_, typename GroupCompare = boost::parameter::void_, typename SlotFunction = boost::parameter::void_, typename ExtendedSlotFunction = boost::parameter::void_, typename Mutex = boost::parameter::void_ > struct signal : detail::signal_impl< Signature, Combiner, Group, GroupCompare, SlotFunction, ExtendedSlotFunction, Mutex >::type{ typedef typename detail::signal_impl< Signature, Combiner, Group, GroupCompare, SlotFunction, ExtendedSlotFunction, Mutex >::type base_type; typedef typename base_type::combiner_type combiner_type; typedef typename base_type::group_compare_type group_compare_type; signal( const combiner_type& combiner = combiner_type(), const group_compare_type& group_compare = group_compare_type() ) : base_type(combiner, group_compare){} }; #include <iostream> #include <boost/lambda/lambda.hpp> int main(){ namespace lambda = boost::lambda; signal<void(), group<float> > sig; sig.connect(0.5f, std::cout << lambda::var(", World!!\n")); sig.connect(std::cout << lambda::var("... and good morning!\n")); sig.connect(0.3f, std::cout << lambda::var("Hello")); sig(); return 0; }
[出力]
Hello, World!! ... and good morning!
signal のテンプレート引数が多いので、コードは長くなっていますが、特に難しい事はしていません。
Boost.Parameter で定義する側はちょっと手間なんですけども、ユーザ側の定義はすっきりするので、こういう時に Boost.Parameter は便利ですね!
[boost]
- ver 1.47.0