class 的子 classes 的 C++ 编译时间列表
C++ Compile time list of subclasses of a class
我在考虑如何创建一个列表,其中包含从模板库 class 派生的所有 class。
首先我想要一个模板 Base class:
template <typename T>
class Base
{
public:
Base() {};
virtual ~Base() {};
};
和一个 class 继承自基础模板 class:
class Foo : public Base<Foo >
{
public:
Foo () {};
virtual ~Foo () {};
};
可能有任意数量的其他子class像Foo
。结果应该类似于:
std::vector<std::string> allTemplates = Base<Base>::getAllTemplateClasses();
我的问题是是否可以在编译时创建所有 sub-classes 的列表?魔术队应该在基地 class 或在 child class 中付出很少的努力。
我之前在不同的方向思考。首先我认为可以使用 constexpr
。就像每个 child class 都需要一个带有签名的静态函数:
constexpr static std::string name() { "Foo";}
或者认为也许可以使用元编程并创建编译时列表,如 A Compile Time Data Structure Using,Template-Meta 的示例。这里的问题是我不知道模板创建的负责人。
接下来我正在考虑使用宏并以这种方式构建枚举结构 Enum structs expanding。所以我找不到这个问题的任何解决方案我想问你是否可能?
编辑:
说清楚:我想要 child objects 的列表,不需要创建它们。
有了这个很好的 post static constructor 和一个已经与这个相似的答案,我找到了一个解决方案。神奇的是静态构造函数。首先,我必须创建一个容器来容纳 subclass 并添加 subclasses:
//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);
}
所以现在我们必须创建一个静态 class 来将字符串添加到列表中。它类似于 post static constructor:
//base.h
class StaticClassType {
public:
StaticClassType(const char *name) {
// Notify when the static member is created
add_object(name);
}
};
基础 class 是一个模板 class,它创建 '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());
现在我们可以创建两个 classes 和主要的:
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 作为父对象而没有做任何事情就得到了对象列表 class。
我在考虑如何创建一个列表,其中包含从模板库 class 派生的所有 class。
首先我想要一个模板 Base class:
template <typename T>
class Base
{
public:
Base() {};
virtual ~Base() {};
};
和一个 class 继承自基础模板 class:
class Foo : public Base<Foo >
{
public:
Foo () {};
virtual ~Foo () {};
};
可能有任意数量的其他子class像Foo
。结果应该类似于:
std::vector<std::string> allTemplates = Base<Base>::getAllTemplateClasses();
我的问题是是否可以在编译时创建所有 sub-classes 的列表?魔术队应该在基地 class 或在 child class 中付出很少的努力。
我之前在不同的方向思考。首先我认为可以使用 constexpr
。就像每个 child class 都需要一个带有签名的静态函数:
constexpr static std::string name() { "Foo";}
或者认为也许可以使用元编程并创建编译时列表,如 A Compile Time Data Structure Using,Template-Meta 的示例。这里的问题是我不知道模板创建的负责人。
接下来我正在考虑使用宏并以这种方式构建枚举结构 Enum structs expanding。所以我找不到这个问题的任何解决方案我想问你是否可能?
编辑:
说清楚:我想要 child objects 的列表,不需要创建它们。
有了这个很好的 post static constructor 和一个已经与这个相似的答案,我找到了一个解决方案。神奇的是静态构造函数。首先,我必须创建一个容器来容纳 subclass 并添加 subclasses:
//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);
}
所以现在我们必须创建一个静态 class 来将字符串添加到列表中。它类似于 post static constructor:
//base.h
class StaticClassType {
public:
StaticClassType(const char *name) {
// Notify when the static member is created
add_object(name);
}
};
基础 class 是一个模板 class,它创建 '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());
现在我们可以创建两个 classes 和主要的:
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 作为父对象而没有做任何事情就得到了对象列表 class。