2013-10-22 118 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