Как выполнить сканирование типов в C ++? - PullRequest
3 голосов
/ 26 апреля 2011

У меня есть ESB . Любое сериализованное сообщение переносит свое собственное полностью определенное имя (то есть пространство имен + имя класса). У меня есть конкретный тип для каждого сообщения, которое инкапсулирует конкретную логику для выполнения.
Каждый раз, когда я получаю сообщение, мне сначала нужно его десериализовать, чтобы я мог выполнять его операции - и больше, в зависимости от его конкретного типа -.

Мне нужен способ регистрации каждого отдельного класса во время компиляции или во время инициализации приложения.
С .net я бы использовал отражение для сканирования сборок и обнаружения типов сообщений во время инициализации, но как бы вы сделали это в C ++?

Ответы [ 3 ]

3 голосов
/ 26 апреля 2011

C ++ не имеет возможности отражения.Я полагаю, вы могли бы попытаться проверить объектные файлы и т. Д., Но нет надежного способа сделать это (AFAIK);компилятор может полностью исключить или исказить некоторые вещи.

По существу, для сериализации вам нужно будет выполнить (полу) регистрацию вручную.Но вас может заинтересовать библиотека сериализации, которая поможет с рутинной работой, например Boost Serialization .

1 голос
/ 26 апреля 2011

Я лично пользуюсь ручной регистрацией дороги. Если вы забыли зарегистрироваться ... то тест все равно не работает.

Вам просто нужно использовать фабрику и реализовать некоторую диспетчеризацию тегов. Например:

typedef void (*ActOnMessageType)(Message const&);

typedef std::map<std::string, ActOnMessageType> MessageDispatcherType;

static MessageDispatcherType& GetDispatcher() {
  static MessageDispatcherType D; return D;
}

static bool RegisterMessageHandler(std::string name, ActOnMessageType func) {
  return GetDispatcher().insert(std::make_pair(name, func)).second;
}

Тогда вы просто подготовите свои функции:

void ActOnFoo(Message const& m);
void ActOnBar(Message const& m);

И зарегистрируйте их:

bool const gRegisteredFoo = RegisterMessageHandler("Foo", ActOnFoo);
bool const gRegisteredBar = RegsiterMessageHandler("Bar", ActOnBar);

Примечание: я эффективно использую лениво инициализированный синглтон, чтобы разрешить развязку. То есть регистрация выполняется во время загрузки библиотеки и, таким образом, каждый вызов Register... помещается в файл, в котором определена функция. Единственное отличие от глобальной переменной заключается в том, что здесь карта диспетчеризации фактически постоянна после завершения инициализации.

1 голос
/ 26 апреля 2011

Поскольку в C ++ нет отражения, я бы предложил использовать внешний сценарий для сканирования вашего исходного кода на предмет всех соответствующих классов (что легко, если вы используете пустой фиктивный #defines, чтобы комментировать их в исходном коде) и генерировать егорегистрационный код.

...