Dear all,
I haven't really written any C++ code in recent two years, so lots of
my old kknowledge and concept just don't work for me anymore. Still
it's hard for me to understand why the following code is not working
anymore.
#include <iostream>
int main () {
try
{
throw "out of range";
}
catch (char * str)
{
cout << "Exception: " << str << endl;
}
return 0;
}
I can compile it under several versions of Linux ( from gcc 2.96 of
RedHat 7.3 to gcc 3.3.1 of latest Mandrake) without any error, but the
executable code aborted when I run it, displaying: Abort (core
dumped).
I saw similar examples from text books somewhere. Also, if I change
the constant string "Out of range" to a string variable, this code
works. So is it a string related problem?
Thanks!
JK
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
jkhongyu (1)
|
12/10/2003 11:36:03 AM |
|
On 10 Dec 2003 06:36:03 -0500, jkhongyu@yahoo.com (jkhongyu@yahoo.com) wrote:
>I haven't really written any C++ code in recent two years, so lots of
>my old kknowledge and concept just don't work for me anymore. Still
>it's hard for me to understand why the following code is not working
>anymore.
>
>#include <iostream>
>
>int main () {
> try
> {
> throw "out of range";
> }
> catch (char * str)
> {
> cout << "Exception: " << str << endl;
> }
> return 0;
>}
If this "worked" then your exception handler could modify the
string constant.
Instead, try
catch( char const* str )
But as a matter of coding style, _do not_ throw anything else than
objects of std::exception or derived classes.
Personal preference: throw std::rutime_error or derived for situations
where 'assert' would be completely inappropriate, throw an object of
class std::exception or a derived class that is not in the std::runtime_error
tree for exceptions where 'assert' could conceivably be used.
The rationale for that preference is that std::bad_exception does not derive
from std::logic_error (and std::bad_alloc is a mysterious beast), and that it
allows code to catch only std::runtime_error (and derived), thus passing the
more hopeless, fun-spoiling exceptions up to a top-level handler.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
alfps
|
12/10/2003 4:05:43 PM
|
|
In article <2c7916f0.0312092255.3da0c7e5@posting.google.com>,
"jkhongyu@yahoo.com" <jkhongyu@yahoo.com> writes
>Dear all,
>
>I haven't really written any C++ code in recent two years, so lots of
>my old kknowledge and concept just don't work for me anymore. Still
>it's hard for me to understand why the following code is not working
>anymore.
>
>#include <iostream>
>
>int main () {
> try
> {
> throw "out of range";
> }
> catch (char * str)
> {
> cout << "Exception: " << str << endl;
> }
> return 0;
>}
>
>
>I can compile it under several versions of Linux ( from gcc 2.96 of
>RedHat 7.3 to gcc 3.3.1 of latest Mandrake) without any error, but the
>executable code aborted when I run it, displaying: Abort (core
>dumped).
>
>I saw similar examples from text books somewhere. Also, if I change
>the constant string "Out of range" to a string variable, this code
>works. So is it a string related problem?
The critical change is that the type of a string literal is now an array
of n const char which decays to char const *. In a restricted number of
contexts (to preserve legacy code) there is a conversion from string
literal to char*. The above is not one of those cases. What you have
thrown is an const char[14] which can be caught as either a const
char[14] & (possibly const qualified) or as a char const *.
Of course there is nothing wrong with any individual line of your source
code and so it will always compile but the catch will fail to catch the
exception thrown hence your program terminates with an 'unhandled
exception error.'
--
Francis Glassborow ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
Francis
|
12/10/2003 4:26:02 PM
|
|
Hey JK,
There are a couple things you can do:
1. Insert the line 'using namespace std' directly below the #include.
2. Include iostream.h instead of the current one you are using; this will
avoid the need for a using declaration.
3. In main, insert the lines 'using std::cout' and 'using std::end'
To find out why these solutions fix the problem, check out the explination
of namespaces in you C++ book or post back here w/ more questions.
Have a nice day.
--
Regards,
Travis Spencer
<jkhongyu@yahoo.com> wrote in message
news:2c7916f0.0312092255.3da0c7e5@posting.google.com...
> Dear all,
>
> I haven't really written any C++ code in recent two years, so lots of
> my old kknowledge and concept just don't work for me anymore. Still
> it's hard for me to understand why the following code is not working
> anymore.
>
> #include <iostream>
>
> int main () {
> try
> {
> throw "out of range";
> }
> catch (char * str)
> {
> cout << "Exception: " << str << endl;
> }
> return 0;
> }
>
>
> I can compile it under several versions of Linux ( from gcc 2.96 of
> RedHat 7.3 to gcc 3.3.1 of latest Mandrake) without any error, but the
> executable code aborted when I run it, displaying: Abort (core
> dumped).
>
> I saw similar examples from text books somewhere. Also, if I change
> the constant string "Out of range" to a string variable, this code
> works. So is it a string related problem?
>
> Thanks!
>
> JK
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
Travis
|
12/10/2003 8:15:06 PM
|
|
jkhongyu@yahoo.com wrote:
> #include <iostream>
>
> int main () {
> try
> {
> throw "out of range";
> }
> catch (char * str)
catch (const char* str)
or
catch (const char str[])
> {
> cout << "Exception: " << str << endl;
std::cout << "Exception: " << str << std::endl;
> }
> return 0;
> }
>
> I can compile it under several versions of Linux ( from gcc 2.96 of
> RedHat 7.3 to gcc 3.3.1 of latest Mandrake) without any error,
I'm surprised to hear that - you didn't qualify cout or endl with std::.
> but the
> executable code aborted when I run it, displaying: Abort (core
> dumped).
String literals are arrays of const chars, not arrays of chars.
Best regards,
Tom
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
Thomas8675309
|
12/10/2003 8:16:35 PM
|
|
jkhongyu@yahoo.com <jkhongyu@yahoo.com> wrote:
: #include <iostream>
: int main () {
: try
: {
: throw "out of range";
: }
: catch (char * str)
: {
: cout << "Exception: " << str << endl;
std::cout << "Exception: " << str << std::endl;
: }
: return 0;
: }
: I saw similar examples from text books somewhere. Also, if I change
: the constant string "Out of range" to a string variable, this code
: works. So is it a string related problem?
"out of range" is of type const char[13] and gets thrown as a const char*
pointing to the first character. You try to catch a pointer to a non-const
char, which does not match your exception.
catch (const char *str)
should work fine. When you use an extra variable like:
try
{
char * exc = "out of range";
throw exc;
}
a special rule kicks in which allows string literals to be assigned to
char * for backward compatibility (discussed in another thread recently).
When you then throw this variable, it is of type char * without the const
and can be caught by your catch phrase.
--
Frank Thilo - thilo@unix-ag.org IRC: Chestal
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
Frank
|
12/10/2003 8:17:36 PM
|
|
jkhongyu@yahoo.com wrote:
> try
> {
> throw "out of range";
> }
> catch (char * str)
> {
> cout << "Exception: " << str << endl;
> }
Try this more condensed version:
char* str = "out of range";
String literals are constants in C++.
Uli
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
Ulrich
|
12/10/2003 8:18:40 PM
|
|
> try
> {
> throw "out of range";
> }
> catch (char * str)
> {
> cout << "Exception: " << str << endl;
> }
Try catching a "const char* str"; this works with g++ 2.95.3 and 3.3.1.
Or, preferably, use something like
#include <stdexcept>
[...]
try
{
throw std::out_of_range( "Your message here" );
}
catch ( const std::exception& e )
{
std::cout << "Exception: " << e.what() << std::endl;
}
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
andreas
|
12/10/2003 8:21:38 PM
|
|
Hi,
> int main () {
> try
> {
> throw "out of range";
> }
> catch (char * str)
> {
> cout << "Exception: " << str << endl;
> }
> return 0;
> }
> I can compile it under several versions of Linux ( from gcc 2.96 of
> RedHat 7.3 to gcc 3.3.1 of latest Mandrake) without any error, but the
> executable code aborted when I run it, displaying: Abort (core
> dumped).
This is because "out of range" is a "const char *", not a "char *". Change
that and it'll work fine.
Greetings,
Thomas
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
Thomas
|
12/10/2003 8:22:31 PM
|
|
jkhongyu@yahoo.com (jkhongyu@yahoo.com) wrote:
> try
> {
> throw "out of range";
A string literal is of type const char*.
> }
> catch (char * str)
This has different constness, so won't catch your string. Change this
to
catch ( const char* str )
and it should work.
> I can compile it under several versions of Linux ( from gcc 2.96 of
> RedHat 7.3 to gcc 3.3.1 of latest Mandrake) without any error, but the
> executable code aborted when I run it, displaying: Abort (core
> dumped).
As you would expect -- the exception is never caught, std::terminate
is called which calls abort(). On POSIX-compliant systems, e.g.
Linux, this will raise SIGABRT, resulting in the behaviour you
describe.
In general, it is bad practice to throw string literals about. A much
better idea is to throw some sort of exception class. The Standard
library provides just such a class: std::exception. I suggest you use
this instead.
--
Richard Smith
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
richard
|
12/10/2003 8:31:13 PM
|
|
jkhongyu@yahoo.com wrote:
> Dear all,
>
> I haven't really written any C++ code in recent two years, so lots of
> my old kknowledge and concept just don't work for me anymore. Still
> it's hard for me to understand why the following code is not working
> anymore.
Evidently you upgraded to a more standard-compliant compiler.
However, the first standard was completed over 5 years ago so the
changes aren't all that new.
> #include <iostream>
>
> int main () {
> try
> {
> throw "out of range";
In standard C++, string literals have type const char[N] where N is
the length of the string including the null terminator. When thrown,
this undergoes the standard array-to-pointer conversion resulting in
an exception of type const char *. This is of course not convertible
to type char * without a cast.
> }
> catch (char * str)
> {
> cout << "Exception: " << str << endl;
> }
> return 0;
> }
>
>
> I can compile it under several versions of Linux ( from gcc 2.96 of
> RedHat 7.3 to gcc 3.3.1 of latest Mandrake) without any error, but the
> executable code aborted when I run it, displaying: Abort (core
> dumped).
>
> I saw similar examples from text books somewhere. Also, if I change
> the constant string "Out of range" to a string variable, this code
> works. So is it a string related problem?
In earlier versions of C++ and in C, string literals have type
char *. For compatibility, standard C++ provides a standard
conversion of string literals to type char *, but this is not used
when an exception is thrown.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
Ben
|
12/10/2003 8:36:35 PM
|
|
In article <br7ekh02d2g@enews3.newsguy.com>, Travis Spencer
<travislspencer@hotmail.com> writes
>Hey JK,
>
>There are a couple things you can do:
>
>1. Insert the line 'using namespace std' directly below the #include.
>2. Include iostream.h instead of the current one you are using; this will
>avoid the need for a using declaration.
>3. In main, insert the lines 'using std::cout' and 'using std::end'
>
>To find out why these solutions fix the problem, check out the explination
>of namespaces in you C++ book or post back here w/ more questions.
They don't, however they may hide it.
--
Francis Glassborow ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
Francis
|
12/11/2003 10:40:18 AM
|
|
Hello, Ulrich!
Ulrich Eckhardt schrieb:
> jkhongyu@yahoo.com wrote:
> > try
> > {
> > throw "out of range";
> > }
> > catch (char * str)
> > {
> > cout << "Exception: " << str << endl;
> > }
>
> Try this more condensed version:
>
> char* str = "out of range";
>
> String literals are constants in C++.
Regrettably your expression does compile successfully
on conforming compilers due to backward-compatibility
to C.
Or did you mean the following:
char* str = "out of range";
throw str;
?? - which is OK, of course!
Daniel
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
Daniel
|
12/11/2003 10:40:59 AM
|
|
jkhongyu@yahoo.com (jkhongyu@yahoo.com) wrote:
> try
> {
> throw "out of range";
Here you throw an object of type 'char const*'
> }
> catch (char * str)
> {
> cout << "Exception: " << str << endl;
> }
.... but there is no handler for it! You might want to try
catch (char const* str)
{
std::cout << "Exception: " << str << std::endl;
}
instead. Of course, I would recommend to use the standard exception classes:
try { throw std::out_of_range("out of range..."); }
catch (std::exception const& ex)
{
std::cout << "Exception: " << ex.what() << "\n";
}
At the very least, you should probably derive the classes you are intending
to throw from 'std::exception'.
--
<mailto:dietmar_kuehl@yahoo.com> <http://www.dietmar-kuehl.de/>
Phaidros eaSE - Easy Software Engineering: <http://www.phaidros.com/>
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
dietmar_kuehl
|
12/11/2003 11:38:45 AM
|
|
"Francis Glassborow" <francis@robinton.demon.co.uk> wrote in message news:X$IEJAETPy1$Ewtd@robinton.demon.co.uk...
> The critical change is that the type of a string literal is now an array
> of n const char which decays to char const *. In a restricted number of
> contexts (to preserve legacy code) there is a conversion from string
> literal to char*. The above is not one of those cases. What you have
> thrown is an const char[14] which can be caught as either a const
> char[14] & (possibly const qualified) or as a char const *.
The problem is that it has no clue that you are converting const char[...] to
char* so it can't cheat on the conversion. The throw converts the value to
const char* when it makes the copy implicit in the throw. That as you say
doesn't match the char*.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
Ron
|
12/11/2003 11:41:56 AM
|
|
jkhongyu@yahoo.com (jkhongyu@yahoo.com) wrote in message news:<2c7916f0.0312092255.3da0c7e5@posting.google.com>...
> Dear all,
>
> I haven't really written any C++ code in recent two years, so lots of
> my old kknowledge and concept just don't work for me anymore. Still
> it's hard for me to understand why the following code is not working
> anymore.
>
> #include <iostream>
>
> int main () {
> try
> {
> throw "out of range";
> }
> catch (char * str)
catch (const char *str)
> {
> cout << "Exception: " << str << endl;
> }
> return 0;
> }
>
>
> I can compile it under several versions of Linux ( from gcc 2.96 of
> RedHat 7.3 to gcc 3.3.1 of latest Mandrake) without any error, but the
> executable code aborted when I run it, displaying: Abort (core
> dumped).
>
> I saw similar examples from text books somewhere. Also, if I change
> the constant string "Out of range" to a string variable, this code
> works. So is it a string related problem?
You throw an exception that wasn't caught by any 'catch' stmt
in your program. As a result, the program aborted and created
a core dump.
Your code threw a 'const char *' object, and the 'catch' stmt
references a 'char *' object, which is incompatible. I'm not sure
this code would work if you change "out of range" to
std::string("out of range") - even 'c_str()' of a string would return
a 'const char *', and not 'char *'.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
tmk
|
12/11/2003 11:45:04 AM
|
|
Hello, Travis Spencer!
Travis Spencer schrieb:
> There are a couple things you can do:
[snip]
> 2. Include iostream.h instead of the current one you are using; this will
> avoid the need for a using declaration.
That one is really not a recommended solution, since iostream.h never was a
standard C++ header. Using it supports bad programming style in non-portable
code. Since JK already used <iostream> (even, if its former library obviously
did not support the std namespace), its better to use one of the other two
proposals.
Greetings from Bremen,
Daniel
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
Daniel
|
12/11/2003 12:06:24 PM
|
|
Daniel Kr�gler (nee Spangenberg) <dsp@bdal.de> wrote in message
news:<3FD8228A.5D822F68@bdal.de>...
> Travis Spencer schrieb:
> > There are a couple things you can do:
> [snip]
> > 2. Include iostream.h instead of the current one you are using;
> > this will avoid the need for a using declaration.
> That one is really not a recommended solution, since iostream.h never
> was a standard C++ header.
That's not true. <iostream.h> was the de facto standard until we got a
standard (formally, 1998). Even today, there are compilers in
widespread use which don't correctly support <iostream>.
That, of course, has nothing to do with the original poster's problem in
this case:-). And if you're able to use a more or less conformant
<iostream>, you should prefer it. But a lot of people are still stuck
with g++ pre 3.0 (where <iostream> was a farce) or VC++ 6.0 (where bugs
in the compiler mean that you cannot inherit from streambuf if use
<iostream>).
Formally, of course, since he's using <iostream>, we should also insist
that he needs to include <ostream>. But that's also a nit, and not the
source of his problems.
> Using it supports bad programming style in non-portable code.
For what definition of portable. In my current situation, I find
<iostream.h> more portable -- if I use <iostream>, one of my target
compilers (the most important one, in fact, Sun CC -compat=4) complains
that it cannot find the header file. And of course, if I use
<iostream>, I will also use <ostream> and <istream>, and another
compiler (g++ 2.95.2) will complain that it cannot find either of them.
Finally, if I use <iostream>, <streambuf>, etc., and write something
like:
class MyStreambuf : public std::streambuf
{
} ;
class MyOStream : private virtual MyStreambuf, public std::ostream
{
public:
MyOStream() : std::ostream( this ) {}
} ;
The third compiler (VC++ 6.0) complains about the base class
initialization.
In sum, I have to target three different compilers, and none of them
supports <iostream> correctly. Whereas <iostream.h> works as expected
in all three cases.
None of which has anything to do with his problem, of course. (Although
if he is using g++, he has a real problem -- pre 3.0 didn't support the
standard iostream, and 3.0 on doesn't support classical iostream, so it
is impossible to write serious code which works with both of them.)
> Since JK already used <iostream> (even, if its former library
> obviously did not support the std namespace), its better to use one of
> the other two proposals.
While he's learning, and since he apparently does have access to a
fairly recent compiler (g++ 3.3.1), I agree -- stick with <iostream>
(and don't forget <ostream>, etc.). Once he is faced with the problem
of writing working code in a professional environment, however, he will
have to deal with portability constraints, in one way or another.
--
James Kanze GABI Software mailto:kanze@gabi-soft.fr
Conseils en informatique orient�e objet/ http://www.gabi-soft.fr
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
kanze
|
12/12/2003 7:14:27 PM
|
|
On 2003-12-10, Alf P. Steinbach <alfps@start.no> wrote:
> But as a matter of coding style, _do not_ throw anything else than
> objects of std::exception or derived classes.
>
> Personal preference: throw std::rutime_error or derived for
> situations where 'assert' would be completely inappropriate, throw
> an object of class std::exception or a derived class that is not in
> the std::runtime_error tree for exceptions where 'assert' could
> conceivably be used.
>
> The rationale for that preference is that std::bad_exception does
> not derive from std::logic_error (and std::bad_alloc is a mysterious
> beast), and that it allows code to catch only std::runtime_error
> (and derived), thus passing the more hopeless, fun-spoiling
> exceptions up to a top-level handler.
I've used this *exact* approach quite a bit up to this point in my
young career, but after I started to research the pros and cons of
using exception classes derived from std::exception as opposed to
custom exception hierarchies, what I've turned up so far has suggested
that deriving from std::exception is *not* particularly recommended.
However, the references I speak of are all a few years old, the topic
hasn't apparently made it into the FAQ, and even Andrei defines a
class inheriting from std::exception in MC++D Section 8.5. Anyone
care to offer any up-to-date input or guidance?
Mike
-----= Posted via Newsfeeds.Com, Uncensored Usenet News =-----
http://www.newsfeeds.com - The #1 Newsgroup Service in the World!
-----== Over 100,000 Newsgroups - 19 Different Servers! =-----
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
Mike
|
12/13/2003 11:24:35 PM
|
|
Hello James Kanze,
kanze@gabi-soft.fr schrieb:
> Daniel Kr�gler (nee Spangenberg) <dsp@bdal.de> wrote in message
> [snip]
> > That one is really not a recommended solution, since iostream.h never
> > was a standard C++ header.
>
> That's not true. <iostream.h> was the de facto standard until we got a
> standard (formally, 1998). Even today, there are compilers in
> widespread use which don't correctly support <iostream>.
I cannot resist, James: TMHO even a "de facto standard" is
not a standard. You are right, that there do exist <iostream.h>
implementations,
which are better than their <iostream> correspondents, but **usually** the
deficiencies of those <iostream> implementations are due to rather old
libraries
and they cannot be given as real-world counter-examples.
> That, of course, has nothing to do with the original poster's problem in
> this case:-). And if you're able to use a more or less conformant
> <iostream>, you should prefer it. But a lot of people are still stuck
> with g++ pre 3.0 (where <iostream> was a farce) or VC++ 6.0 (where bugs
> in the compiler mean that you cannot inherit from streambuf if use
> <iostream>).
>
> Formally, of course, since he's using <iostream>, we should also insist
> that he needs to include <ostream>. But that's also a nit, and not the
> source of his problems.
But that nit-comparison does not fit very well, does it? I have heart a lot
of experts saying, that #include <iostream> should make #include <ostream>
unnecessary, but I have never heart one say that one should **generally**
prefer #include <iostream.h> over #include <iostream> (and I am sure, you
also do not give such recommendations).
I think, one should give this recommendation, if you are fixed to library
and/or
compiler, but otherwise... - no.
> In sum, I have to target three different compilers, and none of them
> supports <iostream> correctly. Whereas <iostream.h> works as expected
> in all three cases.
I can add to this, that we got a bunch of problems due to translation units
mixing
headers using both #include <iostream.h> and #include <iostream>, which
where at least partly due to namespace resolution problems of the compilers
you are mentioning (notably VC6). This is even worse, if some of those
headers belong to 3rd party libraries...
I am sure, that you will ensure, that your headers are self-consistent
concerning
this problem, but you cannot demand, that customers using your headers, are
enforced to use the pre-standard iostream.h headers, do you?
I assume, that you speak with a lot of (very valuable!) experience having to
work with quite old libraries and under those circumstances such a
proceeding
seems reasonable, but I would not give such as a general advice.
Greetings from Bremen,
Daniel
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
Daniel
|
12/15/2003 4:00:16 PM
|
|
Daniel Kr�gler (nee Spangenberg) <dsp@bdal.de> wrote in message
news:<3FDDA624.BB2704B9@bdal.de>...
> kanze@gabi-soft.fr schrieb:
> > Daniel Kr�gler (nee Spangenberg) <dsp@bdal.de> wrote in message
> > [snip]
> > > That one is really not a recommended solution, since iostream.h
> > > never was a standard C++ header.
> > That's not true. <iostream.h> was the de facto standard until we
> > got a standard (formally, 1998). Even today, there are compilers in
> > widespread use which don't correctly support <iostream>.
> I cannot resist, James: TMHO even a "de facto standard" is not a
> standard.
That's playing word games. In practice, saying that <iostream.h> was
never a standard C++ header is playing word games as well. In English,
the word "standard" has two meanings -- a "strong" meaning, as in "ISO
standard", and a weaker one, as in "the standard way of doing this
is...". And it can also have a number of intermediate meanings. Long
before there was an ISO standard for C++, we argued about what was
correct in the language, based on the de facto standard at the time.
C++ didn't suddenly appear the day ISO approved the standard. The
language is a lot older than that, and it has a significant history.
(Some would say regretably.) Saying that <iostream.h> is not modern
C++, and that you should prefer <iostream> *IF* compatibility issues
don't prevent it, is fine. It is, in fact, what I said in my posting.
Saying that C++ has never had a staindard <iostream.h> is ignoring
history.
> You are right, that there do exist <iostream.h> implementations, which
> are better than their <iostream> correspondents, but **usually** the
> deficiencies of those <iostream> implementations are due to rather old
> libraries and they cannot be given as real-world counter-examples.
There are compilers for which <iostream> simply doesn't exist. There
are compilers for which <iostream> has nothing to do with the ISO
standard <iostream>. And at least one widespread compiler has problems
inheriting from typedef'ed template classes -- like e.g. std::streambuf
or std::ostream.
These are real-world compilers. They happen to be the three compilers
at use where I currently work.
That doesn't mean that other people, in other circumstances, should just
forget about <iostream> and the standard streams. It doesn't even mean
that we should -- the latest versions of all three compilers DO support
the ISO standard headers more or less correctly (although there are
serious performance problems with one of them), and I am pushing for the
upgrades. They won't occur immediately, however, for several reasons.
The real world situation is complex.
> > That, of course, has nothing to do with the original poster's
> > problem in this case:-). And if you're able to use a more or less
> > conformant <iostream>, you should prefer it. But a lot of people
> > are still stuck with g++ pre 3.0 (where <iostream> was a farce) or
> > VC++ 6.0 (where bugs in the compiler mean that you cannot inherit
> > from streambuf if use <iostream>).
> > Formally, of course, since he's using <iostream>, we should also
> > insist that he needs to include <ostream>. But that's also a nit,
> > and not the source of his problems.
> But that nit-comparison does not fit very well, does it? I have heart
> a lot of experts saying, that #include <iostream> should make #include
> <ostream> unnecessary,
I've never heard an expert say this. I've heard a couple propose
changing the standard so that including <iostream> would make the
inclusion of <ostream> unnecessary. But if they want to change the
standard (and I can understand their arguments, although I'm really
pretty undecided, or rather don't care, on the question), it is because
they recognize that as currently worded, it is not the case.
> but I have never heart one say that one should **generally** prefer
> #include <iostream.h> over #include <iostream> (and I am sure, you
> also do not give such recommendations).
I didn't. I said (I thought quite explicitly) that *unless* portability
problems force the use of <iostream.h>, you should prefer <iostream>.
I'm just reacting to the claim that <iostream.h> was never a standard.
If it had never been a standard, then I wouldn't have to deal with it
with older compilers.
C++ has a long heritage. That has disadvantages, like having to deal
with two versions of the standard streams. It also has advantages: much
of what is good in the standard comes from what we learned from that
heritage. (I'm not just thinking of things adopted from earlier
versions of the langage -- forbidding the binding of a temporary to a
non-const reference, and to a lesser degree, the new scope for variables
declared in a for statement, are a result of what we learned didn't work
well in earlier versions.)
> I think, one should give this recommendation, if you are fixed to
> library and/or compiler, but otherwise... - no.
> > In sum, I have to target three different compilers, and none of them
> > supports <iostream> correctly. Whereas <iostream.h> works as
> > expected in all three cases.
> I can add to this, that we got a bunch of problems due to translation
> units mixing headers using both #include <iostream.h> and #include
> <iostream>, which where at least partly due to namespace resolution
> problems of the compilers you are mentioning (notably VC6). This is
> even worse, if some of those headers belong to 3rd party libraries...
I think that this is probably a really big problem, although I've been
lucky so far. The solution adopted by VC++ was to support both the
classical and the standard streams completely, as two different,
unrelated class hiarchies. Globally, it is probably the best solution;
I've had no end of problems with Sun CC and g++ because <iostream.h>
doesn't work as it used to (and if I had time to fix things, I'd change
to <iostream>). But it does create problems when different libraries
use different stream types.
> I am sure, that you will ensure, that your headers are self-consistent
> concerning this problem, but you cannot demand, that customers using
> your headers, are enforced to use the pre-standard iostream.h headers,
> do you?
If I'm furnishing things like filtering streambuf's, I pretty much have
to. They simply don't work with <iostream> on VC++ 6.0, due to bugs in
the compiler.
> I assume, that you speak with a lot of (very valuable!) experience
> having to work with quite old libraries and under those circumstances
> such a proceeding seems reasonable, but I would not give such as a
> general advice.
I wasn't giving general advice. I was simply reacting to a posting
which more or less negated history. History that, for better or for
worse, a lot of programmers still have to deal with.
--
James Kanze GABI Software mailto:kanze@gabi-soft.fr
Conseils en informatique orient�e objet/ http://www.gabi-soft.fr
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
kanze
|
12/16/2003 3:40:08 PM
|
|
Hello, James Kanze!
kanze@gabi-soft.fr schrieb:
> That's playing word games. In practice, saying that <iostream.h> was
> never a standard C++ header is playing word games as well. In English,
> the word "standard" has two meanings -- a "strong" meaning, as in "ISO
> standard", and a weaker one, as in "the standard way of doing this
> is...". And it can also have a number of intermediate meanings. Long
> before there was an ISO standard for C++, we argued about what was
> correct in the language, based on the de facto standard at the time.
>
> C++ didn't suddenly appear the day ISO approved the standard. The
> language is a lot older than that, and it has a significant history.
> (Some would say regretably.) Saying that <iostream.h> is not modern
> C++, and that you should prefer <iostream> *IF* compatibility issues
> don't prevent it, is fine. It is, in fact, what I said in my posting.
> Saying that C++ has never had a staindard <iostream.h> is ignoring
> history.
I really didn't want to offend you. But I truely belief, that most
contributors
in this group really do give the advice to use <iostream> instead of
<iostream.h> and nearly everyone says that the last one never was a
standard header. There have to be two relaxations of this assertion:
First: Nothing becomes true, just because the majority assumes so or beliefs
so.
Second: I absolutely understand, that you distinguish here the meaning of
standard in a sense of popular usage versus official standard and I don't
want to say that <iostream.h> never was of popular use. But I think, that
this distinguishing point of view was not so clear in your original
statements
you provided to the original post.
> There are compilers for which <iostream> simply doesn't exist. There
> are compilers for which <iostream> has nothing to do with the ISO
> standard <iostream>. And at least one widespread compiler has problems
> inheriting from typedef'ed template classes -- like e.g. std::streambuf
> or std::ostream.
>
> These are real-world compilers. They happen to be the three compilers
> at use where I currently work.
>
> That doesn't mean that other people, in other circumstances, should just
> forget about <iostream> and the standard streams. It doesn't even mean
> that we should -- the latest versions of all three compilers DO support
> the ISO standard headers more or less correctly (although there are
> serious performance problems with one of them), and I am pushing for the
> upgrades. They won't occur immediately, however, for several reasons.
>
> The real world situation is complex.
It is and there exist 'lot of noncorming compilers and libraries, but as a
general recommendation I would always set on conforming behaviour until
proof shows the opposite. If it proofs the opposite, I usually use helper
headers, which hide this lack of conformity - but of course this is a matter
of preference and style.
> > But that nit-comparison does not fit very well, does it? I have heart
> > a lot of experts saying, that #include <iostream> should make #include
> > <ostream> unnecessary,
>
> I've never heard an expert say this. I've heard a couple propose
> changing the standard so that including <iostream> would make the
> inclusion of <ostream> unnecessary.
Bad English of me? I thought I meant the same thing....
Greetings from Bremen,
Daniel
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
Daniel
|
12/16/2003 8:47:55 PM
|
|
Daniel Kr�gler (nee Spangenberg) <dsp@bdal.de> wrote in message
news:<3FDF2FD4.DFCD2EDE@bdal.de>...
Before going any further...
Shortly after posting the message to which you are responding, I reread
part of the thread. I would like to stress that I totally agree with
your basic reaction -- if someone has code using <iostream> which
compiles but doesn't run, changing it to <iostream.h> will generally not
solve the problem, and is in every case bad advice.
Not back to our regularly scheduled nits.
> kanze@gabi-soft.fr schrieb:
> > That's playing word games. In practice, saying that <iostream.h>
> > was never a standard C++ header is playing word games as well. In
> > English, the word "standard" has two meanings -- a "strong" meaning,
> > as in "ISO standard", and a weaker one, as in "the standard way of
> > doing this is...". And it can also have a number of intermediate
> > meanings. Long before there was an ISO standard for C++, we argued
> > about what was correct in the language, based on the de facto
> > standard at the time.
> > C++ didn't suddenly appear the day ISO approved the standard. The
> > language is a lot older than that, and it has a significant history.
> > (Some would say regretably.) Saying that <iostream.h> is not modern
> > C++, and that you should prefer <iostream> *IF* compatibility issues
> > don't prevent it, is fine. It is, in fact, what I said in my
> > posting. Saying that C++ has never had a staindard <iostream.h> is
> > ignoring history.
> I really didn't want to offend you. But I truely belief, that most
> contributors in this group really do give the advice to use <iostream>
> instead of <iostream.h> and nearly everyone says that the last one
> never was a standard header.
I too advice using <iostream> instead of <iostream.h>, whenever
possible. Or at least, using a more or less conforming version os
<iostream> -- I don't count the <iostream> in g++ 2.95. So I agree with
the majority.
As for "never was a standard header": without some adverb to indicate
that only formal standards are being considered, the statement is simply
false. In English, at least, the word "standard" simply has too many
meanings.
> There have to be two relaxations of this assertion: First: Nothing
> becomes true, just because the majority assumes so or beliefs so.
> Second: I absolutely understand, that you distinguish here the meaning
> of standard in a sense of popular usage versus official standard and I
> don't want to say that <iostream.h> never was of popular use. But I
> think, that this distinguishing point of view was not so clear in your
> original statements you provided to the original post.
The original statement was yours: "<iostream.h> never was a standard
header." That's a very categorical statement, and without
qualification, is false. I would have no problem with "was never an ISO
standard", or even "was never a formal standard"; myself, I would tend
to say that it "is no longer the standard header for IO", since from a
pratical point of view, before the ISO standard, <iostream.h> was the
accepted standard.
> > There are compilers for which <iostream> simply doesn't exist.
> > There are compilers for which <iostream> has nothing to do with the
> > ISO standard <iostream>. And at least one widespread compiler has
> > problems inheriting from typedef'ed template classes -- like
> > e.g. std::streambuf or std::ostream.
> > These are real-world compilers. They happen to be the three
> > compilers at use where I currently work.
> > That doesn't mean that other people, in other circumstances, should
> > just forget about <iostream> and the standard streams. It doesn't
> > even mean that we should -- the latest versions of all three
> > compilers DO support the ISO standard headers more or less correctly
> > (although there are serious performance problems with one of them),
> > and I am pushing for the upgrades. They won't occur immediately,
> > however, for several reasons.
> > The real world situation is complex.
> It is and there exist 'lot of noncorming compilers and libraries, but
> as a general recommendation I would always set on conforming behaviour
> until proof shows the opposite.
I suppose you regularly use "export"? :-)
I don't even recommend it. (Why waste time.) With regards to
<iostream>, I recommend using it when possible, but 1) I insist then
that the recommendation adhere to conforming use, with inclusion of
<istream> or <ostream> as well, when necessary, and 2) I recognized that
the "is possible" will not always be true. Judging from the companies I
know (which is, admittedly, a very small sample), the two most widely
used compilers today are VC++ 6.0 and g++ 2.95.x -- and there are
problems with <iostream> with both of them. (The implementation of
<iostream.h> in g++ 2.95 isn't conform to the pre-ISO de facto standard
either, but the difference is easily worked around.)
> If it proofs the opposite, I usually use helper headers, which hide
> this lack of conformity - but of course this is a matter of preference
> and style.
When portability is an issue, I always use helper headers. You might
take a look at my solution at my site. But globally, which is better: a
header with a "#define pubsync sync", or using sync as a public
function?
> > > But that nit-comparison does not fit very well, does it? I have
> > > heart a lot of experts saying, that #include <iostream> should
> > > make #include <ostream> unnecessary,
> > I've never heard an expert say this. I've heard a couple propose
> > changing the standard so that including <iostream> would make the
> > inclusion of <ostream> unnecessary.
> Bad English of me? I thought I meant the same thing....
Maybe. I interpreted it as the opposite, but I could be
misunderstanding as well.
--
James Kanze GABI Software mailto:kanze@gabi-soft.fr
Conseils en informatique orient�e objet/ http://www.gabi-soft.fr
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
kanze
|
12/17/2003 7:09:45 PM
|
|
|
22 Replies
84 Views
(page loaded in 0.26 seconds)
|