编译时的C++类型注册技巧

Any*_*orn 10 c++ macros templates

我有以下情况:假设我有一堆类型(仿函数),我想在编译期间注册/编译,最好是像boost :: mpl :: vector.你知道这么做的诀窍吗?

我的愿望是拥有实现仿函数类型和注册文件的hpp文件,其中宏将类型引入编译.

例如

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

希望这是有道理的.谢谢

Rom*_*tsa 16

有一种方法可以逐个注册类型,然后以mpl :: vector或类似形式检索所有类型.我已经在提升邮件列表上学到了这个技巧(也许来自Dave Abrahams,虽然我无法回忆起来).

编辑:我是从https://github.com/boostcon/2011_presentations/raw/master/thu/Boost.Generic.pdf上的幻灯片28中学到的.

我不会在代码中使用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, "")
Run Code Online (Sandbox Code Playgroud)

用法示例:

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, "");
Run Code Online (Sandbox Code Playgroud)

  • @Cheersandhth.-Alf 你为什么这么认为?这段代码实际上所做的只是声明一个函数的新重载。我没有看到任何状态被修改。您不能考虑添加新的重载来修改状态,这意味着每个可能的程序都在修改某些状态。推理的最低代码:https://wandbox.org/permlink/ALpFkVQycMfEZNoG (2认同)