Connecting Tech Pros Worldwide Forums | Help | Site Map

Template function type for arithmetic operators for elementary types

Lionel B
Guest
 
Posts: n/a
#1: Jul 23 '05
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< ::operator+=<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::operator+=(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



Victor Bazarov
Guest
 
Posts: n/a
#2: Jul 23 '05

re: Template function type for arithmetic operators for elementary types


Lionel B wrote:[color=blue]
> [...]
> 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.[/color]

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
Gianni Mariani
Guest
 
Posts: n/a
#3: Jul 23 '05

re: Template function type for arithmetic operators for elementary types


Lionel B wrote:[color=blue]
> 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< ::operator+=<int> >(x); // ??? (line 15)
> return *this;
> }
> };[/color]

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.
[color=blue]
>
> int main()
> {
> X x,y;
>
> x.a = 1;
> x.b = 2;
> y.a = 3;
> y.b = 4;
>
> x += y;
>
> return 0;
> }[/color]

This should now compile.

....
[color=blue]
> // ----- BEGIN CODE -----
>
> int main()
> {
> int a = 1;
>
> operator += (a,1);[/color]

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.
[color=blue]
>
> 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.[/color]

Most compilers I have used will optimize the function calls away and the
efficiency become a non-issue.


Gianni Mariani
Guest
 
Posts: n/a
#4: Jul 23 '05

re: Template function type for arithmetic operators for elementary types


Gianni Mariani wrote:

Correction:

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

....
[color=blue]
>
>
> X& operator-=( const X& rhs )
> {
> ElementWise<PlusEqual>( rhs );[/color]

Should be:
ElementWise<MinusEqual>( rhs );
[color=blue]
> return * this;
> }
> };[/color]
Lionel B
Guest
 
Posts: n/a
#5: Jul 23 '05

re: Template function type for arithmetic operators for elementary types


"Gianni Mariani" <gi2nospam@mariani.ws> wrote in message
news:Y9ydncLXa9a1VLjfRVn-rw@speakeasy.net...[color=blue]
> Lionel B wrote:[color=green]
> > Greetings,
> >
> > I am trying to implement "element-wise" arithmetic operators for a[/color][/color]
class[color=blue][color=green]
> > 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< ::operator+=<int> >(x); // ??? (line 15)
> > return *this;
> > }
> > };[/color]
>
> Not all compilers will support this yet because of the[/color]
template-template[color=blue]
> parameter. This compiled on GCC 4.0(snapshot).
>
> /snip code/[/color]

Cheers, yes that works for my gcc 3.3.3 too.
[color=blue]
> I don't know how useful this is since it's limited in utility, however[/color]
I[color=blue]
> think that does what you were trying to do.[/color]

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;
}
};
[color=blue]
> 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[/color]

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() ...
[color=blue]
> /snip/[/color]
[color=blue][color=green]
> > // ----- BEGIN CODE -----
> >
> > int main()
> > {
> > int a = 1;
> >
> > operator += (a,1);[/color]
>
> 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.[/color]

Yup - that's my solution above.
[color=blue][color=green]
> > So is it at all possible to use arithmetic operators for elementary
> > types as template arguments?[/color][/color]

So... no.
[color=blue][color=green]
> > A simple workaround is to wrap the
> > operators in a function, but it would be neater (and conceivably[/color][/color]
more[color=blue][color=green]
> > efficient) not to have to do this.[/color]
>
> Most compilers I have used will optimize the function calls away and[/color]
the[color=blue]
> efficiency become a non-issue.[/color]

No doubt.

Thanks,


Gianni Mariani
Guest
 
Posts: n/a
#6: Jul 23 '05

re: Template function type for arithmetic operators for elementary types


Lionel B wrote:

....[color=blue]
> I
>[color=green]
>>think that does what you were trying to do.[/color]
>
>
> 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;
> }
> };[/color]


If all you need is int support, you're OK, the solution I posted will
support any type.
[color=blue]
>
>[color=green]
>>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[/color]
>
>
> 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() ...[/color]

OK - then you're all set.

I thought you were looking for a more generic solution. Good luck.

Closed Thread


Similar C / C++ bytes