$include_dir="/home/hyper-archives/boost/include"; include("$include_dir/msg-header.inc") ?>
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