Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;类的子类的编译时列表_C++_Templates_Compilation_Metaprogramming_Typetraits - Fatal编程技术网

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

C++ C++;类的子类的编译时列表,c++,templates,compilation,metaprogramming,typetraits,C++,Templates,Compilation,Metaprogramming,Typetraits,我在考虑如何创建从模板基类派生的所有类的列表 首先,我想要一个模板基类: template <typename T> class Base { public: Base() {}; virtual ~Base() {}; }; 我的问题是,是否可以在编译时创建所有子类的列表?魔法应该发生在基础课上,或者在儿童课上花一点功夫 我以前是从不同的方向思考的。首先,我认为可以使用constexpr。像每个子类一样,需要一个带有签名的静态函数: constexpr stati

我在考虑如何创建从模板基类派生的所有类的列表

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

template <typename T>
class Base
{
public:
    Base() {};
    virtual ~Base() {};
};
我的问题是,是否可以在编译时创建所有子类的列表?魔法应该发生在基础课上,或者在儿童课上花一点功夫

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

constexpr static std::string name() { "Foo";}
或者认为也许可以使用元编程创建一个编译时列表,如的示例。这里的问题是,我不知道模板创建的负责人

接下来,我考虑使用宏并以这种方式构建枚举结构。所以我找不到任何解决这个问题的方法我想问你这是否可能

编辑:

说得很清楚:我想要一个子对象列表,而不需要创建它们。

有了这篇漂亮的文章和一个与此类似的答案,我能够找到一个解决方案。神奇的是静态构造函数。首先,我必须创建一个包含子类的容器,并添加子类:

//base.h
std::set<std::string> &get_objects();
void add_object(const char *name);
基类是一个模板类,它创建一个“StaticClassType”的静态对象。C++保证在调用主()之前完成静态初始化。
//base.h
template<typename T>
class Base {
protected:
    // Static member in a template class
    static StaticClassType m;
    Base()
    {
        (void)m;
    }
};
现在我们可以创建两个类和主类:

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;
}
有一个想法需要考虑。我们必须在某个地方使用
m
。否则,编译器将优化代码并删除
m
。我通过编写构造函数调用强制执行此行为:

TestClass1() :Base() {}

希望您喜欢它,它不是真正的编译时,但我们有对象列表,不做任何事情,编写构造函数并使用base作为父类。

好的,我删除了我的答案,因为它不太有效。缺少的部分是这里描述的:<代码> /C++ +需要在外部定义静态成员。has_static_构造函数::构造函数has_static_构造函数::cons注册器对象实际上不是在静态初始化中构造的,因为当它出现在模板类中时,它只是一个声明而不是定义。我仍然认为这种静态注册的方式是可行的,但是你需要用宏afaik做一些丑陋的事情。(宏的要点是,当您将一个类声明为这个基类的子类时,您还希望在类定义之外声明一个
静态
注册器类型的对象,该对象的构造函数注册了它的名称,宏应该帮助确保这两件事同时发生无论如何,这都是值得写的。)作为补充意见——如果有一种优雅的方法可以做到这一点,我会很感兴趣,但现在我不敢打赌真的有。感谢你们的努力,我是如何说我在思考不同的方向,但没有人真的有帮助。我认为这是一个很好的问题,但没有很好的解决办法。:)我想它可能会被提升一点。谢谢你的帮助@Chris Beck和你的想法,我找到了一些解决方案。虽然这是一个很好的解决你的问题的方案,但实际上这不是一个“编译时”解决方案。该列表是在运行时生成的,即使正如您所说,它在执行main之前运行。
//base.h
class StaticClassType {
public:
    StaticClassType(const char *name) {
        // Notify when the static member is created
        add_object(name);
    }
};
//base.h
template<typename T>
class Base {
protected:
    // Static member in a template class
    static StaticClassType m;
    Base()
    {
        (void)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
TestClass1() :Base() {}