0

ソリューションは、gcc 4.2 および vs2012sp1 でコンパイル可能である必要があります。

コールバック システムを実装する必要があります。ID の代わりに型を操作できるように、さまざまなコールバックを CallbackMap 内の型として使用できる必要があります。ID は、さまざまなコンパイル時のチェックで使用されるため、コンパイル時の定数である必要があります。コールバックは ID によって「ルックアップ」できる必要があり、ルックアップは実行時に行われます。

追加の制約: ID 範囲を制御できなければなりません。たとえば、最初の ID は 20 です。また、id_type は size_t ではなく、16/32/64 ビットの整数である場合があります。

問題: この CallbackMap が成長するにつれて、それを変更した人は ID のカウントを間違ってしまうことが多くなっています。コンパイラにカウントしてもらいたいのですが、何らかの形でコールバックも登録してもらいたいです。

現在のソリューションの例:

#include <boost/signals2/signal.hpp>
#include <map>

typedef size_t id_type;
typedef boost::signals2::signal<void()> sig_type;

#define REGISTER_CALLBACK(NAME) cb_map_[NAME.ID] = &NAME;

struct CallbackBase
{
  sig_type sig;
};

template <id_type N>
struct Callback : CallbackBase
{
  static const size_t ID = N;
};

struct CallbackMap
{
  Callback<1> cb1;
  Callback<2> cb2;
  Callback<3> cb3;

  CallbackMap()
  {
    REGISTER_CALLBACK(cb1);
    REGISTER_CALLBACK(cb2);
    REGISTER_CALLBACK(cb3);
  }

  CallbackBase& GetCallback(id_type id)
  { // I know, no checks here..
    return *cb_map_.find(id)->second;
  }

private:
  std::map<id_type, CallbackBase*> cb_map_;
};

int main()
{
  CallbackMap cb;

  // Register handlers for callbacks
  // cb.cb1.sig.connect(...)

  int incomingRuntimeId = 2;
  cb.GetCallback(incomingRuntimeId).sig();

  return 0;
}

私はこのようなものが欲しいです(REGISTER_CALLBACKがなくても良いです):

struct CallbackMap
{
  DECLARE_CALLBACK(cb1);
  DECLARE_CALLBACK(cb2);
  DECLARE_CALLBACK(cb3);

  CallbackMap()
  {
    REGISTER_CALLBACK(cb1);
    REGISTER_CALLBACK(cb2);
    REGISTER_CALLBACK(cb3);
  }
  ...
};

私のデザインを完全に作り直したとしても、同様の使用法があれば、改善のためのすべての提案と同様に素晴らしいでしょう. ありがとう

4

0 に答える 0