1

Boost の signal2 ライブラリは、その拡張機能の一部について代替パラメータを渡すための優れた方法を定義しています (そのパラメータ ライブラリを介して)。これらの代替パラメーターの 1 つが私のコードでかなり一般的である場合、使用をさらに簡素化するヘルパーを作成したいと思います。たとえば、別のミューテックス タイプを指定するには、次のようにします。

namespace bs2 = boost::signals2;
template<typename Signature>
struct my_signal
{
    typedef typename bs2::signal_type<Signature,
        bs2::keywords::mutex_type<my_mutex> >::type type;
};

my_signal<void ()>::type some_signal;

残念ながら、これを行うことで、冗長な構文に戻ったり、 my_signal_with_combiner などの追加のメタ関数を定義したりすることなく、他のシグナルパラメーター (コンバイナータイプなど) の代替値を指定する機能も「失って」しまいました (これはばかげているようです)。 . コンバイナーのデフォルトでは、戻り値の型を取得するために署名を分解する必要があるため、デフォルトのテンプレートパラメーター値でもそれを行うことはできないと思います。(もちろん、理想的には、コンバイナーだけでなく、他のパラメーターのいずれかで機能するものが欲しいです。)

したがって、「本当の」質問は次のとおりです。それと同じように動作するが、パラメーターの1つに異なるデフォルト値を持つsignal_typeのようなものを定義する(簡単な)方法はありますか?(理想的には、Boost.Signals2 が将来さらにパラメーターを追加する場合、変更する必要はありません。)

(また、C++11 は使用しないでください。まだ古いコンパイラを使用しています。)

4

1 に答える 1

0

私は次のことを考え出しました。これはトリックを行うようです。ただし、改善された回答にまだ興味があります。

namespace bs2 = boost::signals2;

template <
    typename Signature,
    typename A1 = boost::parameter::void_,
    typename A2 = boost::parameter::void_,
    typename A3 = boost::parameter::void_,
    typename A4 = boost::parameter::void_,
    typename A5 = boost::parameter::void_,
    typename A6 = boost::parameter::void_
  >
struct my_signal_type : public bs2::signal_type<Signature, A1, A2, A3, A4, A5, A6>
{
    typedef typename boost::parameter::value_type<args, bs2::keywords::tag::mutex_type, my_mutex>::type mutex_type;

    typedef bs2::signal<
        signature_type,
        combiner_type,
        group_type,
        group_compare_type,
        slot_function_type,
        extended_slot_function_type,
        mutex_type
    > type;
};

template <
    typename Signature,
    typename A1 = boost::parameter::void_,
    typename A2 = boost::parameter::void_,
    typename A3 = boost::parameter::void_,
    typename A4 = boost::parameter::void_,
    typename A5 = boost::parameter::void_,
    typename A6 = boost::parameter::void_
  >
class MyEvent : public my_signal_type<Signature, A1, A2, A3, A4, A5, A6>::type
{
public:
    typedef typename my_signal_type<Signature, A1, A2, A3, A4, A5, A6>::type base_type;

    explicit MyEvent(const typename base_type::combiner_type& combiner = combiner_type())
        : base_type(combiner)
    {
    }
};

少し困惑したことの 1 つは、コンストラクターで "combiner_type" を使用すると、型宣言で明示的なスコープが必要になる理由です。(ここで「typename」または「base_type::」のいずれかを削除すると、標準の「default-int」エラーがトリガーされます (これは、「それは私が知っている型のようには見えません」という意味です)。これは基本クラスで定義されているため、奇妙です。 . 私はそれがいくつかの奇妙なテンプレートの部分的なインスタンス化だと推測しています.

于 2012-06-19T07:50:13.150 に答える