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:lus<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:lus<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:lus<typename
Expr2Args<T11, ExprT11, T12, ExprT12, BinOp1>::return_type> >(e1, e2);
}
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:lus<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:lus<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:lus<typename
Expr2Args<T11, ExprT11, T12, ExprT12, BinOp1>::return_type> >(e1, e2);
}