|
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