2012-04-08 62 views
1

沒有使用示例來說明這個問題有點難,所以我會適應它。boost如何將類型列表實現爲類的「選項」?

作爲一個基本的例子,boost::intrusive::list有一些有趣的模板,我很難搞清楚它們是如何工作的。類規範看起來有點像這樣:

template<typename T, class... Options> 
class list { 
    ... 
}; 

我的重點是Options參數。首先,它是可變的。這在C++ 11中是「微不足道的」,因爲它受語言支持。在C++ 03中可以很容易地模擬(最多隻能有10個參數,所有參數都有一些默認的標記值)。

這裏是我的問題

Options可以以任意順序任意數量的 「選項」 類型的,。例如:

typedef list<Foo, constant_time_size<false> > FooList; 

//This option will configure "list" to use the member hook 
typedef member_hook<Foo, list_member_hook<>, &Foo::hook_> MemberHookOption; 

//This list will use the member hook 
typedef list<Foo, MemberHookOption> FooList; 

這是真的很酷...到底是怎麼他們做這項工作的所有不同的組合。如果我兩次傳遞相同類型的選項會發生什麼?對於boost::instrusive::list,可能的選項是:

  • base_hook<class Hook>/member_hook<class T, class Hook, Hook T::* PtrToMember>/value_traits<class ValueTraits>:所有這些選項指定列表和鉤被插入(因爲我們可以在相同的T型幾個鉤子)的類型T的關係。 member_hook會稍後解釋,value_traits將在Container with custom ValueTraits部分中進行解釋。如果沒有指定選項,容器將被配置爲使用默認標籤的基礎鉤子。爲鉤子配置的一些選項(指針類型,鏈接模式等)將被傳播到容器。

  • constant_time_size<bool Enabled>:指定容器是否需要一個常量時間大小()函數。這將指示侵入性容器存儲另外的成員以跟蹤容器的當前大小。默認情況下,恆定時間大小被激活。

  • size_type<bool Enabled>:指定一個可容納容器大小的類型。如果請求了constant_time_size,則此類型將是list.size()所返回的類型以及存儲在侵入式容器中的類型。通常用戶不會需要改變這種類型,但某些容器可以有可能是從的std ::爲size_t(例如,STL類容器使用由它們的分配器所定義的size_type的)不同SIZE_TYPE。 Boost.Intrusive可用於實現這些容器,指定大小的類型。默認情況下,類型是std :: size_t。

我喜歡這個概念,因爲它允許編譯類型行爲的定義。但正如你可以想象的,各種組合可能會變得複雜。我猜測,經過一些魔術,他們正常化選項加入到一個簡單的結構,可用於實際數據結構。但是,這只是猜測工作:-P

+0

我認爲使用模板參數推導並不困難。 – Cosyn 2012-04-08 16:37:18

+0

@Cosyn:這與模板論證扣除無關。我想你可能誤解了這個問題。 – 2012-04-08 17:21:57

+1

看看Boost.Parameter;這就是Boost.Intrusive用來創建命名參數的內容。 – 2012-04-13 04:35:05

回答

1

與政策基礎設計實驗時,我已經這樣做了幾次。

我使用的核心思想是策略被標記(通過內部typedef,類似於迭代器的iterator_category),然後我定義了一個類,它只需遍歷列表並提取給定策略的類別,如果兩個政策提到同一類別,就會引發彙編錯誤。喜歡的東西:

template <typename Tag, typename Opt, typename... Options> 
struct CategoryExtractorImpl { 
    typedef typename if_< 
      same_type<typename Opt::Tag, Tag>, 
      Opt, 
      void 
    >::type Lhs; 
    typedef typename CategoryExtractorImpl<Tag, Options...>::type Rhs; 
    typedef typename Combinator<Lhs,Rhs>::type type; 
}; 

if_只是基於謂詞兩種類型和組合子之間進行選擇寫爲:

template <typename, typename> struct Combinator; 
template <typename L> struct Combinator<L, void> { typedef L type; }; 
template <typename R> struct Combinator<void, R> { typedef R type; }; 
template <> struct Combinator<void, void> { typedef void type; }; 

當然,你還需要提供一個默認的情況下,政策根本沒有提供。

template <typename L, typename R> struct ForgivingCombinator { typedef L type; }; 
template <typename R> struct ForgivingCombinator<void, R> { typedef R type; }; 

最後,你會得到:

template <typename Default, typename... Options> 
struct CategoryExtractor { 
    typedef typename ForgivingCombinator< 
     typename CategoryExtactorImpl<typename Default::Tag, Options...>::type 
     Default 
    >::type type; 
}; 

利用這一點,你只需方便地提取所有類別:

template <typename... Options> 
class List { 
    typedef typename CategoryExtractor<DefaultPolicyX, Options...>::type PolicyX; 
    typedef typename CategoryExtractor<DefaultPolicyY, Options...>::type PolicyY; 
    ... 
}; 

當然,在典型的基於策略的設計,它可能會得到一個有點冗長,因爲你可以私下繼承它們(觸發EBO),然後在需要的時候重複類中的實際類型。

相關問題