2

これらの宣言と定義がある場合:

enum Events
{
  INIT,
  RENDER
};

struct EventBase
{
  typedef void (EventBase::*event_callback_type)();

  ~EventBase() {}

  virtual void init() { assert(0); }
  virtual void render() { assert(0); }
};

template <enum Events>
struct EventTraits
{
  static EventBase::event_callback_type const event_callback;
};

// in a .cpp file
template <>
EventBase::event_callback_type const
EventTraits<INIT>::event_callback(
  &EventBase::init);

template <>
EventBase::event_callback_type const
EventTraits<RENDER>::event_callback(
  &EventBase::render);

// in another class *i are pointers to objects that inherit EventBase
template <enum Events event>
inline void EventNotifier::notify()
{
  for (events_type::const_iterator i(event_handlers[event].begin());
    i != event_handlers[event].begin() + num_event_handlers[event];
    ++i)
  {
    ((*i)->*EventTraits<event>::event_callback)();

    if ((*i)->num_event_handlers[event])
    {
      (*i)->notify<event>();
    }
    // else do nothing
  }
}

イベントRENDERが可能な限り最速の処理を必要としているとすると、メンバーテンプレートの特殊化を行う価値があると思いますか。

template <>
inline void EventNotifier::notify<RENDER>()
{
  for (events_type::const_iterator i(event_handlers[RENDER].begin());
    i != event_handlers[RENDER].begin() + num_event_handlers[RENDER];
    ++i)
  {
    (*i)->render();

    if ((*i)->num_event_handlers[RENDER])
    {
      (*i)->notify<RENDER>();
    }
    // else do nothing
  }
}

これには、メンバー関数への静的ポインターのフェッチは必要ありません。または、おそらく私はこれを行う必要があります:

template <enum Events>
struct EventTraits
{
  static EventBase::event_callback_type event_callback();
};

そして、構造体テンプレートを専門にしますか?

4

2 に答える 2

2

わずか5セント追加。EventNotifier::notify() は完全にスレッドセーフではないように見えます。さらに、イベント ハンドラーが新しいイベントを生成すると、悪いことが起こる可能性があります。この方法で通知を行うことをお勧めします(C++ 11、すべてのタイプを知らないだけです):

template <> inline void EventNotifier::notify<RENDER>()
{
  decltype(event_handlers[RENDER]) local;
  decltype(num_event_handlers[RENDER]) local_num;

  {
    std::lock_guard<std::mutex> guard(my_mutex);
    local = event_handlers[RENDER];
    local_num = num_event_handlers[RENDER];
  }

  for (events_type::const_iterator i(local.begin()); i != local.begin() + local_num; ++i)
  {
    (*i)->render();

    if ((*i)->num_event_handlers[RENDER]) (*i)->notify<RENDER>();
  }
}
于 2012-05-22T10:27:44.020 に答える
1

メンバーの特殊化は、コンパイラーが生成するコードと同じように記述したコードであるため、現在の形式に違いはありません。

ここに小さな改善があります:

template <enum Events event>
inline void EventNotifier::notify()
{
  for (events_type::const_iterator i(event_handlers[event].begin()),
       end (event_handlers[event].begin() + num_event_handlers[event]);
       i != end; ++i)
  {
    ((*i)->*EventTraits<event>::event_callback)();

    if ((*i)->num_event_handlers[event])
    {
      (*i)->notify<event>();
    }
    // else do nothing
  }
}
于 2012-05-22T10:51:17.513 に答える