【问题标题】:Efficient way to define an introspective C++ class hierararchy description ?定义内省 C++ 类层次结构描述的有效方法?
【发布时间】:2012-05-16 13:03:15
【问题描述】:

我有一个由继承定义的 C++ 类层次结构,我在其中存储了这个层次结构的描述,以后可以用于自省。我想知道是否有比我目前的方式更有效或更清洁的方式来定义它。 这是我的代码的精简版

// in header file (hpp)
struct Type
{
    Type( const string& n, const Type* p = nullptr ) : name(n), parent(p) {}
    const string name;
    const Type* parent;
};

class Base
{
public:
    static const Type m_type;
    virtual const Type& type() const { return m_type; } 
};

class Derived : public Base
{
public:
    static const Type m_type;
    const Type& type() const { return m_type; }
};

// in implementation file (cpp)
const Type Base::m_type( "Base" );
const Type Derived::m_type( "Derived", &Base::m_type );

【问题讨论】:

  • 你总是只有一个基类吗?
  • 是的,对于我使用它的类。你是对的,它应该被修复以覆盖多重继承。

标签: c++ introspection


【解决方案1】:

不一定更有效,但请考虑您是否真的需要一个公共基类。另一种方法使用全局类型信息注册表。然后通过TypeInfo::get(my_variable)TypeInfo::get(typeid(my_type))查询一个类型的类型信息。

这样做的好处是它也适用于现有类型,只需将其添加到此类型信息注册表中即可。

在内部,注册表将使用从 std::type_infoType 或类似的映射。以下是概念证明。不幸的是,代码不能在 clang 或 GCC 上编译。根据错误消息,我怀疑是一个错误,但我也可能是错的……

struct Type {
    std::string name;
    std::vector<Type*> parents;
    // TODO Extend by fully-qualified name (namespace) etc.

    template <typename... T>
    Type(std::string&& name, T*... parents)
        : name(name), parents{parents...} { }
};

struct TypeInfo {
    template <typename T>
    static Type const& get(T const&) { return get(typeid(T)); }

    template <typename T>
    static Type const& get() { return get(typeid(T)); }

    static Type const& get(std::type_info const& info) {
        auto i = types.find(info);
        if (i == types.end())
            throw unknown_type_error(info.name());

        return i->second;
    }

    template <typename T>
    static void register_type(Type&& type) {
        types.insert(std::make_pair(typeid(T), type));
    }

    typedef std::unordered_map<std::type_info, Type> type_dir_t;
    static type_dir_t types;
};

完整代码as gist on github.

在 C++ 中通常不赞成为逻辑上不相关的类使用公共基类,尽管可以说这类似于 CRTP / mixins,其中鼓励使用公共基类。所以我想说,如果你不关心现有类型,这种方法不一定有什么问题。

【讨论】:

  • 同意缺少对多重继承的支持。您将如何使用类型名称填充全局类型信息注册表?您能否提供更详细的代码示例?你的想法看起来很有趣。
  • @chmike 查看更新。 ——我什至没有提到多重继承。 ;-) 但是,是的,这当然是缺失的。以及命名空间信息等:)
  • @chmike 此外,您应该考虑用例。目前,这比std::type_info 提供的价值不多,但我想你已经意识到这一点,并有意简化了问题的代码示例。
  • 它很有价值,因为我想保持控制并确保类型名称的可移植性。 type_info 不可移植。用例是在配置文件中定义一些对象网络并在运行时实例化它。配置文件需要人类可读可写,并在编译器更改时保持有效。
  • @chmike 我同意。我只是想说明这一点。 (仅供参考,我计划开发类似的东西已经有一段时间了。你的问题实际上给了我动力,让我把我的想法变成一个更具体的形式......不幸的是,我目前没有时间进一步追求这个......)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-19
  • 1970-01-01
  • 2020-11-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多