Boost logo

Boost :

From: Sebastian Redl (sebastian.redl_at_[hidden])
Date: 2006-02-01 11:14:59


Spencer Collyer wrote:

>Whilst working on a policy-based sparse-array class (which I hope to
>submit to Boost at some point), I had the problem that there did not seem
>to be any sensible way to organise the policies such that sensible
>defaults could be coded in the template. Rather than always forcing the
>users to specify the earlier policies, even when the default would be
>fine, simply because they wanted to use a different policy for one of the
>later parameters, I came up with the following little utility.
>
>
This looks like a very nice utility, and I'm sure it could find application.
A library facing a similar problem is the iterator library, where the
use_default mechanism was used. In this particular case, however, your
method is not applicable as it is, because the parameters specified by
use_default can be primitives.

An alternative to the inheritance would be a policy_type metafunction:
=============================================
BOOST_MPL_HAS_XXX_TRAIT_DEF(policy_type)

struct not_a_policy {};

template <class P>
struct policy_type
{
  typedef BOOST_DEDUCED_TYPENAME if_< has_policy_type< P >,
P::policy_type, not_a_policy >::type type;
}
=============================================

Your example could then be rewritten as:
=============================================
struct a_policy {};
struct b_policy {};

struct a1 { typedef a_policy policy_type; }

struct a2 {}; // External policy, have to externalize type:
template<> struct policy_type<a2> { typedef a_policy type; };

struct a3 : public a1 {};

// Quick porting from your model
struct b_base { typedef b_policy policy_type; }

struct b1 : public b_base {};
struct b2 : public b_base {};
struct b3 : public b_base {};
=============================================

PolicySelector would be adapted like thus (I'll write typename instead
of the boost macro):
=============================================
namespace m = boost::mpl;

template<typename Type, typename Policies, typename DefPolicy>
class PolicySelector
{
private:
    typedef typename m::find_if< Policies, m::is_same< Type, typename
policy_type<m::_1>::type > >::type pos;
    typedef typename m::end< Policies >::type end_pos;
public:
    typedef typename m::if_< m::is_same< pos, end_pos >,
        DefPolicy,
        typename m::deref< pos >::type
>::type type;
};
=============================================

A_Selector thus becomes:
=============================================
template< typename Policies >
struct A_Selector
{
    typedef typename PolicySelector< a_policy, Policies, a3>::type type;
    // I don't know why you had Types::type here in your example.
};
=============================================

All other code should work unchanged.

Sebastian Redl


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