|
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