2013-10-22 150 views
3

我想实现一个存储不同类型的对象的目录对象。需要能够通过名称访问对象,获取实际的指针类型并对其进行序列化。我心目中的对象是这样的:实现一个对象目录:boost :: any,boost :: variant或?

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

“SOMETYPE”我想使用boost ::变种。但是,似乎我需要在运行时将对象类型添加到变体列表中。即使我知道在未来一个目录的对象类型,这将成为

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

其中Typelist是不同迪尔斯不同。然后,有一个目录将是Typelist的动态结合。看起来很复杂。它将很快达到50个变体类型的极限。替代方法是Boost :: Any来简化语义。但我想迭代一组对象,并在它上面做一些事情 - 每个对象都是boost :: fusion adapt_struct - 我想在每个对象的每个成员上融合:: for_each并显示它们,例如。任何替代方案或建议?

+0

是不是一个基类,一个模型在你的目录中的任意项目,是一个选项?然后,您可以保留一个shared_ptr或一个指向特定对象的普通指针,然后在您访问它们时施放它们。 –

+0

这将是其中一个选项。但是,一旦我存储了基类,问题是如何知道我可以将它们转换为什么类型,以便对实际类型进行一些有用的操作。存储typeinfo似乎不足以让我做static_cast (t),在那里我需要“T”。 – surfcode

回答

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"); 
} 
+0

谢谢!早些时候,我想我会使用boost :: any,然后使用typeinfo来存储一个“任何”类型的访问函子。使用模板标签类型可能效率更高。 – surfcode

1

composite design pattern是一个这样的东西有多少不同类型的经典解

+0

我不认为这是问题的答案。我知道有些是叶子,有些是复合的。问题是,对于叶,在Object类中上面的“SomeType”的实际C++类型应该是什么。 – surfcode

+0

复合设计模式;这对我来说是新的。我以前做过。但从未想过设计模式会存在。这种模式最常见的用途是在XML/DOM处理中。 – kingstonian