Can I use typedef to define types used in the return type in template function?

P

PengYu.UT

I have the following sample program, which can convert function object
with 1 argument into function object with 2 arguments. It can also do +
between function object of the same type.

The last line is very long. I'm wondering if there is any way to
suppress it. I can only think of typedef. But I'm not sure whether I
can use typedef for the return type.

Would you please help me? Please don't be daunted by the length of the
code.

Thanks,
Peng

/*main.cc*/
#include "expression_templates.h"
#include <cassert>
#include <complex>

int main(void) {
sample_1_arg_fun<std::complex<double> > f;
std::cout << cast1stArg(f)(0, 1) << std::endl;
std::cout << cast2ndArg(f)(0, 1) << std::endl;
std::cout << (cast2ndArg(f) + cast2ndArg(f))(2, 1) << std::endl;
}

/*expression_templates.h*/
#include <iostream>
#include <functional>
#include <algorithm>
#include <limits>

template <typename T>
class sample_1_arg_fun {
public:
typedef T return_type;
return_type operator()(int i) const { return (i>= the_min_limit()
&& i <= the_max_limit())?i:0; }
int the_min_limit() const { return std::numeric_limits<int>::min();
}
int the_max_limit() const { return std::numeric_limits<int>::max();
}
};

struct LimitsUnion {
int min_limit(int min_limit1, int min_limit2) const { return
std::min(min_limit1, min_limit2); }
int max_limit(int max_limit1, int max_limit2) const { return
std::max(max_limit1, max_limit2); }
};

struct LimitsIntersection {
int min_limit(int min_limit1, int min_limit2) const { return
std::max(min_limit1, min_limit2); }
int max_limit(int max_limit1, int max_limit2) const { return
std::min(max_limit1, max_limit2); }
};

template <typename BinOp>
struct BinOpTraits;

template <typename T>
struct BinOpTraits<std::plus<T> >{
typedef LimitsUnion limit_op;
};

template <typename T1, typename ExprT1, typename T2, typename ExprT2,
typename BinOp>
class Expr2Args;

template <typename T, typename ExprT>
class Expr2Args<T, ExprT, void, void, void> {
public:
typedef T return_type;
Expr2Args(const ExprT e) : _e(e) {}
return_type operator()(int i1, int) const { return _e(i1); }
int the_1st_min_limit() const { return e.the_min_limit(); }
int the_1st_max_limit() const { return e.the_max_limit(); }
int the_2nd_min_limit() const { return
std::numeric_limits<int>::min(); }
int the_2nd_max_limit() const { return
std::numeric_limits<int>::max(); }
private:
const ExprT _e;
};

template <typename T, typename ExprT>
class Expr2Args<void, void, T, ExprT, void> {
public:
typedef T return_type;
Expr2Args(const ExprT e) : _e(e) {}
return_type operator()(int, int i2) const { return _e(i2); }
int the_1st_min_limit() const { return
std::numeric_limits<int>::min(); }
int the_1st_max_limit() const { return
std::numeric_limits<int>::max(); }
int the_2nd_min_limit() const { return e.the_min_limit(); }
int the_2nd_max_limit() const { return e.the_max_limit(); }
private:
const ExprT _e;
};

template <typename T, typename ExprT1, typename ExprT2, typename BinOp>
class Expr2Args<T, ExprT1, T, ExprT2, BinOp> {
typedef typename BinOpTraits<BinOp>::limit_op limit_op;
public:
typedef T return_type;
Expr2Args(const ExprT1 e1, const ExprT2 e2) : _e1(e1), _e2(e2) {}
return_type operator()(int i1, int i2) const { return
BinOp()(_e1(i1, i2), _e2(i1, i2)); }
int the_1st_min_limit() const { return
limit_op::min_limit(_e1.the_1st_min_limit(), _e2.the_1st_min_limit());
}
int the_1st_max_limit() const { return
limit_op::max_limit(_e1.the_1st_max_limit(), _e2.the_1st_max_limit());
}
int the_2nd_min_limit() const { return
limit_op::min_limit(_e1.the_2nd_min_limit(), _e2.the_2nd_min_limit());
}
int the_2nd_max_limit() const { return
limit_op::max_limit(_e1.the_2nd_max_limit(), _e2.the_2nd_max_limit());
}
private:
const ExprT1 _e1;
const ExprT2 _e2;
};

template <typename ExprT>
Expr2Args<typename ExprT::return_type, ExprT, void, void, void>
cast1stArg(const ExprT e) {
return Expr2Args<typename ExprT::return_type, ExprT, void, void,
void>(e);
}

template <typename ExprT>
Expr2Args<void, void, typename ExprT::return_type, ExprT, void>
cast2ndArg(const ExprT e) {
return Expr2Args<void, void, typename ExprT::return_type, ExprT,
void>(e);
}

template <typename T11, typename ExprT11, typename T12, typename
ExprT12, typename BinOp1, typename T21, typename ExprT21, typename T22,
typename ExprT22, typename BinOp2>
Expr2Args<typename Expr2Args<T11, ExprT11, T12, ExprT12,
BinOp1>::return_type, Expr2Args<T11, ExprT11, T12, ExprT12, BinOp1>,
typename Expr2Args<T21, ExprT21, T22, ExprT22, BinOp2>::return_type,
Expr2Args<T21, ExprT21, T22, ExprT22, BinOp2>, std::plus<typename
Expr2Args<T11, ExprT11, T12, ExprT12, BinOp1>::return_type> >
operator+(const Expr2Args<T11, ExprT11, T12, ExprT12, BinOp1>& e1,
const Expr2Args<T21, ExprT21, T22, ExprT22, BinOp2>& e2) {
return Expr2Args<typename Expr2Args<T11, ExprT11, T12, ExprT12,
BinOp1>::return_type, Expr2Args<T11, ExprT11, T12, ExprT12, BinOp1>,
typename Expr2Args<T21, ExprT21, T22, ExprT22, BinOp1>::return_type,
Expr2Args<T21, ExprT21, T22, ExprT22, BinOp2>, std::plus<typename
Expr2Args<T11, ExprT11, T12, ExprT12, BinOp1>::return_type> >(e1, e2);
}
 
A

Aleksey Loginov

I have the following sample program, which can convert function object
with 1 argument into function object with 2 arguments. It can also do +
between function object of the same type.

what is your main goal?
The last line is very long. I'm wondering if there is any way to
suppress it. I can only think of typedef. But I'm not sure whether I
can use typedef for the return type.

Would you please help me? Please don't be daunted by the length of the
code.

Thanks,
Peng

/*main.cc*/
#include "expression_templates.h"
#include <cassert>
#include <complex>

int main(void) {
sample_1_arg_fun<std::complex<double> > f;
std::cout << cast1stArg(f)(0, 1) << std::endl;
std::cout << cast2ndArg(f)(0, 1) << std::endl;
std::cout << (cast2ndArg(f) + cast2ndArg(f))(2, 1) << std::endl;
}

/*expression_templates.h*/
#include <iostream>
#include <functional>
#include <algorithm>
#include <limits>

template <typename T>
class sample_1_arg_fun {
public:
typedef T return_type;
return_type operator()(int i) const { return (i>= the_min_limit()
&& i <= the_max_limit())?i:0; }
int the_min_limit() const { return std::numeric_limits<int>::min();
}
int the_max_limit() const { return std::numeric_limits<int>::max();
}
};

struct LimitsUnion {
int min_limit(int min_limit1, int min_limit2) const { return
std::min(min_limit1, min_limit2); }
int max_limit(int max_limit1, int max_limit2) const { return
std::max(max_limit1, max_limit2); }
};

any reasons not to use "static max_limit(int, int)"?
template <typename T11, typename ExprT11, typename T12, typename
ExprT12, typename BinOp1, typename T21, typename ExprT21, typename T22,
typename ExprT22, typename BinOp2>
Expr2Args<typename Expr2Args<T11, ExprT11, T12, ExprT12,
BinOp1>::return_type, Expr2Args<T11, ExprT11, T12, ExprT12, BinOp1>,
typename Expr2Args<T21, ExprT21, T22, ExprT22, BinOp2>::return_type,
Expr2Args<T21, ExprT21, T22, ExprT22, BinOp2>, std::plus<typename
Expr2Args<T11, ExprT11, T12, ExprT12, BinOp1>::return_type> >
operator+(const Expr2Args<T11, ExprT11, T12, ExprT12, BinOp1>& e1,
const Expr2Args<T21, ExprT21, T22, ExprT22, BinOp2>& e2) {
return Expr2Args<typename Expr2Args<T11, ExprT11, T12, ExprT12,
BinOp1>::return_type, Expr2Args<T11, ExprT11, T12, ExprT12, BinOp1>,
typename Expr2Args<T21, ExprT21, T22, ExprT22, BinOp1>::return_type,
Expr2Args<T21, ExprT21, T22, ExprT22, BinOp2>, std::plus<typename
Expr2Args<T11, ExprT11, T12, ExprT12, BinOp1>::return_type> >(e1, e2);
}

may be this:

template <typename T1, typename T2>
Expr2Args< typename T1::return_type, T1, typename T2::return_type,
T2, std::plus<typename T1::return_type> >
operator+(const T1& e1, const T2& e2) {
return Expr2Args< typename T1::return_type, T1, typename
T2::return_type,T2, std::plus<typename T1::return_type> >(e1, e2);
}
 
A

Aleksey Loginov

Aleksey said:
may be this:

template <typename T1, typename T2>
Expr2Args< typename T1::return_type, T1, typename T2::return_type,
T2, std::plus<typename T1::return_type> >
operator+(const T1& e1, const T2& e2) {
return Expr2Args< typename T1::return_type, T1, typename
T2::return_type,T2, std::plus<typename T1::return_type> >(e1, e2);
}

my mistake.

template< typename T11, typename ExprT11, typename T12, typename
ExprT12, typename BinOp1, typename T21, typename ExprT21, typename T22,

typename ExprT22, typename BinOp2, typename T1=Expr2Args<T11, ExprT11,
T12, ExprT12, BinOp1>, typename T2=Expr2Args<T21, ExprT21, T22,
ExprT22, BinOp2> >
Expr2Args< typename T1::return_type, T1, typename T2::return_type,
T2, std::plus<typename T1::return_type> >
operator+(const Expr2Args<T11, ExprT11, T12, ExprT12, BinOp1>& e1,
const Expr2Args<T21, ExprT21, T22, ExprT22, BinOp2>& e2) { ... }

and this
http://osl.iu.edu/~tveldhui/papers/techniques/techniques01.html#l14
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,955
Messages
2,570,117
Members
46,705
Latest member
v_darius

Latest Threads

Top