实现一个对象目录:boost :: any,boost :: variant,还是?

时间:2013-10-22 07:14:29

标签: c++ boost-variant boost-fusion boost-any

我想实现一个存储不同类型对象的目录对象。需要能够通过名称访问对象,获取实际的指针类型并序列化它。我想到的对象看起来像这样:

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 dir将是Typelist的动态联合。看起来很复杂。它很快就会达到50种不同类型的极限。替代方案是Boost :: Any来简化语义。但我想迭代一组对象,并在其上做东西 - 每个对象都是一个boost :: fusion adapt_struct - 我想在每个对象的每个成员上融合:: for_each并显示它们,例如。任何替代或建议?

2 个答案:

答案 0 :(得分: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");
}

答案 1 :(得分:1)

Th composite design pattern是此类事物的经典解决方案