Template function type for arithmetic operators for elementary types | | |
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 | | | | 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 | | | | 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. | | | | 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] | | | | 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, | | | | 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. |  | | | | /bytes/about
We are a network of experts and professionals in IT and software development that help one another with answers to tough questions and share insights.
Get the best answers to your questions from over 226,449 network members.
|