C++编译时类的子类列表

标签 c++ templates compilation metaprogramming typetraits

我在考虑如何创建一个包含所有派生自模板基类的类的列表。

首先我想要一个模板基类:

template <typename T>
class Base
{
public:
    Base() {};
    virtual ~Base() {};
};

和一个继承自基模板类的类:

class Foo : public Base<Foo >
{
public:
    Foo () {};
    virtual ~Foo () {};
};

可能有任意数量的其他子类,如 Foo。结果应该是这样的:

std::vector<std::string> allTemplates = Base<Base>::getAllTemplateClasses();

我的问题是是否可以在编译时创建所有子类的列表?魔术应该在基类中发生,或者在子类中付出很少的努力。

我之前在不同的方向思考。首先我认为可以使用 constexpr。就像每个子类都需要一个带有签名的静态函数:

constexpr static std::string name() { "Foo";}

或者认为也许可以使用元编程并创建编译时间列表,例如 A Compile Time Data Structure Using,Template-Meta 的示例.这里的问题是我不知道模板创建的负责人。

接下来我正在考虑使用宏并以这种方式构建枚举结构 Enum structs expanding .所以我找不到这个问题的任何解决方案我想问你是否有可能?

编辑:

明确地说:我想要一个子对象列表,而不需要创建它们。

最佳答案

有了这个好帖子 static constructor并且已经有一个与此类似的答案,我能够找到解决方案。神奇的是静态构造函数。首先,我必须创建一个包含子类的容器并添加子类:

//base.h
std::set<std::string> &get_objects();
void add_object(const char *name);

和实现:

// base.cpp

std::set<std::string> &get_objects()
{
    static std::set<std::string> theSet;
    return theSet;
}

void add_object(const char *name)
{
    get_objects().emplace(name);
}

所以现在我们必须创建一个静态类来将字符串添加到列表中。它类似于帖子 static constructor :

//base.h
class StaticClassType {
public:
    StaticClassType(const char *name) {
        // Notify when the static member is created
        add_object(name);
    }
};

基类是一个模板类,它创建一个“StaticClassType”的静态对象。 C++ 保证在调用 main() 之前完成静态初始化。

//base.h
template<typename T>
class Base {
protected:
    // Static member in a template class
    static StaticClassType m;
    Base()
    {
        (void)m;
    }
};

如果没有下一行,m 就不会被创建:

template<typename T>
StaticClassType Base<T>::m = StaticClassType(typeid(T).name());

现在我们可以创建两个类和主要类:

class TestClass1 : public Base<TestClass1> {
public:
    TestClass1() :Base() {}
};

class TestClass1 : public Base<TestClass1> {
public:
    TestClass1() :Base() {}
};

int main()
{
    std::set<std::string> &test = get_objects();
    for(auto str : test)
        std::cout << str.c_str() << std::endl;
    return 0;
}

输出没有任何对象的构造:

class TestClass1
class TestClass2

有一个想法需要照顾。我们必须在某处使用 m 。否则,编译器正在优化代码并删除 m。我通过编写构造函数调用来强制执行此行为:

TestClass1() :Base() {}

希望你喜欢它,它不是真正的编译时间,但我们通过编写构造函数并使用 base 作为父类而无需执行任何操作就拥有了对象列表。

关于C++编译时类的子类列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34858341/

相关文章:

templates - 如何向 Sphinx 文档添加自定义页脚?

swift - 有没有办法让Swift编译器忽略错误?

java - 编译器对泛型方法的空参数的行为不同

c++ - 我如何在类声明之外实现我的显式覆盖?

c++ - qt创建动态对象并为同一信号分配不同的功能

c++ - XCode 附加进程/分离进程(以编程方式分离调试器)

c++ - 为什么删除模板复制构造函数会导致赋值运算符功能失调?

C++句柄/主体类自动由模板参数包组成。这可以改进吗?

c++ - int 和 double 变量的初始化

c++ - 内联调用 always_inline 失败 '__m128i _mm_cvtepu8_epi32(__m128i)' : target specific option mismatch _mm_cvtepu8_epi32 (__m128i __X)