Listing 1: Class parameter_tuple
#include<boost/type_traits/transform_traits.hpp>
#include<boost/type_traits/cv_traits.hpp>
class nil {
public:
typedef nil element_type;
typedef nil nested_type;
nil() {}
nil(const nil&) {}
nil(const nil&, const nil&) {}
nil(const nil&, const nil&, const nil&) {}
nil(const nil&, const nil&, const nil&, const nil&) {}
/* EXTEND */
};
template<typename FP, int n>
class nth_parameter_type {
public:
typedef nth_parameter_type<FP::nested_type, n-1>::ret
ret;
};
template<typename FP>
class nth_parameter_type<FP, 0> {
public:
typedef typename FP::element_type ret;
};
// Tag classes for mandatory and default parameters.
class default_parameter_tag{};
class mandatory_parameter_tag{};
// Class parameter_tuple
template<typename Head, typename Tail>
class parameter_tuple {
typedef typename Head element_type;
typedef typename Tail nested_type;
typedef boost::add_reference<element_type>::type
element_reference_type;
typedef boost::add_reference<boost::add_const<
element_type
>::type>::type element_const_reference_type;
typedef boost::add_reference<boost::add_const<
nested_type
>::type>::type rest_const_reference_type;
template<int n>
class nth_parameter_tag{};
public:
// Constructor from n elements
parameter_tuple(
element_const_reference_type elem_0,
typename boost::add_reference<boost::add_const<
nth_parameter_type<Tail, 0>::ret
>::type>::type elem_1 = nil(),
typename boost::add_reference<boost::add_const<
nth_parameter_type<Tail, 1>::ret
>::type>::type elem_2 = nil(),
typename boost::add_reference<boost::add_const<
nth_parameter_type<Tail, 2>::ret
>::type>::type elem_3 = nil()
/* EXTEND */ ) :
m_element(elem_0),
m_rest(elem_1, elem_2, elem_3 /* EXTEND */ ) {}
// Copy constructor from two function parameter objects,
// default implementation: copy element from first arg.
template<typename Rhs1Head, typename Rhs1Tail,
typename Rhs2Head, typename Rhs2Tail>
parameter_tuple(
const parameter_tuple<Rhs1Head, Rhs1Tail>& rhs1,
const parameter_tuple<Rhs2Head, Rhs2Tail>& rhs2
) :
m_element(rhs1.get_element()),
m_rest(rhs1.get_rest(), rhs2.get_rest()) {}
// Copy constructor from two function parameter objects,
// overload when the element type of the first argument
// is default_parameter: copy element from second arg.
template<typename Rhs1Tail, typename Rhs2Head,
typename Rhs2Tail>
parameter_tuple(
const parameter_tuple<
default_parameter_tag, Rhs1Tail>& rhs1,
const parameter_tuple<Rhs2Head, Rhs2Tail>& rhs2) :
m_element(rhs2.get_element()),
m_rest(rhs1.get_rest(), rhs2.get_rest()) {}
// Get function to retrieve the nth parameter.
template<int m>
typename boost::add_reference<
typename nth_parameter_type<
parameter_tuple<Head, Tail>, m>::ret>::type
get_parameter()
{return get_parameter_internal(nth_parameter_tag<m>());}
// Get functions to retrieve the element and the
// tail. These must be public for the copy constructors.
element_const_reference_type get_element() const
{ return m_element; }
//
rest_const_reference_type get_rest() const
{ return m_rest; }
private:
element_type m_element;
nested_type m_rest;
// Get function to retrieve the nth parameter, default
// implementation: look in the nested rest object.
template<int m>
typename boost::add_reference<
typename nth_parameter_type<
parameter_tuple<Head, Tail>, m
>::ret>::type
get_parameter_internal(nth_parameter_tag<m>)
{ return m_rest.get_parameter<m-1>(); };
// Get function to retrieve the nth parameter, overload
// for m=0: return the element.
element_reference_type get_parameter_internal(
nth_parameter_tag<0>)
{ return m_element; };
// Prevent assignment and copy construction.
parameter_tuple(const parameter_tuple&);
parameter_tuple& operator=(const parameter_tuple&);
};
// parameter_tuple type generator
template<typename T1=nil, typename T2=nil,
typename T3=nil, typename T4=nil
/* EXTEND */>
class make_parameter_tuple_type {
public:
typedef typename parameter_tuple<
T1, typename make_parameter_tuple_type<
T2, T3, T4 /* EXTEND */>::ret> ret;
};
// Kicks in for zero arguments passed
template<>
class make_parameter_tuple_type<
nil, nil, nil, nil /* EXTEND */ >
{
public:
typedef typename nil ret;
};