Boost logo

Boost :

From: Aleksey Gurtovoy (agurtovoy_at_[hidden])
Date: 2002-10-08 19:15:58


David B. Held wrote:
> template <class F, typename T>
> struct apply_lambda
> {
> typedef typename mpl::lambda<F>::type f_;
> typedef typename mpl::apply<f_, T>::type type;
> };
>
> // Extracts the policy_category as a metafunction
> template <class Policy>
> struct get_category
> {
> typedef typename Policy::policy_category type;
> };
>
> // Avoids premature dereferencing so as to properly handle the end
> // iterator
> template <typename T>
> struct make_iterator
> {
> typedef T type;
> };

mpl::identity?

>
> template <class Sequence, class Category, class Default>
> struct get_policy
> {
> typedef typename mpl::find_if<
> Sequence, is_same<get_category<_>, Category>
> >::type i_;
> typedef typename mpl::if_c<
> ::boost::is_same<i_, mpl::end<Sequence>::type >::value,
> make_iterator<Default>, i_
> >::type::type type;
> };

Fixing a missing typename and style a little bit, here's an "approved"
version :)

    template <class Sequence, class Category, class Default>
    struct get_policy
    {
        typedef typename mpl::find_if<
              Sequence
            , is_same< get_category<_>,Category >
>::type iter_;

        typedef typename mpl::end<Sequence>::type last_;
        typedef typename mpl::apply_if<
              typename is_same<iter_, last_>::type
            , mpl::identity<Default>
            , iter_
>::type type;
    };

>
> # define BOOST_STORAGE_POLICY
> \
> apply_lambda<
> \
> get_policy<policies_, storage_policy_tag,
> scalar_storage<_> >::type,
> \
> T
> \
> >::type
> # define BOOST_CHECKING_POLICY
> \
> apply_lambda<
> \
> get_policy<policies_, checking_policy_tag,
> assert_check<_> >::type,
> \
> typename BOOST_STORAGE_POLICY::stored_type
> \
> >::type
> # define BOOST_OWNERSHIP_POLICY
> \
> apply_lambda<
> \
> get_policy<policies_, ownership_policy_tag,
> ref_counted<_> >::type,
> \
> typename BOOST_STORAGE_POLICY::pointer_type
> \
> >::type
> # define BOOST_CONVERSION_POLICY
> \
> apply_lambda<
> \
> get_policy<policies_, conversion_policy_tag,
> disallow_conversion<_>
> >::type, \
> typename BOOST_STORAGE_POLICY::pointer_type
> \
> >::type
>
> struct empty_policy
> { typedef void policy_category; };
>
> template <
> typename T,
> class P1 = empty_policy, class P2 = empty_policy,
> class P3 = empty_policy, class P4 = empty_policy,
> class policies_ = mpl::list<P1, P2, P3, P4>
> >
> class smart_ptr
> : public optimally_inherit<
> optimally_inherit<
> BOOST_STORAGE_POLICY,
> BOOST_OWNERSHIP_POLICY
> >::type,
> optimally_inherit<
> BOOST_CHECKING_POLICY,
> BOOST_CONVERSION_POLICY
> >::type
> >::type
> {
> public: // Policy types
> typedef T
> element_type;
> typedef BOOST_STORAGE_POLICY
> storage_policy;
> typedef BOOST_OWNERSHIP_POLICY
> ownership_policy;
> typedef BOOST_CHECKING_POLICY
> checking_policy;
> typedef BOOST_CONVERSION_POLICY
> conversion_policy;
> typedef typename optimally_inherit<
> optimally_inherit<
> BOOST_STORAGE_POLICY,
> BOOST_OWNERSHIP_POLICY
> >::type,
> optimally_inherit<
> BOOST_CHECKING_POLICY,
> BOOST_CONVERSION_POLICY
> >::type
> >::type base_type;
> typedef typename base_type::base1_type::base1_type
> storage_base;
> typedef typename base_type::base1_type::base2_type
> ownership_base;
> typedef typename base_type::base2_type::base1_type
> checking_base;
> typedef typename base_type::base2_type::base2_type
> conversion_base;
> typedef smart_ptr this_type;
> };

A question - why BOOST_STORAGE_POLICY et al. instead of, let's say,

    typename get_storage_policy<policies_,T>::type

?

I don't have any complexes about preprocessor usage (MPL is a living prove
of it :), but those BOOST_XXX_POLICY #define-s make me wince ;).

[...]

> First, I would like a sanity check. Did I write the metafunctions
> correctly? Did I call them correctly?

Yes, it all looks good to me.

> Am I overlooking any minor mistakes that could
> be causing my problem? Is there any way to simplify the code further?

Probably to have an associative container in MPL, but not now :). Feel free
to contribute, of course.

> It would be nice to combine the get_policy<> and apply_lambda<>
> functions somehow, but I couldn't think of an elegant way to do it.

In one or another form 'apply_lambda<>' is going to end up in the library
itself, so don't bother to merge that :).

> Second, what do you expect to be the type of the policies
> after getting cranked through the policy adaptor? Do they have
> some funky type, or do they manage to get passed through more
> or less unchanged?

It is guaranteed that given

    template< typename T > struct her
    {
        typedef her type;
    };

this always holds:

    typedef apply_lambda<her<_>, int>::type h;
    BOOST_MPL_ASSERT_IS_SAME(h, her<int>);

Does it answer your question?

> It's quite nice that my test code can do this:
>
> boost::smart_ptr<
> object,
> boost::ref_counted<_>,
> boost::assert_check<_>
> > p(new object(dead));
>
> boost::smart_ptr<
> object,
> boost::scalar_storage<_>,
> boost::disallow_conversion<_>
> > q(p);
>

Yep, that is cool!

Aleksey


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk