Boost logo

Boost :

Subject: Re: [boost] [parameter] named template parameters
From: Lorenzo Caminiti (lorcaminiti_at_[hidden])
Date: 2011-11-03 14:05:38

On Wed, Nov 2, 2011 at 6:46 PM, Jeffrey Lee Hellrung, Jr.
<jeffrey.hellrung_at_[hidden]> wrote:
> On Wed, Nov 2, 2011 at 2:00 PM, Lorenzo Caminiti <lorcaminiti_at_[hidden]>wrote:
>> Hello all (and especially Boost.Parameter's authors),
>> The Boost.Parameter docs suggest to implement parameter-enabled class
>> templates using a series of typedes for the argument pack and the
>> actual argument types. I think it is best to define extra template
>> parameters with default values to old the argument pack Args and named
>> template parameters ClassType, etc as shown below. This allows to use
>> the named template parameters within the class declaration for example
>> in a base class (boost::python::class_<ClassType, ...>) instead that
>> just in the class definition.
>> Do you see any problem in using extra template parameter to define the
>> argument pack and named template parameters?
> I *think* I know what you're asking, and I *think* it's fine, but I
> basically didn't even try parsing the code below due to formatting :/

OK, let me try again (I tested the formatting of the code below
sending an email to myself and it showed up fine):

#include <boost/parameter.hpp>
#include <boost/python/class.hpp>
#include <boost/type_traits/is_class.hpp>
#include <boost/type_traits/is_base_and_derived.hpp>
#include <boost/mpl/is_sequence.hpp>
#include <boost/mpl/placeholders.hpp>
#include <boost/mpl/not.hpp>
#include <boost/mpl/and.hpp>
#include <boost/noncopyable.hpp>
#include <boost/shared_ptr.hpp>

namespace py {

namespace detail { struct bases_tag {}; }

template< class B0 = void, class B1 = void, class B2 = void >
struct bases : detail::bases_tag {};

/** @todo to be consistent w/ PARAM_NAME, these macros should generate
_ClassType, etc with leading _ be default and in tag namespace by
default */

     typename Arg123X0
   , typename Arg123X1 = boost::parameter::void_
   , typename Arg123X2 = boost::parameter::void_
   , typename Arg123X3 = boost::parameter::void_
   , typename Args123 = typename boost::parameter::parameters<
       // IF(IS_EMPTY(DEFAULT(p)), required, optional)
           , boost::is_class<boost::mpl::_>
       , boost::parameter::optional<
           // IF(IS_DEDUCED(p), deduced<tag::NAME(p)>, tag::NAME(p))
           , boost::is_base_and_derived<detail::bases_tag, boost::mpl::_>
       , boost::parameter::optional<
           , boost::mpl::not_<
                   , boost::is_same<boost::noncopyable, boost::mpl::_>
       , boost::parameter::optional<
           , boost::is_same<boost::noncopyable, boost::mpl::_>
     >::bind<Arg123X0, Arg123X1, Arg123X2, Arg123X3>::type
   , typename ClassType = typename boost::parameter::value_type<
           Args123, tag::ClassType >::type
   , typename BaseList = typename boost::parameter::value_type<
           // ... COMMA_IF(COMPL(IS_EMPTY(DEFAULT(p)))) DEFAULT(p) >::type
           Args123, tag::BaseList, bases<> >::type
   , typename HeldType = typename boost::parameter::value_type<
           Args123, tag::HeldType, ClassType >::type
   , typename Copyable = typename boost::parameter::value_type<
           Args123, tag::Copyable, void >::type
struct class_ : boost::python::class_<ClassType, BaseList, Heldtype, Copyable>
   typedef ClassType class_type;
   typedef BaseList base_list;
   typedef HeldType held_type;
   typedef Copyable copyable;

} // namespace py

struct b { virtual ~b() = 0; };
struct d : b { ~d() {} };

// Named parameters.
typedef py::class_< py::ClassType<b>, py::Copyable<boost::noncopyable> > x1;
/** @todo use std::auto_ptr instead of boost::shared_ptr */
typedef py::class_< d, py::HeldType< boost::shared_ptr<d> >,
       py::BaseList< py::bases<b> > > x2;
// Deduced parameters.
typedef py::class_< b, boost::noncopyable > y1;
typedef py::class_< d, boost::shared_ptr<d>, py::bases<b> > y2;

>> A couple more things:
>> 1) I thing that BOOST_PARAMETER_TEMPLATE_KEYWORD(ClassType) macro
>> should define a symbol _ClassType to be used for the named parameter
>> so to be consistent with the BOOST_PARAMETER_NAME(x) which defined _x
>> to be used for the named function parameter. However, ClassType is
>> defined without the leading _. What is the reason for this asymmetry?
> The fact that each keyword is used in different contexts is enough
> justification for me to explain the asymmetry.
> I gathered the leading underscored prepended to function parameter keywords
> was motivated by a desire to prevent shadowing bugs (as per the rationale
> given in the documentation, if I remember correctly).  No such problem
> arises with template parameter keywords, so the only justification I can
> think of to prepend template parameter keywords with an underscore is
> because that's what's done with function parameter keywords, which seems
> kind of weak.

Yes but these all sound like implementation reasons to me. If the
parameter name keywords need the leading _ for functions, as a library
users I'd expect the template parameters to follow the same
convention. Why should a user expect template parameter name keywords
to follow a different convention than function parameter name

> 2) I'd expect a macro that allows to specify tag and passing argument
>> name for template parameters
>> BOOST_PARAMETER_TEMPLATE_KEYWORD((PassClassType, mytag) ClassType) as
>> for BOOST_PARAMETER_NAME((pass_x, mytag) x) does for function
>> parameters. Why is such a usage of BOOST_PARAMETER_TEMPLATE_KEYWORD
>> not supported?
> Not sure; really, I'm not familiar enough with the specifics of the above
> macros to be sure that I'm not sure, though :/


Boost list run by bdawes at, gregod at, cpdaniel at, john at