
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