Boost logo

Boost :

From: David Abrahams (dave_at_[hidden])
Date: 2008-07-15 22:57:13


on Mon Jul 14 2008, "vicente.botet" <vicente.botet-AT-wanadoo.fr> wrote:

> Hello,
>
> I'm doing a Locally Unique Identifier generator library. The DSL
> grammar is quite complex, so the use of optional class parameters
> seams unavoidable. I have started to use the Boost.Parameter Library
> as the Boost.Flyweight does.

I'm not familiar with Flyweight.

> The flyweight class that takes 5 optional parameters and is currently
> declared as follows
>
> <code>
> template<
> typename T,
> typename Arg1,typename Arg2,typename Arg3,typename Arg4,typename Arg5
> /**/>

I think there must be defaults for these arguments, probably
parameter::void_, yes?

> class flyweight
> {
> private:
> typedef parameter::parameters<
> parameter::optional<
> parameter::deduced<tag<> >,
> detail::is_tag<boost::mpl::_>
> >,
> parameter::optional<
> parameter::deduced<tracking<> >,
> is_tracking<boost::mpl::_>
> >,
> parameter::optional<
> parameter::deduced<factory<> >,
> is_factory<boost::mpl::_>
> >,
> parameter::optional<
> parameter::deduced<locking<> >,
> is_locking<boost::mpl::_>
> >,
> parameter::optional<
> parameter::deduced<holder<> >,
> is_holder<boost::mpl::_>
> >
> > signature;
> typedef typename signature::bind<
> Arg1,Arg2,Arg3,Arg4,Arg5
> >::type args;
> typedef typename parameter::binding<
> args,tag<>,mpl::na
> >::type tag_type;
> typedef typename parameter::binding<
> args,tracking<>,refcounted
> >::type tracking_policy;
> typedef typename parameter::binding<
> args,factory<>,hashed_factory<>
> >::type factory_specifier;
> typedef typename parameter::binding<
> args,locking<>,simple_locking
> >::type locking_policy;
> typedef typename parameter::binding<
> args,holder<>,static_holder
> >::type holder_specifier;
>
> typedef parameter::parameters<
> parameter::optional<
> parameter::deduced<
> detail::unmatched_arg
> >,
> mpl::not_<
> mpl::or_<
> detail::is_tag<boost::mpl::_>,
> is_tracking<boost::mpl::_>,
> is_factory<boost::mpl::_>,
> is_locking<boost::mpl::_>,
> is_holder<boost::mpl::_>
> >
> >
> >
> > unmatched_signature;
> typedef typename unmatched_signature::bind<
> Arg1,Arg2,Arg3,Arg4,Arg5
> >::type unmatched_args;
> typedef typename parameter::binding<
> unmatched_args,detail::unmatched_arg,
> detail::unmatched_arg
> >::type unmatched_arg_detected;
> BOOST_STATIC_ASSERT((

Should use one of the MPL assertions, but anyway...

> /* You have passed a type in the specification of a flyweight type that
> * could not be interpreted as a valid argument.
> */
> is_same<unmatched_arg_detected,detail::unmatched_arg>::value));
> ...
> </code>
>
> I have made abstraction of the common structure of this code resulting
> on a 'expr' class.
> The boost::dsl::expr class has three parameters:
> * a tag for the expression
> * a vector of parameters specification, each one been either mandatory
> or optional, and containing a tag, a predicate stating if a parameter
> corresponds to the tag, and a default value for the optionals
> * a vector of the current parameters
>
> The parameter associated to a given tag can be obtained using the get
> template function. For example to get the tracking parameter we can
> use:
>
> typename base_type::template get<tracking<> >::type
>
> All the implementation details are encapsulated on the expre class.
>
> The flyweight class can then be rewriten as:
>
> <code>
<schnipp>
> </code>
>
> BOOST_FLYWEIGHT_BASE is used to avoid repeating the long template expression

Rewriting so I can grok it...

template <
    class T
  , class Arg1, class Arg2, class Arg3, class Arg4,class Arg5
>
struct flyweight_base
{
    typedef dsl::expr<
        flyweight<T>
      , mpl::vector<
            dsl::optional<tag<>, detail::is_tag<mpl::_>, mpl::na >
          , dsl::optional<tracking<>, is_tracking<mpl::_>, refcounted >
          , dsl::optional<factory<>, is_factory<mpl::_>, hashed_factory<> >
          , dsl::optional<locking<>, is_locking<mpl::_>, simple_locking >,
          , dsl::optional<holder<>, is_holder<mpl::_>, static_holder >
>
      , mpl::vector<Arg1,Arg2,Arg3,Arg4,Arg5>
> type;
};

template<
 typename T,
 typename Arg1,typename Arg2,typename Arg3,typename Arg4,typename Arg5
>
class flyweight : public flyweight_base<T,Arg1,Arg2,Arg3,Arg4,Arg5>::type
{
   typedef flyweight_base<T,Arg1,Arg2,Arg3,Arg4,Arg5>::type base_type;

    typedef typename base_type::template get< tag<> >::type tag_type;
    typedef typename base_type::template get< tracking<> >::type tracking_policy;
    typedef typename base_type::template get< factory<> >::type
    factory_specifier;
    typedef typename base_type::template get< locking<> >::type locking_policy;
    typedef typename base_type::template get< holder<> >::type holder_specifier;
// ...
};

So, what benefit, exactly, is the framework providing (e.g. is it
providing the equivalent of the static assertion in the original code?),
and what is the purpose of using derivation above?

> I would like to know if there is an interest in such a class, and if
> it could be added to the parameters library?

Anything that makes declaring parameter-enabled classes simpler would be
a welcome addition. However, I'm not yet sure what this is doing ;-)

-- 
Dave Abrahams
BoostPro Computing
http://www.boostpro.com

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