如何维护从基类派生的所有类型的编译时列表?

时间:2014-07-31 01:26:18

标签: c++ boost

有人提出了一个类似的问题,即维护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循环的可怕混合来自动执行此过程,但我希望避免使用宏来尽可能保持代码库的可维护性。

有什么建议吗?

编辑:解决方案必须完全是编译时,即使没有实例化任何类型,也必须正常工作。

1 个答案:

答案 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