Boost logo

Boost :

From: Serge Barral (sbarral_at_[hidden])
Date: 2001-07-02 02:30:33


On Sun, 01 Jul 2001 19:18:43 Eric Ford wrote:
> 1. I'm working on a templatized (mathematical) function class that
> takes an argument of type ArgT and returns a type of RetT. For one of
> the methods I need to multiply an ArgT by a RetT. (If that operation
> isn't definted there should be a compile-time error.) Is there a good
> way to specify the type (at compile time) returned by a function when
> given arguments of a specified type? I'm thinking something like...
>
> template<class RegT, class ArgT>
> class Foo
> {
> public:
> typename operator*(RetT,ArgT) RetTimesArgT;
> RetT f(ArgT x) {...};
> RetTimesArgT fx(ArgT x) { return f(x)*x; };
> };
>
> Foo<float,int> bar;
>
> so I'd want bar.fx(3) to return a float.

I had to adress the same problem in the past, and took inspiration from the
Todd Verldhuizen's "Techniques for Scientific C++"
(http://extreme.indiana.edu/~tveldhui/papers/techniques/) where such a
problem is adressed with Traits.
See below a possible implementation. Note that I assumed that
auto-promotion of small types defaults to int, but as far as I know it is
platform dependant.
With this implementation you would get the proper return type with:
typedef typename PromoteTrait< RegT, ArgT >::ResultType RetTimesArgT;

This works for most binary operators (+,*,-,/) but you may have to modify
it depending on the promotion rules used by your operators.

         Serge

//////////////////////////////////////////////////////

/*
Make standard C++ arithmetic conversions. For user-defined types,
two identical type result in the same type. If different user-defined
types are to be mixed, or if a user-defined type is to be mixed with
predefined types, the user must explicitely defined the type of the result.

For example, if mixing types A and B must result in type B, the user
may define the following specialization of PromoteTraits:

struct PromoteTrait< A, B > { typedef B ResultType; };
struct PromoteTrait< B, A > { typedef B ResultType; };
*/

// Assign a Rank to each predefined type
template< class T >
struct Rank {};

// Defined types that are auto-promoted to int
template<> struct Rank< bool > { enum { value=1 }; };
template<> struct Rank< char > { enum { value=1 }; };
template<> struct Rank< signed char > { enum { value=1 }; };
template<> struct Rank< unsigned char > { enum { value=1 }; };
template<> struct Rank< short > { enum { value=1 }; };
template<> struct Rank< unsigned short > { enum { value=1 }; };

// Types without auto-promotion
template<> struct Rank< int > { enum { value=1 }; };
template<> struct Rank< unsigned int > { enum { value=2 }; };
template<> struct Rank< long > { enum { value=3 }; };
template<> struct Rank< unsigned long > { enum { value=4 }; };
template<> struct Rank< float > { enum { value=5 }; };
template<> struct Rank< double > { enum { value=6 }; };
template<> struct Rank< long double > { enum { value=7 }; };

// Define the type resulting from a promotion
template< int rank >
struct RankTrait {};

template<> struct RankTrait< 1 > { typedef int Type; };
template<> struct RankTrait< 2 > { typedef unsigned int Type; };
template<> struct RankTrait< 3 > { typedef long Type; };
template<> struct RankTrait< 4 > { typedef unsigned long Type; };
template<> struct RankTrait< 5 > { typedef float Type; };
template<> struct RankTrait< 6 > { typedef double Type; };
template<> struct RankTrait< 7 > { typedef long double Type; };

// Promotion for two operands
template <class T1, class T2>
struct PromoteTrait
{
    enum // Compute the highest rank
    {
        maxRank = int(Rank<T1>::value) > int(Rank<T2>::value) ?
                  int(Rank<T1>::value) : int(Rank<T2>::value)
    };
    typedef typename RankTrait< maxRank >::Type ResultType;
};

// By default, two identical types result in the same type
// (this is needed for user-defined types)
template< class T >
struct PromoteTrait< T, T> { typedef T ResultType; };

// Override the previous specialization to respect standard auto-promotions
struct PromoteTrait< bool, bool> { typedef int
ResultType; };
struct PromoteTrait< char, char> { typedef int
ResultType; };
struct PromoteTrait< signed char, signed char> { typedef int
ResultType; };
struct PromoteTrait< unsigned char, unsigned char> { typedef int
ResultType; };
struct PromoteTrait< short, short> { typedef int
ResultType; };
struct PromoteTrait< unsigned short, unsigned short> { typedef int
ResultType; };


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