Template function type for arithmetic operators for elementary types

Discussion in 'C++' started by Lionel B, Mar 2, 2005.

  1. Lionel B

    Lionel B Guest

    Greetings,

    I am trying to implement "element-wise" arithmetic operators for a class
    along the following lines (this is a simplified example):

    // ----- BEGIN CODE -----

    struct X
    {
    int a,b;

    typedef int& optype(int&,int); // ???

    template<optype OP> void element_wise(X& x)
    {
    OP(a,x.a);
    OP(b,x.b);
    }

    X& operator+=(X& x)
    {
    element_wise< ::eek:perator+=<int> >(x); // ??? (line 15)
    return *this;
    }
    };

    int main()
    {
    X x,y;

    x.a = 1;
    x.b = 2;
    y.a = 3;
    y.b = 4;

    x += y;

    return 0;
    }

    // ----- END CODE -----

    I get the error (gcc):

    test.cpp: In member function `X& X::eek:perator+=(X&)':
    test.cpp:15: error: no matching function for call to
    `X::element_wise(X&)'

    This is perhaps not surprising, in view of that:

    // ----- BEGIN CODE -----

    int main()
    {
    int a = 1;

    operator += (a,1);

    return 0;
    }


    // ----- END CODE -----

    fails to compile with "error: `operator+=' not defined" (this surprised
    me somewhat). It seems that function-style prototypes for arithmetic
    operators on elementary types don't exist.

    So is it at all possible to use arithmetic operators for elementary
    types as template arguments? A simple workaround is to wrap the
    operators in a function, but it would be neater (and conceivably more
    efficient) not to have to do this.

    Regards,

    --
    Lionel B
    Lionel B, Mar 2, 2005
    #1
    1. Advertising

  2. Re: Template function type for arithmetic operators for elementarytypes

    Lionel B wrote:
    > [...]
    > So is it at all possible to use arithmetic operators for elementary
    > types as template arguments? A simple workaround is to wrap the
    > operators in a function, but it would be neater (and conceivably more
    > efficient) not to have to do this.


    Take a look at the library implementation of 'std::plus' and other
    arithmetic functors. They are defined in <functional> and described
    in 20.3.2. My guess is you should simply use them and/or provide your
    own of similar form.

    V
    Victor Bazarov, Mar 2, 2005
    #2
    1. Advertising

  3. Re: Template function type for arithmetic operators for elementarytypes

    Lionel B wrote:
    > Greetings,
    >
    > I am trying to implement "element-wise" arithmetic operators for a class
    > along the following lines (this is a simplified example):
    >
    > // ----- BEGIN CODE -----
    >
    > struct X
    > {
    > int a,b;
    >
    > typedef int& optype(int&,int); // ???
    >
    > template<optype OP> void element_wise(X& x)
    > {
    > OP(a,x.a);
    > OP(b,x.b);
    > }
    >
    > X& operator+=(X& x)
    > {
    > element_wise< ::eek:perator+=<int> >(x); // ??? (line 15)
    > return *this;
    > }
    > };


    Not all compilers will support this yet because of the template-template
    parameter. This compiled on GCC 4.0(snapshot).

    template < template <typename Tf> class F, typename T >
    void Do( T & res, const T& val )
    {
    F<T>::DoThing( res, val );
    }




    template <typename Tf>
    struct PlusEqual
    {
    static void DoThing( Tf & res, const Tf & val )
    {
    res += val;
    }
    };


    template <typename Tf>
    struct MinusEqual
    {
    static void DoThing( Tf & res, const Tf & val )
    {
    res -= val;
    }
    };


    struct X
    {
    float a;
    int b;


    template < template <typename Tf> class F >
    void ElementWise( const X & rhs )
    {
    Do<F>( a, rhs.a );
    Do<F>( b, rhs.b );
    }


    X& operator+=( const X& rhs )
    {
    ElementWise<PlusEqual>( rhs );
    return * this;
    }


    X& operator-=( const X& rhs )
    {
    ElementWise<PlusEqual>( rhs );
    return * this;
    }
    };

    I don't know how useful this is since it's limited in utility, however I
    think that does what you were trying to do. In the example you posted,
    there were numerous issues, I won't go into the details other than to
    say, you can't pass a function as a template parameter in your case
    since you don't know what the type of the parameters are, hence you can
    pass a template as the template parameter.

    >
    > int main()
    > {
    > X x,y;
    >
    > x.a = 1;
    > x.b = 2;
    > y.a = 3;
    > y.b = 4;
    >
    > x += y;
    >
    > return 0;
    > }


    This should now compile.

    ....

    > // ----- BEGIN CODE -----
    >
    > int main()
    > {
    > int a = 1;
    >
    > operator += (a,1);


    You're invoking global operator += on two ints:

    "ComeauTest.c", line 1: error: nonmember operator requires a parameter
    with class
    or enum type
    int operator +=( int &, int );

    You can't override the built-in global operators, but you can create
    your own types and define new global operators.

    >
    > return 0;
    > }
    >
    >
    > // ----- END CODE -----
    >
    > fails to compile with "error: `operator+=' not defined" (this surprised
    > me somewhat). It seems that function-style prototypes for arithmetic
    > operators on elementary types don't exist.
    >
    > So is it at all possible to use arithmetic operators for elementary
    > types as template arguments? A simple workaround is to wrap the
    > operators in a function, but it would be neater (and conceivably more
    > efficient) not to have to do this.


    Most compilers I have used will optimize the function calls away and the
    efficiency become a non-issue.
    Gianni Mariani, Mar 2, 2005
    #3
  4. Re: Template function type for arithmetic operators for elementarytypes

    Gianni Mariani wrote:

    Correction:

    ....
    >
    > template <typename Tf>
    > struct MinusEqual
    > {
    > static void DoThing( Tf & res, const Tf & val )
    > {
    > res -= val;
    > }
    > };
    >
    >
    > struct X
    > {
    > float a;
    > int b;


    ....

    >
    >
    > X& operator-=( const X& rhs )
    > {
    > ElementWise<PlusEqual>( rhs );


    Should be:
    ElementWise<MinusEqual>( rhs );

    > return * this;
    > }
    > };
    Gianni Mariani, Mar 2, 2005
    #4
  5. Lionel B

    Lionel B Guest

    "Gianni Mariani" <> wrote in message
    news:...
    > Lionel B wrote:
    > > Greetings,
    > >
    > > I am trying to implement "element-wise" arithmetic operators for a

    class
    > > along the following lines (this is a simplified example):
    > >
    > > // ----- BEGIN CODE -----
    > >
    > > struct X
    > > {
    > > int a,b;
    > >
    > > typedef int& optype(int&,int); // ???
    > >
    > > template<optype OP> void element_wise(X& x)
    > > {
    > > OP(a,x.a);
    > > OP(b,x.b);
    > > }
    > >
    > > X& operator+=(X& x)
    > > {
    > > element_wise< ::eek:perator+=<int> >(x); // ??? (line 15)
    > > return *this;
    > > }
    > > };

    >
    > Not all compilers will support this yet because of the

    template-template
    > parameter. This compiled on GCC 4.0(snapshot).
    >
    > /snip code/


    Cheers, yes that works for my gcc 3.3.3 too.

    > I don't know how useful this is since it's limited in utility, however

    I
    > think that does what you were trying to do.


    It does. BTW, the reason for what I was trying to do is simply to avoid
    code duplication: my "real" ElementWise() function is rather lengthy and
    complex, and needs to be parametrised by operator type (plus, minus,
    etc.).

    I suspect the "functional" approach you give above is probably
    uneccessarily sophisticated for my needs... the following works
    perfectly well for me.

    typedef void optype(int&, const int&);

    void plus_equal(int& a, int b)
    {
    a += b;
    }

    struct X
    {
    int a,b;

    template<optype OP> void element_wise(X& x)
    {
    OP(a,x.a);
    OP(b,x.b);
    }

    X& operator+=(X& x)
    {
    element_wise<plus_equal>(x);
    return *this;
    }
    };

    > In the example you posted,
    > there were numerous issues, I won't go into the details other than to
    > say, you can't pass a function as a template parameter in your case
    > since you don't know what the type of the parameters are


    Not sure I follow you... I *do* know the parameter types of the function
    I want to pass as template parameter: namely (int&, const int), as
    above. My issue was whether I could pass the global operator+= function
    as a parameter to my to element_wise() ...

    > /snip/


    > > // ----- BEGIN CODE -----
    > >
    > > int main()
    > > {
    > > int a = 1;
    > >
    > > operator += (a,1);

    >
    > You're invoking global operator += on two ints:
    >
    > "ComeauTest.c", line 1: error: nonmember operator requires a parameter
    > with class
    > or enum type
    > int operator +=( int &, int );
    >
    > You can't override the built-in global operators, but you can create
    > your own types and define new global operators.


    Yup - that's my solution above.

    > > So is it at all possible to use arithmetic operators for elementary
    > > types as template arguments?


    So... no.

    > > A simple workaround is to wrap the
    > > operators in a function, but it would be neater (and conceivably

    more
    > > efficient) not to have to do this.

    >
    > Most compilers I have used will optimize the function calls away and

    the
    > efficiency become a non-issue.


    No doubt.

    Thanks,
    Lionel B, Mar 2, 2005
    #5
  6. Re: Template function type for arithmetic operators for elementarytypes

    Lionel B wrote:

    ....
    > I
    >
    >>think that does what you were trying to do.

    >
    >
    > It does. BTW, the reason for what I was trying to do is simply to avoid
    > code duplication: my "real" ElementWise() function is rather lengthy and
    > complex, and needs to be parametrised by operator type (plus, minus,
    > etc.).
    >
    > I suspect the "functional" approach you give above is probably
    > uneccessarily sophisticated for my needs... the following works
    > perfectly well for me.
    >
    > typedef void optype(int&, const int&);
    >
    > void plus_equal(int& a, int b)
    > {
    > a += b;
    > }
    >
    > struct X
    > {
    > int a,b;
    >
    > template<optype OP> void element_wise(X& x)
    > {
    > OP(a,x.a);
    > OP(b,x.b);
    > }
    >
    > X& operator+=(X& x)
    > {
    > element_wise<plus_equal>(x);
    > return *this;
    > }
    > };



    If all you need is int support, you're OK, the solution I posted will
    support any type.

    >
    >
    >>In the example you posted,
    >>there were numerous issues, I won't go into the details other than to
    >>say, you can't pass a function as a template parameter in your case
    >>since you don't know what the type of the parameters are

    >
    >
    > Not sure I follow you... I *do* know the parameter types of the function
    > I want to pass as template parameter: namely (int&, const int), as
    > above. My issue was whether I could pass the global operator+= function
    > as a parameter to my to element_wise() ...


    OK - then you're all set.

    I thought you were looking for a more generic solution. Good luck.
    Gianni Mariani, Mar 3, 2005
    #6
    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. =?ISO-8859-1?Q?Christian_Brechb=FChler?=

    Enhancing valarray with "normal" arithmetic operators

    =?ISO-8859-1?Q?Christian_Brechb=FChler?=, Sep 12, 2003, in forum: C++
    Replies:
    6
    Views:
    956
    =?ISO-8859-1?Q?Christian_Brechb=FChler?=
    Sep 14, 2003
  2. Trent Buck

    variadic arithmetic, boolean operators

    Trent Buck, Jan 1, 2005, in forum: C Programming
    Replies:
    3
    Views:
    403
    Mysidia
    Jan 2, 2005
  3. joshc
    Replies:
    5
    Views:
    552
    Keith Thompson
    Mar 31, 2005
  4. ittium
    Replies:
    4
    Views:
    294
    Goran
    Dec 9, 2011
  5. bagratte
    Replies:
    16
    Views:
    1,513
    Liviu
    Feb 22, 2012
Loading...

Share This Page