有人提出了一个类似的问题,即维护c#
的类型的运行时列表:
How can I store and use an array of different types derived from a common base type?
基本上我想要的是维护一系列从公共基类派生的类型名称。我可以通过执行以下操作在运行时实现此目的:
std::vector v;
template <typename Derived>
class Base
{
Base() { v.push_back(typeid(Derived).name())
};
如果所有派生类都是单例,但有运行时开销,则此方法有效。如果他们不是单身人士,我可以添加一些检查以避免重复,但它仍然涉及运行时成本。我想的是填充类型序列,例如boost::mpl_vector
:
class Derived1 : public Base<Derived1> {}
class Derived2 : public Base<Derived2> {}
class Derived3 : public Base<Derived3> {}
typedef boost::mpl::vector<
Derived1,
Derived2,
Derived3> TypeSequence;
这有效,但这意味着我必须手动维护列表,这对许多类型来说都很麻烦。我知道我可以使用boost preprocessor
循环的可怕混合来自动执行此过程,但我希望避免使用宏来尽可能保持代码库的可维护性。
有什么建议吗?
编辑:解决方案必须完全是编译时,即使没有实例化任何类型,也必须正常工作。
答案 0 :(得分:2)
注意:这个答案是在#34之前编写的;解决方案必须完全是编译时的,即使没有实例化类型也必须正常工作。&#34;被添加到问题中。
虽然这不是在编译时计算的,但每种类型的名称只添加一次。您必须创建至少一个每种类型的实例才能工作(aka。未实例化的类型将不会添加到容器中)
#include <iostream>
#include <vector>
#include <string>
struct TypeBase{
static std::vector<std::string> m_container;
};
std::vector<std::string> TypeBase::m_container;
template <typename DerivedType>
struct MyBase{
MyBase(){
static bool typeAdded = false;
if(!typeAdded){
typeAdded = true;
// you may also want to demangle this name
// take a look at boost/units/detail/utility.hpp
TypeBase::m_container.push_back(typeid(DerivedType).name());
}
}
};
struct Derived1 : public MyBase<Derived1>{
};
struct Derived2 : public MyBase<Derived2>{
};
struct Derived3 : public MyBase<Derived3>{
};
int main(){
Derived1 a, b, c;
Derived2 d, e, f;
Derived3 g, h, i;
for(std::string const & name : TypeBase::m_container){
std::cout << name << std::endl;
}
std::cin.get();
}
使用我的编译器打印:
struct Derived1
struct Derived2
struct Derived3