私はこれを念頭に置いて掲示しています。それは長いポストになります。 私はイベントシステムを作成しています。イベントを1か所に登録したいのです。
----- ----- Event.h
typedef int EventAddress;
typedef int EventId;
typedef int EventType;
static const EventAddress EVENT_FROM_ALL=-1;
static const EventAddress EVENT_TO_ALL=-1;
static const EventId EVENT_ID_INITIAL=-1;
static const EventType EVENT_TYPE_INITIAL=-1;
static const EventId EVENT_ID_ALL=0;
static const EventType EVENT_TYPE_ALL=0;
struct Event
{
public:
EventId eventId;
EventType eventType;
EventAddress from;
Event(const EventId eventId, const EventType eventType):
eventId(eventId),
eventType(eventType)
{
}
virtual ~Event()
{
}
virtual std::string asString()=0;
private:
Event();
};
template <class T>
struct EventBase
:public Event
{
static int EVENT_ID;
static int EVENT_TYPE;
EventBase():
Event(EVENT_ID,EVENT_TYPE)
{
}
};
template <class T>
int EventBase<T>::EVENT_ID=EVENT_ID_INITIAL;
template <class T>
int EventBase<T>::EVENT_TYPE=EVENT_TYPE_INITIAL;
/// Events All
struct EventAll:
public Event
{
static int EVENT_ID;
static int EVENT_TYPE;
EventAll():
Event(EVENT_ID,EVENT_TYPE)
{
}
virtual std::string asString()
{
return __PRETTY_FUNCTION__;
}
};
----- ----- Event.cpp
#include "Event.h"
int EventAll::EVENT_ID=EVENT_ID_ALL;
int EventAll::EVENT_TYPE=EVENT_TYPE_ALL;
------ EventGenerator.h ------
struct EventIdGenerator
{
int generator;
EventIdGenerator():
generator(0)
{
}
};
template <class T, class Base>
struct UnitId:
virtual public Base,
public T
{
UnitId()
{
++Base::generator;
T::EVENT_ID=Base::generator;
}
};
struct EventTypeGenerator
{
static int generator;
};
template <class T, class Base>
struct UnitType:
virtual public Base,
public T
{
UnitType()
{
T::EVENT_TYPE=Base::generator;
}
};
----- ----- EventGenerator.cpp
#include "EventGenerator.h"
int EventTypeGenerator::generator=0;
ではなく、楽しいもの...
----- ----- EventsTank.h
#include <loki/Typelist.h>
#include <loki/HierarchyGenerators.h>
#include "Event.h"
#include "EventGenerator.h"
#define EVENT_CONTEXT__ Tank
#define EVENT_NAME__ EventTank1
struct EVENT_NAME__:
public EventBase<EVENT_NAME__>
{
std::string s;
double b;
void f()
{
}
virtual std::string asString()
{
return __PRETTY_FUNCTION__;
}
};
#undef EVENT_NAME__
#define EVENT_NAME__ EventTank2
struct EVENT_NAME__:
public EventBase<EVENT_NAME__>
{
std::string s;
double b;
void f()
{
}
virtual std::string asString()
{
return __PRETTY_FUNCTION__;
}
};
#undef EVENT_NAME__
#define EVENT_NAME__ EventTank3
struct EVENT_NAME__:
public EventBase<EVENT_NAME__>
{
std::string s;
double b;
void f()
{
}
virtual std::string asString()
{
return __PRETTY_FUNCTION__;
}
};
#undef EVENT_NAME__
#define TOKENPASTE(x, y, z) x ## y ## z
#define TOKENPASTE2(x, y, z) TOKENPASTE(x, y, z)
#define EVENTS_ALL__ TOKENPASTE2(Events,EVENT_CONTEXT__,All)
template <typename...Ts>
struct TYPELIST;
template <>
struct TYPELIST<>
{
typedef Loki::NullType Result;
};
template <typename HEAD, typename...Ts>
struct TYPELIST<HEAD,Ts...>
{
typedef Loki::Typelist<HEAD, typename TYPELIST<Ts...>::Result> Result;
};
typedef TYPELIST<
EventTank1,
EventTank2,
EventTank3
>::Result EVENTS_ALL__;
/// Do not change below---------------------------------------------------------------------
#define EVENT_CONTEXT_ALL__ TOKENPASTE2(Event,EVENT_CONTEXT__,All)
struct EVENT_CONTEXT_ALL__:
public EventBase<EVENT_CONTEXT_ALL__>
{
virtual std::string asString()
{
return __PRETTY_FUNCTION__;
}
};
#define EVENT_ALL_REVERSED__ TOKENPASTE2(Event,EVENT_CONTEXT__,AllReversed)
typedef Loki::TL::Reverse<EVENTS_ALL__>::Result EVENT_ALL_REVERSED__;
#define EVENT_ALL_REVERSED_FIRST__ TOKENPASTE2(Event,EVENT_CONTEXT__,AllReversedFirst)
typedef Loki::TL::TypeAt<EVENTS_ALL__,0>::Result EVENT_ALL_REVERSED_FIRST__;
template <class Base>
struct UnitType<EVENT_ALL_REVERSED_FIRST__,Base>:
virtual public Base,
public EVENT_ALL_REVERSED_FIRST__
{
typedef EVENT_ALL_REVERSED_FIRST__ T;
UnitType()
{
std::cout << __PRETTY_FUNCTION__ << std::endl;
++Base::generator;
T::EVENT_TYPE=Base::generator;
EVENT_CONTEXT_ALL__::EVENT_ID=EVENT_ID_ALL;
EVENT_CONTEXT_ALL__::EVENT_TYPE=Base::generator;
}
};
#define ALL_CONTEXT_EVENTS__ TOKENPASTE2(All,EVENT_CONTEXT__,Events)
typedef Loki::GenLinearHierarchy<EVENT_ALL_REVERSED__,UnitType,EventTypeGenerator> ALL_CONTEXT_EVENTS__;
#undef ALL_CONTEXT_EVENTS__
#undef EVENT_ALL_REVERSED__
#undef EVENT_ALL_REVERSED_FIRST__
#undef EVENT_NAME_ALL__
#undef EVENTS_ALL__
----- ----- EventsTank.cpp
#include "EventsTank.h"
AllTankEvents allTankEvents;
----- ----- EventRegisterer.cpp
#include <loki/Typelist.h>
#include <loki/HierarchyGenerators.h>
#include "../core/Event.h"
#include "EventsTank.h"
typedef Loki::GenLinearHierarchy<Loki::TL::Reverse<EventsTankAll>::Result,UnitId,EventIdGenerator> AllEvents;
AllEvents allEvents;
これはコードがたくさんあるので、私は要約しようとします。 私は基本クラスEventBase
を持っています。このクラスは2人の重要なメンバー: EVENT_ID
とEVENT_TYPE
を持っています。私がやっていることは、2つのクラスをメタ作成することです:AllTankEventsは、instatiationでTankEventsのEVENT_TYPEを初期化し、AllEventsはEVENT_IDを初期化します。 このような邪魔者は、別のタンクイベント定義を追加し、それをタイプリストEVENTS_ALL__
に追加する必要があります。 if (event.EVENT_ID==EventTank1::EVENT_ID)
などのコードでイベントを送出することができます。 他のコードは、EVENT_ID/EVENT_TYPE
については、EVENT_ID_INITIAL/EVENT_TYPE_INITIAL
とassert
で初期化されています。 Cプリプロセッサマクロを恐れてはいけません。彼らはただの砂糖なので、私はいくつかのタスクを自動化することができます。 見て、私は今行く必要があります。
は静的IDですか、ソリューションの一部だと思ってそこに配置しましたか?この問題に対する理想的な解決法はおそらくこれらのIDを必要とせず、代わりに型システムに依存するでしょう。つまり、クラス名自体が一意の静的識別子として機能します。 – wilhelmtell
私はRTTIを避け、C++内にとどまっています。 –
@ DanM.Katz:多分私はあなたが望むものを作った。あなたがまだ興味があるなら、ここに投稿してください。 –