C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Overloading binary operators for class template args

 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated)
View previous topic :: View next topic  
Author Message
Guest






PostPosted: Wed Sep 20, 2006 9:39 pm    Post subject: Overloading binary operators for class template args Reply with quote



Could anyone please enlighten me on how to overload binary ops (e.g.
'+', '|') for class template argument?

Suppose I have some user defined type "Type" that presumably doesn't
already have the types of operators I'm interested in overloaded.
I want to write a template class "Wrapper":

template <typename T> class Wrapper;

so that the code like the one below will compile and work:

void f(Wrapper<Type> wt) { ... };

Type a = foo;
Type b = bar;
Type c = baz;
Wrapper<Type> w(c);

w = a + b;
w = (a | b) & c;

f(a ^ b);

I can easily do this for a non-template, "Type"-specific "Wrapper"
class, but once you have many "Type" types to wrap this becomes either
an exercise in copy-paste or an exercise in macros fiddling. I can do
it with template "Wrapper" class and a macro to define the necessary
non-member binary ops for "Type", but the burden of using the macro
lies on user's shoulders which is no good. I can even do it with a
template "Wrapper" class and nothing else using at least one widely
used but non-standard C++ dialect compiler. But how do I do it in
standard C++98 or at least in VC71/VC8/GCC3/GCC4 compatible manner?

I'd readily settle for an implementation that doesn't have ops of
interest overloaded for BOTH arguments of type "Type" (i.e. one
"Wrapper" and one "Type"), if someone could just point out how do I
pull it off while making code similar to the above work. I'm
clearly interested in "observable behavior", rather than in particular
implementation syntax to make it work.

Just in case: modifying the original "Type" types themselves is
certainly not an option. That's the whole reason for creating the
"Wrapper" in the first place...

Thanks in advance.

A.C.


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
kanze
Guest





PostPosted: Thu Sep 21, 2006 10:17 pm    Post subject: Re: Overloading binary operators for class template args Reply with quote



amwyll.codydd (AT) gmail (DOT) com wrote:
Quote:
Could anyone please enlighten me on how to overload binary ops (e.g.
'+', '|') for class template argument?

Suppose I have some user defined type "Type" that presumably doesn't
already have the types of operators I'm interested in overloaded.
I want to write a template class "Wrapper":

template <typename T> class Wrapper;

so that the code like the one below will compile and work:

void f(Wrapper<Type> wt) { ... };

Type a = foo;
Type b = bar;
Type c = baz;
Wrapper<Type> w(c);

w = a + b;
w = (a | b) & c;

f(a ^ b);

I can easily do this for a non-template, "Type"-specific "Wrapper"
class, but once you have many "Type" types to wrap this becomes either
an exercise in copy-paste or an exercise in macros fiddling. I can do
it with template "Wrapper" class and a macro to define the necessary
non-member binary ops for "Type", but the burden of using the macro
lies on user's shoulders which is no good. I can even do it with a
template "Wrapper" class and nothing else using at least one widely
used but non-standard C++ dialect compiler. But how do I do it in
standard C++98 or at least in VC71/VC8/GCC3/GCC4 compatible manner?

Well, obviously, it depends on the characteristics of Type. If
Type is a typedef for double, for example, you can't do it,
because the operator+ is already defined, and it doesn't return
Wrapper<double>. Given this, I'll suppose that Type is a user
defined type, written by you (or by users of your class). Given
this, you could always require that Type derive from a template
class WrapperOps, which looked something like:

template< typename T >
class WrapperOps
{
friend inline Wrapper< T > operator+(
T const& lhs, T const& rhs )
{
// ...
}
// ...
} ;

You could easily use concept checking to enforce that anytime
Wrapper<T> was instantiated, WrapperOps<T> was a base class of
T.

If the code to implement the operators is more than you want in
an inline function, you can simply write a template function for
it, and foreward in the inline operator.

Quote:
I'd readily settle for an implementation that doesn't have ops
of interest overloaded for BOTH arguments of type "Type" (i.e.
one "Wrapper" and one "Type"), if someone could just point out
how do I pull it off while making code similar to the above
work. I'm clearly interested in "observable behavior", rather
than in particular implementation syntax to make it work.

Same trick, except that you can also do it by deriving Wrapper
from WrapperOps, or just defining the operators as inline
friends in Wrapper.

Quote:
Just in case: modifying the original "Type" types themselves
is certainly not an option. That's the whole reason for
creating the "Wrapper" in the first place...

In which case, the trick can't be used for the Type op Type
situation. The trick only works (today) because of the way ADL
works, so at least one of the operators must have the same type
as the class containing the inline function, or a class derived
from it. The operators thus defined are only visible through
ADL.

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Amwyll Codydd
Guest





PostPosted: Tue Sep 26, 2006 11:13 pm    Post subject: Re: Overloading binary operators for class template args Reply with quote



Thanks for taking the time to answer, James, and sorry for the late
follow-up.

kanze wrote:
Quote:
amwyll.codydd (AT) gmail (DOT) com wrote:
Suppose I have some user defined type "Type" that presumably doesn't
already have the types of operators I'm interested in overloaded.
If Type is a typedef for double, for example, you can't do it,
because the operator+ is already defined, and it doesn't return
Wrapper<double>.

Yes, I know, that's why I explicitly specified my assumptions about
the type and operators (see above).

Quote:
Given this, you could always require that Type derive from a
template class WrapperOps, which looked something like:

As I mentioned in my original message, touching the original types is
out of the question. Besides, how could I ever require that, e.g. enum
was to be derived from WrapperOps? :)

Quote:
Same trick, except that you can also do it by deriving Wrapper
from WrapperOps, or just defining the operators as inline
friends in Wrapper.

<snip>

Quote:
The trick only works (today) because of the way ADL
works, so at least one of the operators must have the same type
as the class containing the inline function, or a class derived
from it. The operators thus defined are only visible through
ADL.

That's precisely the problem, James, because implicit user-defined
conversions are NOT considered during ADL. Which means that code
like :

Quote:
Type a = foo;
Type b = bar;
Type c = baz;
Wrapper<Type> w(c);

w = a + b;
w = (a | b) & c;

simply won't work, which means I'm back to square one...

Any other ideas, anyone?

A.C.


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated) All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.