在编译时构建和访问类型列表

Ale*_*int 10 c++ template-meta-programming

我试图使用c ++模板元编程实现以下功能.我希望建立一个类型列表,然后一起收集这些类型,并在列表上进行进一步的编译时处理.例如:

foo.h中:

class Foo { ... };
// INSERT ANY CODE HERE
Run Code Online (Sandbox Code Playgroud)

bar.h:

class Bar { ... };
// INSERT ANY CODE HERE
Run Code Online (Sandbox Code Playgroud)

main.h:

#include "foo.h"
#include "bar.h"

struct list_of_types {
  typedef /* INSERT ANY CODE HERE */ type;
};
Run Code Online (Sandbox Code Playgroud)

我可以在上面的插槽中插入任何代码,只要list_of_types :: type解析为包含类型Foo和Bar的列表的某些表示(例如boost :: mpl :: vector).以下限制适用:

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

  2. 如果我包含更多类型添加到列表中的标题,则main.h中的代码不应该更改.

  3. 类型列表必须在编译时可用.我打算进一步进行涉及清单的元编程.

小智 18

利用通用头,可变参数模板和宏的解决方案:

// 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
Run Code Online (Sandbox Code Playgroud)
// Header foo.h
#include <common.h>

class Foo { };

typedef typename concat<TYPE_LIST, Foo>::type TypeListFoo;
#undef TYPE_LIST
#define TYPE_LIST TypeListFoo
Run Code Online (Sandbox Code Playgroud)
// Header bar.h
#include <common.h>

class Bar { };

typedef typename concat<TYPE_LIST, Bar>::type TypeListBar;
#undef TYPE_LIST
#define TYPE_LIST TypeListBar
Run Code Online (Sandbox Code Playgroud)
// 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;
}
Run Code Online (Sandbox Code Playgroud)