Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Why cant we overload certain operators in C++

1 view
Skip to first unread message

Venkat

unread,
Jan 16, 2006, 9:19:25 AM1/16/06
to
Hi

Can anyone tell me what is the reason for which operators like ::, ..
.* and ?: have been made nonoverloadable?


Regards

Venkat


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

Attila Feher

unread,
Jan 16, 2006, 5:27:43 PM1/16/06
to
Venkat wrote:
> Hi
>
> Can anyone tell me what is the reason for which operators like ::, ..
> .* and ?: have been made nonoverloadable?

Why would you need to overload those? What do you try to achieve?

WW aka Attila

Stanimir Kabaivanov

unread,
Jan 16, 2006, 5:43:11 PM1/16/06
to
Hi Venkat,

> Can anyone tell me what is the reason for which operators like ::, ..
> .* and ?: have been made nonoverloadable?
>
Well, for example one of the main reasons is that they accept name (and
not a value) as their second operand (except ?: of course :) ).
In case overloading them is allowed this would bring both souce code
readability and compilation into a lot of trouble. First three of the
operators you've listed (:: . and .* (have no idea what the second dot
in .. is - perhaps a typing mistake? ) ) are the primary means of
accessing member data and functions.
Allowing changes in them would simply "destroy" any language rules.

Besides, there are two more things one's not allowed to overload sizeof
and typeid.

HTH,
Stanimir Kabaivanov

PPD

unread,
Jan 17, 2006, 7:57:01 AM1/17/06
to
Let's hear the creator.

Bjarne Stroustrup comprehensively answers this question "Why can't I
overload dot, ::, sizeof, etc.?" in

http://public.research.att.com/~bs/bs_faq2.html.

This should help.

PPD

Francis Glassborow

unread,
Jan 17, 2006, 7:55:47 AM1/17/06
to
In article <1137397980....@o13g2000cwo.googlegroups.com>,
Venkat <ansvenka...@gmail.com> writes

>Hi
>
>Can anyone tell me what is the reason for which operators like ::, ..
>.* and ?: have been made nonoverloadable?

Can you tell me why you would want to? We arguably allow overloading of
too many operators already as those such as '||' and '&&' already cannot
duplicate the builtin semantics for user defined types.


>

--
Francis Glassborow ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects

kanze

unread,
Jan 17, 2006, 10:19:05 AM1/17/06
to
Stanimir Kabaivanov wrote:
> Hi Venkat,
> > Can anyone tell me what is the reason for which operators
> > like ::, .. .* and ?: have been made nonoverloadable?

> Well, for example one of the main reasons is that they accept
> name (and not a value) as their second operand (except ?: of
> course :) ).

But that's also true for ->, which is overloadable.

In the case of ::, the operator only affects name lookup, which
occurs at compile time, so it's hard to imagine what overloading
it could mean conceptually.

In the case of ?:, it's a terciary operator, and it probably
isn't worth the effort to introduce the syntax necessary to
support it. There's also the fact that only two of the three
sub-expressions are executed; it's pretty hard to see how to do
this in an overloaded version.

Operators like ?:, but also &&, || and , (the comma operator)
introduce sequence points and impose ordering, neither of which
occurs in the case of overloading. Arguably, since the
overloaded version cannot possibly have a similar meaning as the
non-overloaded version, none of them should support overloading.
At any rate, good programming practice says to never overload
them.

Operators like , (the comma operator), unary & and ?: (for the
second and third parameters) are already defined for all
possible types. Overloading them changes the semantics of a
previously legal program. As such, they shouldn't be used, even
when the can be legally used.

There's absolutely no reason why . and .* should not be
overloaded. The fact that they cannot be means that you cannot
create a smart reference, or a proxy which behaves like a
reference.

--
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

Bob Hairgrove

unread,
Jan 18, 2006, 6:28:21 AM1/18/06
to
On 17 Jan 2006 10:19:05 -0500, "kanze" <ka...@gabi-soft.fr> wrote:

>In the case of ?:, it's a terciary operator

Shouldn't it be "ternary" (unary, binary, ternary...)?

--
Bob Hairgrove
NoSpam...@Home.com

Niklas Matthies

unread,
Jan 18, 2006, 9:51:23 AM1/18/06
to
On 2006-01-17 15:19, kanze wrote:
:

>> > Can anyone tell me what is the reason for which operators
>> > like ::, .. .* and ?: have been made nonoverloadable?
:

> In the case of ?:, it's a terciary operator, and it probably

ternary

> isn't worth the effort to introduce the syntax necessary to
> support it.

I don't think that introducing

R operator ? : (A a, B b, C c) // non-member function

and possibly

R operator ? : (B b, C c) // member function

would require more effort than for the other overloadable operators.

> There's also the fact that only two of the three sub-expressions are
> executed; it's pretty hard to see how to do this in an overloaded
> version.

But that's the same for &&, ||, and ,, so the question why ?: is not
overloadable given that these others are overloadable is justified.
It could certainly be useful for expression templates, where the
short-circuiting semantics can be maintained.

-- Niklas Matthies

Maciej Sobczak

unread,
Jan 18, 2006, 9:54:14 AM1/18/06
to
kanze wrote:

> Operators like , (the comma operator), unary & and ?: (for the
> second and third parameters) are already defined for all
> possible types. Overloading them changes the semantics of a
> previously legal program.

Except when it doesn't.

If there is a set of user-defined types and the client code that already
uses those types, then later overloading the predefined operators can
indeed change the semantics of a program that was already legal.

But if the set of types is developed and supplied *together* with those
operators (so that both are part of some solution), then there is no
existing code that might possibly use these types with the predefined
versions of operators and therefore there is nothing to break.


--
Maciej Sobczak : http://www.msobczak.com/
Programming : http://www.msobczak.com/prog/

kanze

unread,
Jan 19, 2006, 11:10:54 AM1/19/06
to
Niklas Matthies wrote:
> On 2006-01-17 15:19, kanze wrote:

> >> > Can anyone tell me what is the reason for which operators
> >> > like ::, .. .* and ?: have been made nonoverloadable?

> > In the case of ?:, it's a terciary operator, and it probably

> ternary

> > isn't worth the effort to introduce the syntax necessary to
> > support it.

> I don't think that introducing

> R operator ? : (A a, B b, C c) // non-member function

> and possibly

> R operator ? : (B b, C c) // member function

> would require more effort than for the other overloadable
> operators.

A priori, I'm not sure I see any great problem either. On the
other hand, I've never written a C++ compiler, so I can't be
sure. I do remember reading somewhere that the reason was
simply that they didn't seem to be worth the effort. (Note that
if the added value is really negligible, even a minimal effort
is too much.)

> > There's also the fact that only two of the three
> > sub-expressions are executed; it's pretty hard to see how to
> > do this in an overloaded version.

> But that's the same for &&, ||, and ,, so the question why ?:
> is not overloadable given that these others are overloadable
> is justified.

That's a good question. I'm not sure that in retrospect, it
wouldn't have been a better idea to ban them as well. I do know
that no coding guidelines allows them, simply because skilled
C++ programmers do write code counting on the sequence points;
things like:

if ( p != NULL && p->f() ... )

are frequent. Going against user expectations is not generally
a good idea.

> It could certainly be useful for expression templates, where
> the short-circuiting semantics can be maintained.

If you could guarantee that it would only be used within
expression templates...

--
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

kanze

unread,
Jan 19, 2006, 11:10:32 AM1/19/06
to
Francis Glassborow wrote:
> In article
> <1137397980....@o13g2000cwo.googlegroups.com>, Venkat
> <ansvenka...@gmail.com> writes

> >Can anyone tell me what is the reason for which operators


> >like ::, .. .* and ?: have been made nonoverloadable?

> Can you tell me why you would want to? We arguably allow
> overloading of too many operators already as those such as
> '||' and '&&' already cannot duplicate the builtin semantics
> for user defined types.

Well, . and .* could be useful for writing proxies for
references; I've wanted . once or twice. But I agree that
overloading ||, && and , is never a good idea (and I can't think
of a case where unary & would not cause problems either).

Tell you what: let's trade. Get rid of &&, || and ,, and
introduce . and .* in their place:-).

(While I think that Francis realizes just how much I'm joking,
to make it perfectly clear to others: I am not in favor of
getting rid of existing functionality, no matter how bad or
useless I might think it is. I do think that adding the
possibility to overload . and .* would be a good idea, although
I recognize that doing so is not nearly as trivial as it is
sometimes presented.)

--
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

kanze

unread,
Jan 19, 2006, 11:09:41 AM1/19/06
to
Maciej Sobczak wrote:
> kanze wrote:

> > Operators like , (the comma operator), unary & and ?: (for
> > the second and third parameters) are already defined for all
> > possible types. Overloading them changes the semantics of a
> > previously legal program.

> Except when it doesn't.

> If there is a set of user-defined types and the client code
> that already uses those types, then later overloading the
> predefined operators can indeed change the semantics of a
> program that was already legal.

> But if the set of types is developed and supplied *together*
> with those operators (so that both are part of some solution),
> then there is no existing code that might possibly use these
> types with the predefined versions of operators and therefore
> there is nothing to break.

I think that the key is "developed and supplied together". It's
not always evident that this can be enforced, and fatally,
sooner or later, you will have a programmer who expects the
built in semantics, and doesn't get them. Or vice versa -- a
classical example might be an overloaded unary &, which isn't
picked up in:

class T ;

extern void f( T* ) ;

void
g( T& param )
{
f( &param ) ;
}

Or maybe is picked up, depending on whether one of the other
include files includes the definition of the class (with the
declaration of the operator) or not. (Note that the original
programmer may have included the necessary header, and it got
removed by a maintenance programmer charged with reducing
compiler dependancies, when he noted that the only uses of T
were as references and pointers.)

In the end, they're nice toys for experimenting with yet fancier
ways to obfuscate code, but they're not usable in a professional
environment.

--
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

Allan W

unread,
Jan 19, 2006, 7:04:13 PM1/19/06
to
> Niklas Matthies wrote:
> > But that's the same for &&, ||, and ,, so the question why ?:
> > is not overloadable given that these others are overloadable
> > is justified.

kanze wrote:
> That's a good question. I'm not sure that in retrospect, it
> wouldn't have been a better idea to ban them as well. I do know
> that no coding guidelines allows them, simply because skilled
> C++ programmers do write code counting on the sequence points;
> things like:
>
> if ( p != NULL && p->f() ... )
>
> are frequent. Going against user expectations is not generally
> a good idea.

But if p is a pointer, then overloading && or || wouldn't affect that
statement.
It would only affect statements such as
if (o && o.f()) ...
where o is some user-defined type.

Dietmar Kuehl

unread,
Jan 20, 2006, 7:42:51 AM1/20/06
to
Allan W wrote:
> kanze wrote:
>> That's a good question. I'm not sure that in retrospect, it
>> wouldn't have been a better idea to ban them as well. I do know
>> that no coding guidelines allows them, simply because skilled
>> C++ programmers do write code counting on the sequence points;
>> things like:
>>
>> if ( p != NULL && p->f() ... )
>>
>> are frequent. Going against user expectations is not generally
>> a good idea.
>
> But if p is a pointer, then overloading && or || wouldn't affect that
> statement.

Can you please explain the output of the following program to me
and why the overload does not affect the statement...? Of course,
I failed to put the "..." into the if-statement. Maybe this changes
the look-up rules :-)

#include <iostream>
#include <stddef.h>

struct bar {};
struct foo { bar f() { return bar(); } };

bool operator&& (bool, bar const&)
{
std::cout << "my operator&&() was called!\n";
return false;
}

int main()
{
foo f, *p = &f;
if (p != NULL && p->f())
return 0;
}
--
<mailto:dietma...@yahoo.com> <http://www.dietmar-kuehl.de/>
<http://www.eai-systems.com> - Efficient Artificial Intelligence

Dietmar Kuehl

unread,
Jan 20, 2006, 7:41:31 AM1/20/06
to
kanze wrote:
> Operators like ?:, but also &&, || and , (the comma operator)
> introduce sequence points and impose ordering, neither of which
> occurs in the case of overloading. Arguably, since the
> overloaded version cannot possibly have a similar meaning as the
> non-overloaded version, none of them should support overloading.
> At any rate, good programming practice says to never overload
> them.

I disagree with the absolute notion of the above statement! The
operators you mention are quite useful for expression templates.
Although I agree that there are rare reasons to overload them,
there are uses where overloading them can even have the correct
semantics, e.g. short-circuiting the condition. Of course, the
evaluator resulting from the expression would need to take care
of this.


--
<mailto:dietma...@yahoo.com> <http://www.dietmar-kuehl.de/>
<http://www.eai-systems.com> - Efficient Artificial Intelligence

[ See http://www.gotw.ca/resources/clcm.htm for info about ]

Thomas Tutone

unread,
Jan 20, 2006, 7:44:47 AM1/20/06
to
Allan W wrote:

> kanze wrote:
> > That's a good question. I'm not sure that in retrospect, it
> > wouldn't have been a better idea to ban them as well. I do know
> > that no coding guidelines allows them, simply because skilled
> > C++ programmers do write code counting on the sequence points;
> > things like:
> >
> > if ( p != NULL && p->f() ... )
> >
> > are frequent. Going against user expectations is not generally
> > a good idea.
>
> But if p is a pointer, then overloading && or || wouldn't affect that
> statement.

Why not? If shortcircuit logic is disabled because && has been
overloaded, couldn't the above code result in dereferencing a NULL
pointer? Or am I just missing your point?

Best regards,

Tom

kanze

unread,
Jan 20, 2006, 10:56:39 AM1/20/06
to
Dietmar Kuehl wrote:
> kanze wrote:
> > Operators like ?:, but also &&, || and , (the comma
> > operator) introduce sequence points and impose ordering,
> > neither of which occurs in the case of overloading.
> > Arguably, since the overloaded version cannot possibly have
> > a similar meaning as the non-overloaded version, none of
> > them should support overloading. At any rate, good
> > programming practice says to never overload them.

> I disagree with the absolute notion of the above statement!
> The operators you mention are quite useful for expression
> templates. Although I agree that there are rare reasons to
> overload them, there are uses where overloading them can even
> have the correct semantics, e.g. short-circuiting the
> condition. Of course, the evaluator resulting from the
> expression would need to take care of this.

Well, the rule 0 of the coding guidelines always applies:-).
(The rule 0 is always: any rule in this guidelines can be
ignored if there is a justifiable reason why it is necessary.)

I'll admit I hadn't given the meta-programmation aspects too
much consideration. What I'm worried about is, of course, code
existing in which the sequence points (and the short circuiting
aspects) aren't respected. If I see something like " a && b ",
I should be able to count on b not being evaluated if a is
false. Regardless of the types involved. (And of course, I'm
thinking of run-time evaluation.)

--
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

Allan W

unread,
Jan 20, 2006, 3:12:16 PM1/20/06
to
> > kanze wrote:
> >> if ( p != NULL && p->f() ... )

> Allan W wrote:
> > But if p is a pointer, then overloading && or || wouldn't affect that
> > statement.

Dietmar Kuehl wrote:
> Can you please explain the output of the following program to me
> and why the overload does not affect the statement...? Of course,
> I failed to put the "..." into the if-statement. Maybe this changes
> the look-up rules :-)
>
> #include <iostream>
> #include <stddef.h>
>
> struct bar {};
> struct foo { bar f() { return bar(); } };
>
> bool operator&& (bool, bar const&)
> {
> std::cout << "my operator&&() was called!\n";
> return false;
> }
>
> int main()
> {
> foo f, *p = &f;
> if (p != NULL && p->f())
> return 0;
> }

I was thinking that you can't overload operator&&(bool, bool)
I missed that p->f() might return a user-defined type.
Sorry.

Jerry Coffin

unread,
Jan 22, 2006, 7:03:26 AM1/22/06
to
kanze wrote:

[ ... ]

> Well, . and .* could be useful for writing proxies for
> references; I've wanted . once or twice. But I agree that
> overloading ||, && and , is never a good idea (and I can't think
> of a case where unary & would not cause problems either).

I'm not really sure about && or ||, but I've done a bit of overloading
of operator, that I didn't think was entirely bad. I think Thorsten
Ottosen did a better job of it than I did though. He wrote the
Boost::Assign library, which supports things like this:

vector<int> v;
v += 1,3,5,7,9,2,4,6,8;

which strikes me as quite easy to understand. I'll admit it changes the
semantics you'd normally expect from C++, but I'd posit that to most
people most of the time, these semantics make more sense. Most
reactions I've seen/heard are along the lines of "That would sure be
cool -- too bad it can't be done" -- followed by amazement when this
compiles and does exactly what they hoped for.

--
Later,
Jerry.

kanze

unread,
Jan 23, 2006, 7:31:15 AM1/23/06
to
Jerry Coffin wrote:
> kanze wrote:

> [ ... ]

> > Well, . and .* could be useful for writing proxies for
> > references; I've wanted . once or twice. But I agree that
> > overloading ||, && and , is never a good idea (and I can't
> > think of a case where unary & would not cause problems
> > either).

> I'm not really sure about && or ||, but I've done a bit of
> overloading of operator, that I didn't think was entirely bad.
> I think Thorsten Ottosen did a better job of it than I did
> though. He wrote the Boost::Assign library, which supports
> things like this:

> vector<int> v;
> v += 1,3,5,7,9,2,4,6,8;

> which strikes me as quite easy to understand.

Except, of course, that logically, you'd write it as:
vector<int> v = 1,3...
which doesn't work. And what happens if the example is a little
more complex:
v += f(), g(), h() ;

This no longer does what any experienced C++ programmer knows it
does. In fact, the example only looks good if you use
constants, because everyone knows you don't want to throw away
the results of a constant expression, so you wouldn't write the
statement unless there were tricky overloads.

> I'll admit it changes the semantics you'd normally expect from
> C++, but I'd posit that to most people most of the time, these
> semantics make more sense.

I'd posit that to most people, most of the time, the semantics
of the comma operator don't make much sense to begin with. With
most of the programmers I know, when they see a comma, they
think it is a separator, not an operator.

The above use actually plays on this: it looks and acts more
like a comma separator than like a comma operator. Except that
it only works in contexts where a comma separator is illegal
(since the separator role has precedance over the operator
role). Which can only be a cause of confusion.

> Most reactions I've seen/heard are along the lines of "That
> would sure be cool -- too bad it can't be done" -- followed by
> amazement when this compiles and does exactly what they hoped
> for.

Most of the "that would be cool" reactions I've seen change
radically when it is realized that you can't do it in the
declaration, where you would most expect doing it.

--
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

Dave Harris

unread,
Jan 24, 2006, 6:52:12 AM1/24/06
to
jerry....@gmail.com (Jerry Coffin) wrote (abridged):

>
> I'm not really sure about && or ||, but I've done a bit of overloading
> of operator, that I didn't think was entirely bad. I think Thorsten
> Ottosen did a better job of it than I did though. He wrote the
> Boost::Assign library, which supports things like this:
>
> vector<int> v;
> v += 1,3,5,7,9,2,4,6,8;
>
> which strikes me as quite easy to understand.

I think it is less easy than using operator<<().

v << 1 << 3 << 5 << 7 << 9 << 2 << 4 << 6 << 8;

For me appending to a vector and appending to a stream are similar, even
if one involves formatting as text and the other doesn't. Using comma
seems unnecessarily surprising given the prior meanings of comma, and
using assignment and/or addition is worse. Presumably it doesn't support:

v = v + 1;
v = 1 + v;
vector<int> v2;
v += v2;
v = v + v2; // Concatination or elementwise addition?

I just don't see a good reason to use comma and += here.

-- Dave Harris, Nottingham, UK.

0 new messages