在编译时build立和访问types列表

我想要实现以下使用C ++模板元编程。 我希望build立一个types列表,然后把这些types一起收集起来,并在列表中进一步编译处理。 举个例子:

foo.h中:

class Foo { ... }; // INSERT ANY CODE HERE 

bar.h:

 class Bar { ... }; // INSERT ANY CODE HERE 

main.h:

 #include "foo.h" #include "bar.h" struct list_of_types { typedef /* INSERT ANY CODE HERE */ type; }; 

我可以插入任何代码到上面的插槽中,只要list_of_types :: typeparsing为包含typesFoo和Bar的列表的某种表示(例如boost :: mpl :: vector)。 以下限制适用:

  1. foo.h中的代码不应该知道bar.h中的代码,反之亦然。 应该可以改变main.h中的#include指令的顺序,而不是更改任何其他代码。

  2. 在main.h中的代码不应该改变,如果我进一步包含进一步的头添加到列表中的types。

  3. types列表必须在编译时可用。 我打算进行进一步的元编程,涉及这个列表。

利用通用标题,可变参数模板和macros的解决scheme:

 // Header common.h // A distinct Void type struct Void {}; template <typename ...> struct concat; template <template <typename ...> class List, typename T> struct concat<List<Void>, T> { typedef List<T> type; }; template <template <typename ...> class List, typename ...Types, typename T> struct concat<List<Types...>, T> { typedef List<Types..., T> type; }; template <typename...> struct TypeList {}; template <> struct TypeList<Void> {}; typedef TypeList<Void> TypelistVoid; #define TYPE_LIST TypelistVoid // Header foo.h // #include <common.h> class Foo { }; typedef typename concat<TYPE_LIST, Foo>::type TypeListFoo; #undef TYPE_LIST #define TYPE_LIST TypeListFoo // Header bar.h // #include <common.h> class Bar { }; typedef typename concat<TYPE_LIST, Bar>::type TypeListBar; #undef TYPE_LIST #define TYPE_LIST TypeListBar // Header main.h // #include "foo.h" // #include "bar.h" struct list_of_types { typedef TYPE_LIST type; }; // Or just typedef TYPE_LIST list_of_types; // Test #include <iostream> #include <typeinfo> template <template <typename ...> class List, typename T, typename ...Types> void info(); template <typename T, typename ...Types> inline void info(TypeList<T, Types...>) { std::cout << typeid(T).name() << std::endl; info(TypeList<Types...>()); } template <typename T> inline void info(TypeList<T>) { std::cout << typeid(T).name() << std::endl; } int main() { info(list_of_types::type()); return 0; }