不使用示例就很难表达这个问题,所以我会正确解决的。
作为一个基本示例,boost::intrusive::list
有一些有趣的模板,我很难弄清楚它们的工作方式。类规范看起来像这样:
template<typename T, class... Options>
class list {
...
};
我的重点是
Options
参数。对于初学者来说,它是可变的。在c++ 11中,这是“琐碎的”,因为该语言支持它。而且肯定很容易在c++ 03中进行仿真(最多可以有10个参数,所有参数都带有一些默认标记值)。这是我的问题:
Options
可以采用任意数量的“option”类型,的顺序为。例如: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进行说明,并在具有自定义ValueTraits的容器部分中说明value_traits。如果未指定任何选项,则将容器配置为使用带有默认标记的基本钩子(Hook)。为挂钩配置的某些选项(指针的类型,链接模式等)将传播到容器。 constant_time_size<bool Enabled>
:指定容器是否需要恒定的时间size()函数。这将指示侵入式容器存储其他成员,以跟踪容器的当前大小。默认情况下,恒定时间大小处于激活状态。 size_type<bool Enabled>
:指定可以容纳容器大小的类型。如果请求constant_time_size,则此类型将是list.size()返回的类型,并且是存储在介入式容器中的类型。用户通常不需要更改此类型,但是某些容器可以具有可能不同于std::size_t的size_type(例如,类似STL的容器使用其分配器定义的size_type)。 Boost.Intrusive可用于实现指定大小类型的容器。默认情况下,类型为std::size_t。 我喜欢这个概念,因为它允许编译类型行为的定义。但您可以想象,各种组合会变得复杂。我猜想通过某种魔术,它们将选项标准化为一个简单的结构,可以用于实际的数据结构。但这只是猜测:-P
最佳答案
在尝试使用Policy Base设计时,我已经做了几次。
我使用的核心思想是对策略进行了标记(通过内部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),然后在需要时在类中重复实际的类型。
关于c++ - 如何 boost 类的 “options”类型列表?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/10064361/