2012-04-08 59 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),然后在需要的时候重复类中的实际类型。

相关问题