Boost logo

Boost :

From: vicente.botet (vicente.botet_at_[hidden])
Date: 2008-07-14 18:54:57


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.

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
>
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((
    /* 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>
#define BOOST_FLYWEIGHT_BASE 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> >

template<
  typename T,
  typename Arg1,typename Arg2,typename Arg3,typename Arg4,typename Arg5
>
class flyweight : public BOOST_FLYWEIGHT_BASE
{
    typedef BOOST_FLYWEIGHT_BASE base_type;
#undef BOOST_FLYWEIGHT_BASE

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;
// ...
};
</code>

BOOST_FLYWEIGHT_BASE is used to avoid repeating the long template expression

I would like to know if there is an interest in such a class, and if it
could be added to the parameters library?
Of course, any improvements are welcome.

The expr.hpp and expr_pp.hpp files are attached. The class is able to manage
with a
variable number of parameters (BOOST_DSL_EXPR_ARITY) when BOOST_DSL_EXPR_PP
is defined or up to 3 otherwise.

Best Regards

Vicente Juan Botet Escriba

P.S. The variadic template code is not correct.





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