3

我想实现一个存储不同类型对象的目录对象。需要能够按名称访问对象,获取实际的指针类型并将其序列化。我想到的对象是这样的:

struct Object {
    std::string name;
    SomeType ptr;
};
struct Dir {
  std::string name;
  std::set<Object> objects;
};

“SomeType”我正在考虑使用 Boost::variant。但是似乎我需要在运行时将对象类型添加到变体列表中。即使我知道前面目录中的对象类型,它也会变成

template <typename Typelist>
struct Object<Typelist> {
    std::string name;
    boost::variant<Typelist> objects;
};

不同的目录在哪里Typelist是不同的。那么,拥有一个 dirs 的目录就是 Typelist 的动态联合。看起来很复杂。它很快就会达到 50 种变体类型的限制。替代方案是 Boost::Any 以简化语义。但我想迭代对象集,并对其进行处理——每个对象都是一个 boost::fusion adapt_struct——我想对每个对象的每个成员进行 fusion::for_each 并显示它们,例如。有什么替代方案或建议吗?

4

2 回答 2

2

一切都取决于您需要多少不同的类型以及什么样的性能。如果对象类型的数量有限,那么最好使用一个公共基类,并为每种类型专门化。

下面的代码使用了boost::shared_ptr相关的强制转换功能。boost::shared_dynamic_cast可用于在基本类型和专用类型之间来回转换。

#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>
#include <iostream>
#include <list>

namespace stackoverflow
{

struct base_object
{
    enum type_t
    {
        directory = 0, file, link,

        n_types
    };

    const std::string name;
    const type_t type;

    base_object(const std::string& name, const type_t& type) :
            name(name), type(type) {
    }

    virtual ~base_object()
    {
    }
};

struct file_object : public base_object
{
    file_object(const std::string& name) : base_object(name, base_object::file)
    {
    }
};

struct symlink_object : public base_object
{
    symlink_object(const std::string& name) : base_object(name, base_object::link)
    {
    }
};

struct directory_object: public base_object
{
    std::list<boost::shared_ptr<base_object> > children;

    directory_object(const std::string& name) :
            base_object(name, base_object::directory)
    {
    }

    template < typename TypeTag >
    boost::shared_ptr< typename TypeTag::object_type > add(const std::string& name);
};

template < typename ObjectType >
struct tag
{
    typedef ObjectType object_type;
};

typedef tag< directory_object > directory;
typedef tag< file_object > file;
typedef tag< symlink_object > symlink;

template < typename TypeTag >
boost::shared_ptr< typename TypeTag::object_type > directory_object::add(const std::string& name)
{
    return boost::shared_dynamic_cast< typename TypeTag::object_type , base_object >(
            *children.insert(children.end(),
                    boost::shared_dynamic_cast< base_object, typename TypeTag::object_type >(
                            boost::make_shared< typename TypeTag::object_type >(name))));
}

}  // namespace stackoverflow


int main(void)
{
    using namespace stackoverflow;

    boost::shared_ptr< directory_object > root = boost::make_shared< directory_object >("/");
    root->add<directory>("etc")
            ->add<file>("hosts");
    root->add<directory>("tmp")
            ->add<file>("something.tmp");
    root->add<directory>("var")
            ->add<directory>("lib")
                ->add<directory>("mysql");
}
于 2013-10-23T11:38:52.363 回答
1

复合设计模式是此类事情的经典解决方案

于 2013-10-23T07:46:14.873 回答