Boost logo

Boost :

From: David B. Held (dheld_at_[hidden])
Date: 2002-05-01 23:42:15

"David Abrahams" <david.abrahams_at_[hidden]> wrote in message
> From: "David B. Held" <dheld_at_[hidden]>
> > "David Abrahams" <david.abrahams_at_[hidden]> wrote in message
> > > From: "David B. Held" <dheld_at_[hidden]>
> > > > Vertical policies facilitate IPC, but at a cost, depending on the
> > > > architecture. For instance, Beman made a tradeoff between
> > > > straight vertical and straight horizontal policy design (diagonal
> > > > policies?). On the one hand, it simplified the design. On the
> > > > other hand, it fixed which policies could see each other.
> > >
> > > It doesn't have to. You /can/ leave the ordering up to the user. I
> > > have in mind a "construction kit" where you configure new smart
> > > pointers like this:
> >
> > I must be dense, because I don't see how this is at all similar to
> > Beman's design
> Don't see why that makes you dense. I never claimed it was like
> Beman's design.

I misread you as saying that with Beman's design, you can leave the
ordering up to the user. I see that you were simply saying that with
full vertical policy chaining, you can have any order. I assumed that
was one of the reasons one would choose vertical chaining.

> > [...]
> > It looks pretty interesting. I still have a hard time getting my head
> > around the idea of something inheriting from itself.
> Nothing can do that in C++.

Well, not directly. ;)

> This is just the straightforward "curiously recursive template" pattern,
> as employed (for example) by the operators library.

Whenever I see people mention it, they seem to call it the "curiously
recurring template pattern", from which I gathered that it pops up in
unusual circumstances. But I can see that "recurrent" is also a
mathematical term for "recursive", and so the term is a bit
ambiguous. When you pointed out that it's a *recursive* pattern,
it all made sense. I don't even want to think about what a compiler
has to do to make that work. :(

> [...]
> If there were base policies which didn't need access to the pointer,
> they could have a default constructor. Maybe the policies don't hold
> the pointer at all, but get passed the entire smart_ptr<> object for
> each operation and extract the pointer explicitly.

Ok. But when you delegate storage to a policy (a la Loki::SmartPtr),
it seems that you have to have extra c'tors in every policy, right?

> > In mine as well, unless smart_ptr were made to work with, say,
> > shared_ptr, and you started adding all these conversion c'tors
> > that started cluttering up the policies considerably.
> You don't put those in the policies. They just live in the outer class.

I see. I was confused by the fact that you pass a raw pointer to
policy classes. But with a conversion c'tor, you could just take out
the raw pointer, and pass that down.

> [...]
> > It seems to me that a policy adaptor is a fairly generic idea.
> > Have you considered generalizing it, and making it standalone,
> > so other policy-based designs can take advantage of it?
> It's already as general as it can get: it's a design pattern. Anything
> can take advantage of it. Trying to write a generalized policy adaptor
> in code could only make it less general.

True. But writing anything in code makes it less general. ;) However,
it seems to me that MPL lets us write something fairly cool. I.e.:

    namespace detail
        class no_policy_tag;

        template <typename T>
        class no_policy
            typedef no_policy_tag policy_tag;

        class no_defaults
            typedef no_policy_tag default_tag_1;
            typedef no_policy_tag default_tag_2;
            typedef no_policy_tag default_tag_3;
            typedef no_policy_tag default_tag_4;

            template <class>
            class default_policy_1;
            template <class>
            class default_policy_2;
            template <class>
            class default_policy_3;
            template <class>
            class default_policy_4;
    } // namespace detail

        template <class> class Policy1 = detail::no_policy,
        template <class> class Policy2 = detail::no_policy,
        template <class> class Policy3 = detail::no_policy,
        template <class> class Policy4 = detail::no_policy,
        template <class> class Defaults = detail::no_defaults
    class policy_adaptor
        // MPL pseudo-code
        mpl::typelist policies<Policy1, Policy2, Policy3, Policy4>;

        typedef typename mpl::find_if<policies,
                typename _1::policy_tag,
                typename Defaults::default_tag_1
>::type iter1;
        typedef typename ct_if<
            is_same<iter1, mpl::end<policies>::type>,
            typename Defaults::default_policy_1, Policy1
>::type policy_1;

        typedef typename mpl::find_if<policies,
                typename _1::policy_tag,
                typename Defaults::default_tag_2
>::type iter2;
        typedef typename ct_if<
            is_same<iter2, mpl::end<policies>::type>,
            typename Defaults::default_policy_2, Policy2
>::type policy_2;

        typedef typename mpl::find_if<policies,
                typename _1::policy_tag,
                typename Defaults::default_tag_3
>::type iter3;
        typedef typename ct_if<
            is_same<iter3, mpl::end<policies>::type>,
            typename Defaults::default_policy_3, Policy3
>::type policy_3;

        typedef typename mpl::find_if<policies,
                typename _1::policy_tag,
                typename Defaults::default_tag_4
>::type iter4;
        typedef typename ct_if<
            is_same<iter4, mpl::end<policies>::type>,
            typename Defaults::default_policy_4, Policy4
>::type policy_4;

        template <typename T>
        class vertical
            : public policy_4<policy_3<policy_2<policy_1<T> > > > >
        { };

        template <typename T>
        class lateral
            : public policy_1<T>
            , public policy_2<T>
            , public policy_3<T>
            , public policy_4<T>
        { };

        template <typename T>
        class opt_lateral
            : public OptionalInherit<
                OptionalInherit<policy_1<T>, policy_2<T> >,
                OptionalInherit<policy_3<T>, policy_4<T> >,
        { };


So this doesn't preserve the order of policy specification, but I'm
sure that could be accomodated if necessary. And clearly, boost::
preprocessor could be used to scale it. Surely it's not as general
as the Policy Adaptor concept; but if it fits a wide range of uses,
then it has to be as useful as any other library, no?

Boost list run by bdawes at, gregod at, cpdaniel at, john at