我想实现一个存储不同类型对象的目录对象。需要能够通过名称访问对象,获取实际的指针类型并序列化它。我想到的对象看起来像这样:
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并显示它们,例如。任何替代或建议?
答案 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是此类事物的经典解决方案