Реализовать каталог объектов: boost :: any, boost :: option или?

Я хотел бы реализовать объект каталога, который хранит различные типы объектов. Необходимо иметь возможность доступа к объектам по имени, получить фактический тип указателя и сериализовать его. Объект, который я имею в виду, выглядит так:

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

«SomeType» Я думал об использовании Boost :: вариант. Но тогда кажется, что мне нужно добавить типы объектов в список вариантов во время выполнения. Даже если бы я знал типы объектов в DIR впереди, это стало бы

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

где Typelist отличается для разных режиссеров. Тогда наличие dir dirs будет динамическим объединением Typelist. Это выглядит сложно. И скоро он достигнет предела в 50 вариантов. Альтернатива Boost :: Any для упрощения семантики. Но я бы хотел перебрать набор объектов и сделать что-то для него — каждый объект является boost :: fusion adapt_struct — я хочу fusion :: for_each для каждого члена каждого объекта и отображать их, например. Есть альтернативы или предложения?

3

Решение

Все зависит от того, сколько разных типов и какой производительности вам нужно. Если количество типов объектов ограничено, то лучше использовать общий базовый класс со специализацией для каждого типа.

Код ниже использует 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 stackoverflowint 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");
}
2

Другие решения

Th композитный дизайн это классическое решение для такой вещи

1

По вопросам рекламы [email protected]