不使用示例就很难表达这个问题,所以我会正确解决的。

作为一个基本示例,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/

    10-11 23:06
    查看更多