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

Discussion in 'C++' started by PengYu.UT@gmail.com, Nov 7, 2005.

  1. Guest

    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);
    }
    , Nov 7, 2005
    #1
    1. Advertising

  2. wrote:
    > 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);
    }
    Aleksey Loginov, Nov 7, 2005
    #2
    1. Advertising

  3. Aleksey Loginov wrote:
    >
    > 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
    Aleksey Loginov, Nov 7, 2005
    #3
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Replies:
    3
    Views:
    463
    Victor Bazarov
    Nov 19, 2004
  2. Pete Becker
    Replies:
    5
    Views:
    1,012
    =?iso-8859-1?Q?Ali_=C7ehreli?=
    Nov 19, 2004
  3. robin liu
    Replies:
    3
    Views:
    821
    Robin Liu
    Apr 21, 2006
  4. Adam Nielsen
    Replies:
    3
    Views:
    405
  5. Adrian
    Replies:
    8
    Views:
    3,302
    James Kanze
    Jan 9, 2009
Loading...

Share This Page