Boost.Signals2のsignalクラスは、テンプレートパラメータがたくさんあり、後ろの方のパラメータを一部だけ指定するのはなかなか大変です。
namespace boost { namespace signals2 { template<typename Signature, 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; } }
Boost.Signals2には、Boost.Parameterベースの名前付きテンプレート引数を指定する、signal_typeメタ関数があります。
デフォルト以外のテンプレート引数を使いたい場合にはこれを使うのがいいでしょう。
例として、signalクラスの最後のテンプレートパラメータであるMutexだけをカスタマイズしてみましょう。適当なスピンロッククラスを作って指定します。
#include <iostream> #include <atomic> #include <boost/signals2.hpp> class spinlock { private: typedef enum {Locked, Unlocked} LockState; std::atomic<LockState> state_; public: spinlock() : state_(Unlocked) {} void lock() { // 現在の状態をLockedと入れ替える while (state_.exchange(Locked, std::memory_order_acquire) == Locked) { // busy-wait...アンロックされるまで待機 } } void unlock() { // 値をUnlockedに更新 state_.store(Unlocked, std::memory_order_release); } }; int main() { namespace signals = boost::signals2; namespace keywords = signals::keywords; // ミューテックスだけカスタマイズする using signal = signals::signal_type<void(int), keywords::mutex_type<spinlock>>::type; signal sig; sig.connect([](int x) { std::cout << x << std::endl; }); sig(3); }
3
signal_typeを使ってる行がそれです。boost::signals2::keywords名前空間に、signalクラスのための名前付きテンプレート引数キーワードが定義されているので、指定したい型をキーワードでラップして渡します。最後に::typeをとると、指定した一部のテンプレート引数以外がデフォルトで埋められたsignal型が返されます。
参照:
Class template signal_type - Boost Signals2 Library