473,387 Members | 1,456 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,387 software developers and data experts.

Is this code supposed to throw or not ?


This is one of those, hugh ? moments.

So, GCC behaves just like I would kinda expect it to but it looks VERY
strange.

It's one of those things that could cause silent strife if you included
files in the wrong order.
class X;

extern X a;
extern X b;

// class X is incomplete ... right ?

inline bool IsEqual( X & i, X & j )
{
// using operator & () on an incomplete class ... OK
// OK we know what this is supposed to do ... right ?
return (&i) == (&j);
}

class X
{
public:
// BUT WAIT
// Place a definition for operator & in the class.
// - basically throw allways.
X * operator & () { throw "Yikes"; };
};

inline bool IsEqualOverride( X & i, X & j )
{
// using operator & () - should use the one defined in the cloass
//
return (&i) == (&j);
}

int main()
{
X x;

// should this throw ?
IsEqual( x, x ); // datapoint - GCC does not throw

// this should throw ... right ?
IsEqualOverride(( x, x ); // GCC throws here
}

Jul 19 '05 #1
3 1449
Gianni Mariani wrote in news:bj********@dispatch.concentric.net:

This is one of those, hugh ? moments.

So, GCC behaves just like I would kinda expect it to but it looks VERY
strange.

It's one of those things that could cause silent strife if you included
files in the wrong order.
<£0.02>
Nope, its if you abuse the ability to declare incomplete types.
</£0.02>

class X;

extern X a;
extern X b;

// class X is incomplete ... right ?

inline bool IsEqual( X & i, X & j )
{
// using operator & () on an incomplete class ... OK
// OK we know what this is supposed to do ... right ?
return (&i) == (&j);
I suppose here the compiler should build an overload set for
op & and A) select the right one or B) not find any and use
the comiler generated op &.

gcc does (B). We can't complain, Its done what we asked it too!
}

class X
{
public:
// BUT WAIT
// Place a definition for operator & in the class.
// - basically throw allways.
X * operator & () { throw "Yikes"; };
};
You could replace the above with:

X * operator & ( X & ) { throw "Yikes"; };

inline bool IsEqualOverride( X & i, X & j )
{
// using operator & () - should use the one defined in the cloass
//
Does the same again, this time uses (A).
return (&i) == (&j);
}

class X {}; // to go with the non-member op & above.
int main()
{
X x;

// should this throw ?
Absolutely *NOT* ( was that loud enough :) ), if it did the compiler
would be doing something we didn't ask it to.
IsEqual( x, x ); // datapoint - GCC does not throw

// this should throw ... right ?
Once we remove the extra '(', it should, again its what we asked for.
IsEqualOverride(( x, x ); // GCC throws here
}


Note that the include order problem goes away if we 1) include
a complete declaration for X with member op &, or 2) provide a
declaration ( and optionaly a definition ) for a non-member op &.
Just add a bit more confusion to the mix, if you put
template < typename X > before the declaration of IsEqual() all
3 (*) compilers I checked threw, even when X was complete before
and op & was declared after, defered ADL I belive, though it
could be that templates are fancy macro's :).

(*) msvc 7.1 /Za, gcc 3.2 and bcc32.

Rob.
--
http://www.victim-prime.dsl.pipex.com/
Jul 19 '05 #2
Rob Williscroft wrote:
Gianni Mariani wrote in news:bj********@dispatch.concentric.net: .... <?0.02>
Nope, its if you abuse the ability to declare incomplete types.
</?0.02>
Incomplete types are a convenient way to separate a hairy implementation
from the rest of the application. I've used this to separate a state
machine and an application. In the state machine implementation, a
state was allowed to be part of an expression. In the rest of the
application it was used as an indicator of the current state and the
only interesting operator was is equal. There were other incomplete
types e.g properties that were used to communicate values between app
and state machine. The expression system was big and potentially
misleading for the application and separating state machine and
application code forced application programmers to structure their code
better.

I overlooked the unary & operator implications. (Not that it was used
in the state machine) - just that it's the only operator that may me
used on an incomplete class - but may be overridden once the class is
defined.

It should be one of those big red flahing warnings when overloading
unary operator &.


Absolutely *NOT* ( was that loud enough :) ), if it did the compiler
would be doing something we didn't ask it to.
But a template would/might not ... right ?

IsEqual( x, x ); // datapoint - GCC does not throw

// this should throw ... right ?

Once we remove the extra '(', it should, again its what we asked for.

IsEqualOverride(( x, x ); // GCC throws here
}

Note that the include order problem goes away if we 1) include
a complete declaration for X with member op &, or 2) provide a
declaration ( and optionaly a definition ) for a non-member op &.


I can think of few things in C++ where within a single scope, behaviour
of a function may change depending on where it is defined.

Just add a bit more confusion to the mix, if you put
template < typename X > before the declaration of IsEqual() all
3 (*) compilers I checked threw, even when X was complete before
and op & was declared after, defered ADL I belive, though it
could be that templates are fancy macro's :).


This is one more example whereby even though we use a template depending
on where it is first instantiated, it will either throw or not.

template <typename T>
inline bool Tequal( T & i, T & j )
{
return (&i) == (&j);
}

class X;

bool func( X & i, X & j )
{
return Tequal( i, j );
}

extern X a;
extern X b;

inline bool IsEqual( X & i, X & j )
{
return (&i) == (&j);
}

class X
{
public:
X * operator & () { throw "Yikes"; };

};

inline bool IsEqualOverride( X & i, X & j )
{
return (&i) == (&j);
}
int main()
{
X x;

func( x, x );
Tequal( x, x );

// IsEqual( x, x );

// IsEqualOverride( x, x );
}

I'm starting to think this is a language defect.

Jul 19 '05 #3
Gianni Mariani wrote in news:bj********@dispatch.concentric.net:
Rob Williscroft wrote:
Gianni Mariani wrote in news:bj********@dispatch.concentric.net: ...
<?0.02>
Nope, its if you abuse the ability to declare incomplete types.
</?0.02>


Incomplete types are a convenient way to separate a hairy implementation
from the rest of the application. I've used this to separate a state
machine and an application. In the state machine implementation, a
state was allowed to be part of an expression. In the rest of the
application it was used as an indicator of the current state and the
only interesting operator was is equal. There were other incomplete
types e.g properties that were used to communicate values between app
and state machine. The expression system was big and potentially
misleading for the application and separating state machine and
application code forced application programmers to structure their code
better.

I overlooked the unary & operator implications. (Not that it was used
in the state machine) - just that it's the only operator that may me
used on an incomplete class - but may be overridden once the class is
defined.

It should be one of those big red flahing warnings when overloading
unary operator &.


Well It really applies to all operator's and overloadable function's
that take references or pointers.

Absolutely *NOT* ( was that loud enough :) ), if it did the compiler
would be doing something we didn't ask it to.


But a template would/might not ... right ?


A template should use ADL (koenig lookup) at the point of instantiation
(as I understand it), so It should. My smart-ass remark about templates
being macro's was aluding to the fact many compilers will get this
right, even though they arn't doing the right thing.

[snip]

Note that the include order problem goes away if we 1) include
a complete declaration for X with member op &, or 2) provide a
declaration ( and optionaly a definition ) for a non-member op &.


I can think of few things in C++ where within a single scope, behaviour
of a function may change depending on where it is defined.


Overload resolution changes it all the time.

int f( double );
int example() { return f( 0 ); }
int f( int ); // move this up a line and the programme changes.

Just add a bit more confusion to the mix, if you put
template < typename X > before the declaration of IsEqual() all
3 (*) compilers I checked threw, even when X was complete before
and op & was declared after, defered ADL I belive, though it
could be that templates are fancy macro's :).

This is one more example whereby even though we use a template depending
on where it is first instantiated, it will either throw or not.


template <typename T>
inline bool Tequal( T & i, T & j )
{
return (&i) == (&j);
}

class X;

bool func( X & i, X & j )
{
return Tequal( i, j );
}

extern X a;
extern X b;

inline bool IsEqual( X & i, X & j )
{
return (&i) == (&j);
}

class X
{
public:
X * operator & () { throw "Yikes"; };

};

inline bool IsEqualOverride( X & i, X & j )
{
return (&i) == (&j);
}
[snip - main()]

I'm starting to think this is a language defect.


I changed main() thus:

#define Try( x ) { \
std::cout << #x "\t"; \
try {{x} std::cout << "OK"; } catch (char const *s) { std::cout << s; } \
std::cout << std::endl; }\

int main()
{
X x;
Try( func( x, x ); )
Try( Tequal( x, x ); )
Try( IsEqual( x, x ); )
Try( IsEqualOverride( x, x ); )
}

msvc 7.1 /Za:
func( x, x ); Yikes
Tequal( x, x ); Yikes
IsEqual( x, x ); OK
IsEqualOverride( x, x ); Yikes

gcc 3.2 (g++):
func( x, x ); OK
Tequal( x, x ); OK
IsEqual( x, x ); OK
IsEqualOverride( x, x ); Yikes

bcc32:
func( x, x ); OK
Tequal( x, x ); Yikes
IsEqual( x, x ); Yikes
IsEqualOverride( x, x ); Yikes
My reading would be that results should be OK, Yikes, OK, Yikes.
But this is impossible, as it means having 2 version's of Tequal<X>.

I think you're right about there being a defect in here. The question
is - what's the defect and what's the fix:

1) Have all overload resolution done by the linker - all output Yikes.
this hasn't got any legs, it just wouldn't be C++ anymore!
Breaks mode code than you can shake a stick at.

2) Stop ADL-at-point-of-instantiation adding to the overload set.
Output as gcc. But it breaks a whole bunch of existing template
code, some in namesace std!

3) Stop ADL-at-point-of-instantiation adding to the overload set if
and only if there is one or more (possibly compiler generated)
overloads available. Output as gcc again. Breaks less code than
(2), possibly some in namespace std.

I'd actually favour (2) as specialization does IMO a much cleaner
job than ADL-at-point-of-instantiation, particularly if we get
partial function specialization (*) as well.

(*) This is being considerd I belive.

Rob.
--
http://www.victim-prime.dsl.pipex.com/
Jul 19 '05 #4

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

242
by: James Cameron | last post by:
Hi I'm developing a program and the client is worried about future reuse of the code. Say 5, 10, 15 years down the road. This will be a major factor in selecting the development language. Any...
3
by: Eric Hudson | last post by:
A quick rant and a question. Why does the designer in VS2003 delete code about custom components that it can't load? I've had large sections of forms disappear in the blink of an eye just...
16
by: Esteban404 | last post by:
I have a Winform news kiosk app which connects to a SQL database. When the main form is running, it reaches a threshold time or number of sequential operations and then loads another instance with...
6
by: C# Learner | last post by:
In the following two code blocks, DoSomethingUseful throws AnException, while neither of the other called methods throw any exceptions. Which of the code blocks is better (in terms of readability,...
1
by: Egbert Nierop \(MVP for IIS\) | last post by:
Hi, I'm 'improving' CComBSTR (yes, I do still program unmanaged code in addition to C# ) to contain features, not found in it. Does anybody have good code which maches LastIndexOf()? If...
171
by: tshad | last post by:
I am just trying to decide whether to split my code and uses code behind. I did it with one of my pages and found it was quite a bit of trouble. I know that most people (and books and articles)...
21
by: Jim | last post by:
I am trying to write an HTTP/HTTPS proxy server in VB.Net 2005. But, I don't really even know how the internal workings of a proxy should act. Does anyone have anything on the protocols used in...
3
by: josh.kuo | last post by:
Sorry about the subject, I can't think of a better one. I recently wrote some PHP classes that I think might be of interest to this group. Since I have been reaping the benefits of reading news...
27
by: George2 | last post by:
Hello everyone, Should I delete memory pointed by pointer a if there is bad_alloc when allocating memory in memory pointed by pointer b? I am not sure whether there will be memory leak if I do...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.