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() {}