Регистрация типа C ++ во время компиляции - PullRequest
10 голосов
/ 25 января 2011

У меня следующая ситуация: предположим, у меня есть куча типов (функторов), которые я хочу зарегистрировать / скомпилировать во время компиляции, предпочтительно в нечто вроде boost :: mpl :: vector.Знаете ли вы какой-нибудь трюк, чтобы сделать это красиво?

Я хочу иметь hpp-файл, который реализует тип функтора и файл регистрации, где макрос вводит тип в компиляцию.*

// registered.hpp
REGISTER("functor1.hpp") // implementation
REGISTER("functor2.hpp")
...
boost::mpl::vector<...> types; // full registration vector

Надеюсь, это имеет смысл.Спасибо

Ответы [ 3 ]

16 голосов
/ 07 февраля 2014

Существует способ зарегистрировать типы один за другим, а затем получить их все в форме mpl :: vector или аналогичной. Я научился этому трюку в списках рассылки буста (возможно, от Дейва Абрахамса, хотя точно не помню).

Редактировать: я узнал об этом из слайда 28 на https://github.com/boostcon/2011_presentations/raw/master/thu/Boost.Generic.pdf.

Я не буду использовать MPL в коде, чтобы сделать его самодостаточным.

// The maximum number of types that can be registered with the same tag.
enum { kMaxRegisteredTypes = 10 };

template <int N>
struct Rank : Rank<N - 1> {};

template <>
struct Rank<0> {};

// Poor man's MPL vector.
template <class... Ts>
struct TypeList {
  static const int size = sizeof...(Ts);
};

template <class List, class T>
struct Append;

template <class... Ts, class T>
struct Append<TypeList<Ts...>, T> {
  typedef TypeList<Ts..., T> type;
};

template <class Tag>
TypeList<> GetTypes(Tag*, Rank<0>) { return {}; }

// Evaluates to TypeList of all types previously registered with
// REGISTER_TYPE macro with the same tag.
#define GET_REGISTERED_TYPES(Tag) \
  decltype(GetTypes(static_cast<Tag*>(nullptr), Rank<kMaxRegisteredTypes>()))

// Appends Type to GET_REGISTERED_TYPES(Tag).
#define REGISTER_TYPE(Tag, Type)                              \
  inline Append<GET_REGISTERED_TYPES(Tag), Type>::type        \
  GetTypes(Tag*, Rank<GET_REGISTERED_TYPES(Tag)::size + 1>) { \
    return {};                                                \
  }                                                           \
  static_assert(true, "")

Пример использования:

struct IntegralTypes;
struct FloatingPointTypes;

// Initially both type lists are empty.
static_assert(std::is_same<GET_REGISTERED_TYPES(IntegralTypes), TypeList<>>::value, "");
static_assert(std::is_same<GET_REGISTERED_TYPES(FloatingPointTypes), TypeList<>>::value, "");

// Add something to both lists.
REGISTER_TYPE(IntegralTypes, int);
REGISTER_TYPE(FloatingPointTypes, float);
static_assert(std::is_same<GET_REGISTERED_TYPES(IntegralTypes), TypeList<int>>::value, "");
static_assert(std::is_same<GET_REGISTERED_TYPES(FloatingPointTypes), TypeList<float>>::value, "");

// Add more types.
REGISTER_TYPE(IntegralTypes, long);
REGISTER_TYPE(FloatingPointTypes, double);
static_assert(std::is_same<GET_REGISTERED_TYPES(IntegralTypes), TypeList<int, long>>::value, "");
static_assert(std::is_same<GET_REGISTERED_TYPES(FloatingPointTypes), TypeList<float, double>>::value, "");
0 голосов
/ 25 января 2011

Вы никогда не решите идею mpl :: vector. Вы не можете изменить шаблон "переменные". Помните, что шаблонное метапрограммирование - это чистый функциональный язык. Никаких побочных эффектов.

Что касается регистрации ... макрос работает нормально. Определите макрос так, чтобы он объявлял и инициализировал небольшую глобальную переменную в процессе регистрации. В качестве альтернативы вы можете пойти по дороге, которую я сделал здесь:

Как принудительно включить определения "неиспользуемых" объектов в библиотеку

Обратите внимание на исправление, если вы пытаетесь сделать это в библиотеке.

0 голосов
/ 25 января 2011

Я бы не использовал макросы. Обычная техника - просто определить некоторый объект, инициализация которого выполняет регистрацию. Подводный камень: вам нужно сослаться на что-то, например, вызовите функцию в модуле компиляции, чтобы связать ее.

Приветствия и hth.,

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...