1 view

Skip to first unread message

Jul 9, 2004, 1:45:03 AM7/9/04

to

When working with different libraries it is quite common to find that

they have their own methods for determining the result_types of

operations.In nearly all cases the functionality is pretty much the

same.

Here Op is a template parameter representing the operation ie '+', '-'

etc.

A and B are my types. Hence in working with Your library I am doing

basically boilerplate:

they have their own methods for determining the result_types of

operations.In nearly all cases the functionality is pretty much the

same.

Here Op is a template parameter representing the operation ie '+', '-'

etc.

A and B are my types. Hence in working with Your library I am doing

basically boilerplate:

your_library_namespace{

your_result_of<Op,MyUDTa,MyUDTb>{

typedef MyOp_implementation your_result_type;

};

}

I would like to propose that the Op name should be standardised in

std, to prevent the tedious replication of what is basically

boilerplate.

We already have the proposed result_of<F(A,B)>::type . All that is now

needed is standardisation of the name Op above for each operation.

Hence I propose this to relieve the tedium :

result_of<operator_plus(My_TypeA,MyTypeB)>::type

result_of<operator_divides(My_TypeA,MyTypeB)>::type

result_of<operator_multiplies(My_TypeA,MyTypeB)>::type

etcetera.

In other words one common interface for operations on UDT's and

fundamental types.

As further refinement implementation of classes representing

binary_operations, and unary operations. The point of this being that

though the above is a pretty interface, it is more work to specialise

individually per UDT. (One Impl shown at the end) The following is

quick.

template<typename L,template<typename>class Op,typename R>

struct binary_operation{

typedef Whatever result_type;

result_type operator()( /*by_const_ref_or_val*/ A,B )

};

template<template<typename>class Op,typename R>

struct unary_operation{

typedef Whatever result_type;

result_type operator()(...)

};

Here the template parameter is merely a key, which resolves to one of

the binary_functions in functional.

Hence a multiplication between an int and a double would look like

this:

binary_operation<int,multiplies,double>::result_type.

Both this and the individual operator_xx functions above play ok with

result_of:

result_of<binary_operation<int,multiplies,double>::type // ok

result_of<operator_multiplies(int,double)>::type // ok

The operator_multiplies interface does not then need to be

specialised per class but can use the implementation in

binary_operation and unary_operation:

template<template <typename> class Op>

struct operator_;

/* operator_ impl ... shown below */

// these just put here to get to the point

struct operator_logical_or : operator_<std::logical_or>{};

struct operator_logical_and : operator_<std::logical_and>{};

struct operator_equal_to : operator_<std::not_equal_to>{};

struct operator_not_equal_to : operator_<std::equal_to>{};

struct operator_greater_equal : operator_<std::greater_equal>{};

struct operator_less_equal : operator_<std::less_equal>{};

struct operator_greater : operator_<std::greater>{};

struct operator_less : operator_<std::less>{};

struct operator_minus : operator_<std::minus>{};

struct operator_plus : operator_<std::plus>{};

struct operator_multiplies : operator_<std::multiplies>{};

struct operator_divides : operator_<std::divides>{};

//possibly

struct operator_shift_left : operator_<shift_left>{};

struct operator_shift_right : operator_<shift_right>{};

struct operator_bit_or : operator_<bit_or>{}; //tbd

struct operator_bit_xor : operator_<bit_xor>{};

struct operator_bit_and : operator_<bit_and>{};

template<template <typename> class Op>

struct operator_{ //base class for operators

template<typename> struct result;

template<typename F, typename L, typename R>

struct result<F(L,R)>

{

typedef typename binary_operator<

L,

Op,

R

>::result_type type;

};

template<typename F, typename T>

struct result<F(T)>

{

typedef typename unary_operator<

Op,

T

>::result_type type;

};

template<typename L, typename R>

typename result<

operator_<Op>(L,R)

>::type

operator()(L const& l, R const & r)

{

return binary_operator<L,Op,R>()(l,r);

}

template<typename L, typename R>

static

typename result<

operator_<Op>(L,R)

>::type apply( L const& l,R const& r)

{

return binary_operator<L,Op,R>::apply(l, r);

}

template<typename T>

typename result<

operator_<Op>(T)

>::type

operator()(const T & t)

{

return unary_operator<Op,T>()(t);

}

template<typename T>

static

typename result<

operator_<Op>(T)

>::type apply(const T& t)

{

return unary_operator<Op,T>::apply(t);

}

};

regards

Andy Little

---

[ comp.std.c++ is moderated. To submit articles, try just posting with ]

[ your news-reader. If that fails, use mailto:std...@ncar.ucar.edu ]

[ --- Please see the FAQ before posting. --- ]

[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]

Reply all

Reply to author

Forward

0 new messages

Search

Clear search

Close search

Google apps

Main menu