Boost logo

Boost :

From: Beman Dawes (beman_at_[hidden])
Date: 1999-11-22 13:48:58


As part of an empty member optimization, Steve Cleary used a traits
class he called "constructor_parameter" to allow a constructor
parameter to be defined as "const T&" or plain "T&" according to the
template argument type.

Dietmar Kühl is working on a somewhat similar traits class called
"reference_traits" to solve a standard library problem with
std::make_pair( "abc", x ).

Steve's traits class specialized only references. It could also be
specialized for pointers and other built-in types.

It seems like this technique may have enough uses to make it a
candidate for boost/utility.hpp.

The following program can be used to experiment with the technique.
The output from CodeWarrior is:

  typeid(i).name() is int
  Constructing int which contains 1 via non-specialized template
  Constructing int which contains 1 via T& specialization
  Constructing int which contains 2 via T& specialization
  Constructing int * which contains 0x0012ff64 via T* specialization
  Constructing const int * which contains 0x0012ff64 via T*
specialization
  Constructing long which contains 2 via long specialization

--Beman

----- snip here -----

// explore the parameter_traits idiom

#include <iostream>
#include <typeinfo>
using namespace std;

template< typename T >
struct parameter_traits
{
    typedef T template_type;
    typedef T raw_type;
    typedef T const & parameter_type;
    static const char * which() { return "non-specialized template";
}
};

template< typename T >
struct parameter_traits< T* >
{
    typedef T * template_type;
    typedef T raw_type;
    typedef T * parameter_type;
    static const char * which() { return "T* specialization"; }
};

template< typename T >
struct parameter_traits< T& >
{
    typedef T & template_type;
    typedef T raw_type;
    typedef T & parameter_type;
    static const char * which() { return "T& specialization"; }
};

template<>
struct parameter_traits< long >
{
    typedef long template_type;
    typedef long raw_type;
    typedef long parameter_type;
    static const char * which() { return "long specialization"; }
};

// could specialize for all the built-in types.

// usage example:

template< typename T >
struct single
{
    T value;
    single( typename parameter_traits<T>::parameter_type v ) :
value(v)
    {
        cout << "Constructing " << typeid(value).name()
             << " which contains " << value
             << " via " << parameter_traits<T>::which()
             << endl;
    }
    virtual ~single(){}
};

int main()
{
    int i = 1;
    cout << "typeid(i).name() is " << typeid(i).name() << endl;
    single<int> x(i);
    single<int&> y(i);
    y.value = 2;
    single<const int&> cy(i);
// cy.value = 3; // error: assign to constant
    single<int*> z(&i);
    single<const int*> cz(&i);
// cz.value = 4; // error: assign to constant
    single<long> lx(i);
    return 0;
}
    


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