Topic: Implicit conversion of g++
Author: AllanW <allan_w@my-deja.com>
Date: 2000/04/22 Raw View
jeffturneresq@my-deja.com wrote:
> meixner@rbg.informatik.tu-darmstadt.de (Matthias Meixner) wrote:
> > class string {
> > char *s;
> > public:
> > string(const char *c) {s=c;}
> > operator char *() { return s; }
> > operator const char *() const { return s; }
> > };
>
> I suppose this was an academic exercise and not an attempt to
> reinvent the wheel for other reasons. I suspect the third
> operator definition should be:
>
> operator const char *() const
> { return static_cast< const char * > s; }
There's no reason for this change. One should avoid using
casts when they are not needed. The expression in the
return statement is subject to implicit conversions.
Variable s is of type "char*" which is implicitly converted
to "const char*" without requiring any sort of cast.
--
Allan_W@my-deja.com is a "Spam Magnet," never read.
Please reply in newsgroups only, sorry.
Sent via Deja.com http://www.deja.com/
Before you buy.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: jeffturneresq@my-deja.com
Date: 2000/04/15 Raw View
meixner@rbg.informatik.tu-darmstadt.de (Matthias Meixner) wrote:
>g++ performs some strange implicit conversions, and it
> is my question, if my understanding of the C++ standard is
> wrong or if g++ makes an error.
>
> Compiling the following small test using g++ gave me warnings:
------------------------------------------------------------
> class string {
> char *s;
> public:
> string(const char *c) {s=c;}
> operator char *() { return s; }
> operator const char *() const { return s; }
> };
I suppose this was an academic exercise and not an attempt to
reinvent the wheel for other reasons. I suspect the third
operator definition should be:
operator const char *() const {return static_cast< const char * > s;}
> void foo(const char *s)
> {
> }
> main()
> {
> string a("test");
> foo(a);
> return 0;
> }
Sent via Deja.com http://www.deja.com/
Before you buy.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: kanze@gabi-soft.de
Date: 2000/03/26 Raw View
Martin von Loewis <loewis@informatik.hu-berlin.de> writes:
|> meixner@rbg.informatik.tu-darmstadt.de (Matthias Meixner) writes:
|> > So who is going to try to modify the standard ... :-)
|> Well, there is a procedure for that. Write-up a defect report, send
|> it to this group with a subject starting with "Defect Report:", and
|> wait :-)
|> Actually, after that, you could also join your national
|> standardisation institute, and let them delegate you to the ISO. In
|> case DIN won't allow your participation, I think ANSI has more open
|> regulations for allowing even non-US people into committees.
DIN will allow him to participate -- I'm sure that if he contacts
Nicolai Josuttis, he will be welcomed.
ANSI will also allow him to participate. At a price of (the last time I
checked) around $1000 a year. Given that he's posting from a
University, that might be a bit steep.
--
James Kanze mailto:kanze@gabi-soft.de
Conseils en informatique orient e objet/
Beratung in objektorientierter Datenverarbeitung
Ziegelh ttenweg 17a, 60598 Frankfurt, Germany Tel. +49(069)63198627
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: meixner@rbg.informatik.tu-darmstadt.de (Matthias Meixner)
Date: 2000/03/25 Raw View
Martin von Loewis (loewis@informatik.hu-berlin.de) wrote:
: meixner@rbg.informatik.tu-darmstadt.de (Matthias Meixner) writes:
:
: There is another disadvantage in change: You break not only existing
: C++ code, but you also invalidate existing implementations, as well as
: teaching material, and ask people to re-learn some of the language. So
Yes, you are right, I forgot this point.
: it would be interesting to find out whether/if today's compiler
: implement the rule as written, or whether they implement them
: incorrectly (perhaps as an option :-).
:
: Ultimately, it would be best if you'd had an experimental C++ compiler
: where you could change the rules, and then have users report their
: experience with the modified compiler. There are at least two
I have created a patch for egcs-20000320, which can be found at:
http://www.student.informatik.tu-darmstadt.de/~meixner/egcspatch
And an example, which demonstrates the differences:
http://www.student.informatik.tu-darmstadt.de/~meixner/example.cxx
So maybe there is some more feedback now ... :-)
- Matthias Meixner
--
Matthias Meixner meixner@rbg.informatik.tu-darmstadt.de
Technische Universit t Darmstadt
Rechnerbetriebsgruppe Telefon (+49) 6151 16 6670
Wilhelminenstra e 7, D-64283 Darmstadt, Germany Fax (+49) 6151 16 4701
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Francis Glassborow <francis@robinton.demon.co.uk>
Date: 2000/03/17 Raw View
In article <8anfcf$bn9$1@sun27.hrz.tu-darmstadt.de>, Matthias Meixner
<meixner@rbg.informatik.tu-darmstadt.de> writes
>: well-specified for the case where conversions return similar types as
>: well, although it apparently does not reflect the intuition of all C++
>: users.
>
>If all C++ users think this way, why not change the standard?
You have a natural language problem, negatives play havoc with
understanding.
The above phrase is better read as if it had been:
'Although apparently this is not intuitive to some C++ users.'
Francis Glassborow Journal Editor, Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: meixner@rbg.informatik.tu-darmstadt.de (Matthias Meixner)
Date: 2000/03/17 Raw View
Francis Glassborow (francis@robinton.demon.co.uk) wrote:
: In article <8anfcf$bn9$1@sun27.hrz.tu-darmstadt.de>, Matthias Meixner
: <meixner@rbg.informatik.tu-darmstadt.de> writes
: >: well-specified for the case where conversions return similar types as
: >: well, although it apparently does not reflect the intuition of all C++
: >: users.
: >
: >If all C++ users think this way, why not change the standard?
:
: You have a natural language problem, negatives play havoc with
: understanding.
:
: The above phrase is better read as if it had been:
:
: 'Although apparently this is not intuitive to some C++ users.'
OK, but the question remains: Would it be a good thing to change the
standard?
Changing the standard would have some advantages:
- If you want to have different conversion functions, that differ only
in constness, you currently have to write three versions to cover all cases.
E.G. for the string example you need to write "operator char *()",
"operator const char *()" and "operator const char *() const" or
"operator const char *()" would be 'hidden' by "operator char *()" for
non const objects. Modyfing the standard would remove the need for writing
this redundant code.
- It would better reflect intuition. OK, you can argument about that, but
it took quite some posts to work out the correct interpretation of the
standard, which is an indication, that the standard is counter intuitive
in this area.
Of course it would have some disadvantages:
- Semantics of code changes. The question here is: does it affect existing
code? I guess that most existing code that could be affected uses
explicit casts in this case anyway.
Maybe someone else wants to comment on that.
Matthias Meixner
--
Matthias Meixner meixner@rbg.informatik.tu-darmstadt.de
Technische Universit t Darmstadt
Rechnerbetriebsgruppe Telefon (+49) 6151 16 6670
Wilhelminenstra e 7, D-64283 Darmstadt, Germany Fax (+49) 6151 16 4701
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Martin von Loewis <loewis@informatik.hu-berlin.de>
Date: 2000/03/22 Raw View
meixner@rbg.informatik.tu-darmstadt.de (Matthias Meixner) writes:
> So who is going to try to modify the standard ... :-)
Well, there is a procedure for that. Write-up a defect report, send it
to this group with a subject starting with "Defect Report:", and wait
:-)
Actually, after that, you could also join your national
standardisation institute, and let them delegate you to the ISO. In
case DIN won't allow your participation, I think ANSI has more open
regulations for allowing even non-US people into committees. So then,
as a delegate, you could fight in the committee to ask them not to
declare your issue as NAD (not a defect :-)
Seriously, the standard shouldn't change unless it is clearly
broken. If enough users feel that way, and have their committee
representatives express this view, and if there is a fix that won't
break other, more important things, than the standard will change. It
just takes some efforts; posting to a newsgroup is but a starting point.
Regards,
Martin
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: meixner@rbg.informatik.tu-darmstadt.de (Matthias Meixner)
Date: 2000/03/22 Raw View
Martin von Loewis (loewis@informatik.hu-berlin.de) wrote:
[...]
: Seriously, the standard shouldn't change unless it is clearly
: broken. If enough users feel that way, and have their committee
: representatives express this view, and if there is a fix that won't
: break other, more important things, than the standard will change. It
: just takes some efforts; posting to a newsgroup is but a starting point.
I hoped to see some comments, if a change in the standard would break
any code (See also my last post). But till now there was no response
voting for or against a change.
- Matthias Meixner
--
Matthias Meixner meixner@rbg.informatik.tu-darmstadt.de
Technische Universit t Darmstadt
Rechnerbetriebsgruppe Telefon (+49) 6151 16 6670
Wilhelminenstra e 7, D-64283 Darmstadt, Germany Fax (+49) 6151 16 4701
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Martin von Loewis <loewis@informatik.hu-berlin.de>
Date: 2000/03/22 Raw View
meixner@rbg.informatik.tu-darmstadt.de (Matthias Meixner) writes:
> Of course it would have some disadvantages:
>
> - Semantics of code changes. The question here is: does it affect existing
> code? I guess that most existing code that could be affected uses
> explicit casts in this case anyway.
There is another disadvantage in change: You break not only existing
C++ code, but you also invalidate existing implementations, as well as
teaching material, and ask people to re-learn some of the language. So
it would be interesting to find out whether/if today's compiler
implement the rule as written, or whether they implement them
incorrectly (perhaps as an option :-).
Ultimately, it would be best if you'd had an experimental C++ compiler
where you could change the rules, and then have users report their
experience with the modified compiler. There are at least two
compilers available to the public in source form, so having a
prototype implementation is possible. To me, a danger with bug
"fixing" is that it may well introduce new bugs.
As to your concrete proposal: I could not find a problem with it
off-hand, after scanning the standard library and the CORBA C++
mapping for potential problems.
Regards,
Martin
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: smeyers@aristeia.com (Scott Meyers)
Date: 2000/03/23 Raw View
On Wed, 22 Mar 2000 21:27:42 CST, Martin von Loewis wrote:
> experience with the modified compiler. There are at least two
> compilers available to the public in source form, so having a
g++ and?
Scott
--
"Effective STL" Seminar June 7-9 Portland, Oregon
Details at http://www.trekservices.com/estl/
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: meixner@rbg.informatik.tu-darmstadt.de (Matthias Meixner)
Date: 2000/03/14 Raw View
Martin von Loewis (loewis@informatik.hu-berlin.de) wrote:
: kanze@gabi-soft.de writes:
:
: > |> g++ performs some strange implizit conversions, and it
: > |> is my question, if my understanding of the C++ standard is
: > |> wrong or if g++ makes an error.
: >
: > Does anyone really have an understanding of the C++ standard in this
: > area?
:
: Having had to explain this particular message in g++ a hundred times
: so far, I'd claim that I now understand the rules ... until I'm proven
: wrong.
:
: > Apparently, the standard considers a conversion of the object type on
: > which you call the member function a worse conversion than the others,
: > supposing all other things equal.
:
: No, it just prescribes a decision tree, where consideration of the
: arguments comes before considering the standard conversion of
: result. It works like this
:
I think you mean section 13.3.3 (Best Viable Function)
: A is better than B
:
: - if the argument conversions for A are better than those of B, or, if
: not that
If this was true, no const conversion operator could be called on a non
const object if there was a single non const conversion operator.
e.g.:
class foo {
public:
operator double *() { return 0; }
operator const char *() const { return 0; }
};
main()
{
foo f;
double *a=f;
const char *b=f; // should give an error, if your rule was true
}
The argument conversion for operator double*() is better than for operator const char *(),
therefore the assignment to b should fail, since there is no conversion from
double * to const char *. Obviously this is not the case.
: - if B is a template and A is not, or, if not that
: - if both are templates, and A is more special than B, or, if not that
: - if, in a user-defined conversion, the conversion from the result of
: A is better than the one of B.
You are right, there is an example about conversion operators right below this rule,
but after having found the example above, I think, this set of rules is not used
in any compiler for selecting conversion functions.
Probably the last rule should be removed from that set of functions and there should
be an extra section about selection of user defined conversion functions in the
standard.
:
: It's actually quite easy to memorize this rule once you know it's
: there :-)
But if you dig a little deeper you come to the conclusion that no compiler
behaves as the standard describes it should.
:
: > A different question might be whether there is a bug in the standard
: > here.
:
: I think coming up with a well-defined and consistent (i.e. not
: self-contradictory) procedure for overload resolution for C++ is
: tricky enough, and I understand the the final standard was a
: *simplification* over the ARM in precisely that area (i.e. in the ARM,
: things would be resolved arbitrarily which are now ambiguous).
:
: So unless there is an alternative complete proposal that does not have
: the 'confusing' border cases, I'd rather stick with what we have.
I vote for a standard, that is more clear in this case.
- Matthias Meixner
--
Matthias Meixner meixner@rbg.informatik.tu-darmstadt.de
Technische Universit t Darmstadt
Rechnerbetriebsgruppe Telefon (+49) 6151 16 6670
Wilhelminenstra e 7, D-64283 Darmstadt, Germany Fax (+49) 6151 16 4701
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Martin von Loewis <loewis@informatik.hu-berlin.de>
Date: 2000/03/15 Raw View
meixner@rbg.informatik.tu-darmstadt.de (Matthias Meixner) writes:
> I think you mean section 13.3.3 (Best Viable Function)
Indeed, yes.
[example deleted]
> The argument conversion for operator double*() is better than for
> operator const char *(), therefore the assignment to b should fail,
> since there is no conversion from double * to const char
> *. Obviously this is not the case.
Obviously, the conversion from f to double* is not a candidate
(13.3.1.5); it does not return 'const char*', and 'double*' cannot be
converted to 'const char*' in a standard conversion
sequence. Therefore, it is not a viable candidate, let alone the best
viable candidate. So the your example behaves as you and I would
expect, even under 'my' interpretation.
> You are right, there is an example about conversion operators right
> below this rule, but after having found the example above, I think,
> this set of rules is not used in any compiler for selecting
> conversion functions.
Sure it is. g++ works exactly that way. Of course, it had eliminated
the 'wrong' conversion operator in the lookup stage already.
> Probably the last rule should be removed from that set of functions
> and there should be an extra section about selection of user defined
> conversion functions in the standard.
No, the standard works fine for the 'normal' case. It is
well-specified for the case where conversions return similar types as
well, although it apparently does not reflect the intuition of all C++
users.
> But if you dig a little deeper you come to the conclusion that no
> compiler behaves as the standard describes it should.
Maybe you should analyse your examples a little better before betting
all your rhetorics onto a simple example :-)
Regards,
Martin
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: meixner@rbg.informatik.tu-darmstadt.de (Matthias Meixner)
Date: 2000/03/16 Raw View
Martin von Loewis (loewis@informatik.hu-berlin.de) wrote:
: meixner@rbg.informatik.tu-darmstadt.de (Matthias Meixner) writes:
:
: > I think you mean section 13.3.3 (Best Viable Function)
:
: Indeed, yes.
:
: [example deleted]
:
: > The argument conversion for operator double*() is better than for
: > operator const char *(), therefore the assignment to b should fail,
: > since there is no conversion from double * to const char
: > *. Obviously this is not the case.
:
: Obviously, the conversion from f to double* is not a candidate
: (13.3.1.5); it does not return 'const char*', and 'double*' cannot be
: converted to 'const char*' in a standard conversion
: sequence. Therefore, it is not a viable candidate, let alone the best
: viable candidate. So the your example behaves as you and I would
: expect, even under 'my' interpretation.
You are right, I overlooked 13.3.1.5.
[...]
: > Probably the last rule should be removed from that set of functions
: > and there should be an extra section about selection of user defined
: > conversion functions in the standard.
:
: No, the standard works fine for the 'normal' case. It is
: well-specified for the case where conversions return similar types as
: well, although it apparently does not reflect the intuition of all C++
: users.
If all C++ users think this way, why not change the standard?
Making the fourth rule of 13.3.3 to the first rule would adapt the behaviour
of C++ to the intuition of most C++ users and probably most sourcecode
out there would not be affected by this change. So I think that overall it
whould not be a bad thing.
So who is going to try to modify the standard ... :-)
: > But if you dig a little deeper you come to the conclusion that no
: > compiler behaves as the standard describes it should.
:
: Maybe you should analyse your examples a little better before betting
: all your rhetorics onto a simple example :-)
However it worked, now I have got the correct answer ... :-)
Regards,
Matthias Meixner
--
Matthias Meixner meixner@rbg.informatik.tu-darmstadt.de
Technische Universit t Darmstadt
Rechnerbetriebsgruppe Telefon (+49) 6151 16 6670
Wilhelminenstra e 7, D-64283 Darmstadt, Germany Fax (+49) 6151 16 4701
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: meixner@rbg.informatik.tu-darmstadt.de (Matthias Meixner)
Date: 2000/03/02 Raw View
g++ performs some strange implizit conversions, and it
is my question, if my understanding of the C++ standard is
wrong or if g++ makes an error.
Compiling the following small test using g++ gave me warnings:
------------------------------------------------------------
class string {
char *s;
public:
string(const char *c) {s=c;}
operator char *() { return s; }
operator const char *() const { return s; }
};
void foo(const char *s)
{
}
main()
{
string a("test");
foo(a);
return 0;
}
t2.cxx: In method `string::string(const char *)':
t2.cxx:8: assignment to `char *' from `const char *' discards qualifiers
t2.cxx: In function `int main()':
t2.cxx:22: warning: choosing `string::operator char *()' over
`string::operator const char *() const'
t2.cxx:22: warning: for conversion from `string' to `const char *'
t2.cxx:22: warning: because conversion sequence for the argument is better
-----------------------------------------------------------------
I think since operator const char *() is an exact match, this
conversion operator should be used instead of operator char *().
Conversion sequences:
1) string->const char *
2) string->char *->const char *
I thought 1) should be used whereas g++ selects 2).
Therefore I EMailed to gcc-bugs and got the following two answers:
> (1) is wrong. It should be:
>
> 1) string->string const->const char *
>
And
> Thanks for your bug report. Your analysis is incorrect, gcc selects
>the right conversion sequence. The candidate sequences are
>
>
>1) string -> string const & -> char const *
>2) string -> string & -> char* -> char const *
>
>because the implicit object argument must be converted to the
>appropriate reference. According to 13.3.3/1, the standard conversion
>sequences from the result of a user-defined conversion to the target
>type are only considered if no conversion sequence for the arguments
>is better, and. In conversion sequence 2), conversion for the
>arguments is better, since it does not involve a qualification
>conversion.
>
>The gcc authors find that this is a confusing rule, hence the warning.
Therefore I have rechecked (the final draft of) the C++ standard:
Section 9.3.2 paragraph 2 says: "In a const member function, the object for
which the function is called is accessed through a const access path; therefore,
a const member function shall not modify the onject and its non-static data members."
As I understand it, this does not imply a conversion string -> const string,
since "const access path" does not mean, that the object has to be converted
to a const object first.
Section 5.2.2 does not give any additional information regarding this case.
So if the conversion string -> const string is not needed, the best conversion
path would be: string -> const char *.
So the question is: which interpretation of the standard is right.
- Matthias Meixner
--
Matthias Meixner meixner@rbg.informatik.tu-darmstadt.de
Technische Universit t Darmstadt
Rechnerbetriebsgruppe Telefon (+49) 6151 16 6670
Wilhelminenstra e 7, D-64283 Darmstadt, Germany Fax (+49) 6151 16 4701
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: kanze@gabi-soft.de
Date: 2000/03/03 Raw View
meixner@rbg.informatik.tu-darmstadt.de (Matthias Meixner) writes:
|> g++ performs some strange implizit conversions, and it
|> is my question, if my understanding of the C++ standard is
|> wrong or if g++ makes an error.
Does anyone really have an understanding of the C++ standard in this
area?
|> Compiling the following small test using g++ gave me warnings:
|> ------------------------------------------------------------
|>
|> class string {
|> char *s;
|> public:
|> string(const char *c) {s=c;}
|> operator char *() { return s; }
|> operator const char *() const { return s; }
|> };
|>
|> void foo(const char *s)
|> {
|> }
|>
|> main()
|> {
|> string a("test");
|> foo(a);
|> return 0;
|> }
|>
|> t2.cxx: In method `string::string(const char *)':
|> t2.cxx:8: assignment to `char *' from `const char *' discards qualifiers
|> t2.cxx: In function `int main()':
|> t2.cxx:22: warning: choosing `string::operator char *()' over
|> `string::operator const char *() const'
|> t2.cxx:22: warning: for conversion from `string' to `const char *'
|> t2.cxx:22: warning: because conversion sequence for the argument is better
|>
|> -----------------------------------------------------------------
|> I think since operator const char *() is an exact match, this
|> conversion operator should be used instead of operator char *().
This is what any reasonable person would think. (Well, it's what I
thought, anyway, until I was corrected:-).) In fact, there are *two*
conversions which are being considered:
- convert a from string to const string, in order to call operator
const char* and have an exact match afterwards, and
- convert the converted char* to a const char*, in order to call foo.
Apparently, the standard considers a conversion of the object type on
which you call the member function a worse conversion than the others,
supposing all other things equal.
|> Conversion sequences:
|> 1) string->const char *
|> 2) string->char *->const char *
|> I thought 1) should be used whereas g++ selects 2).
|> Therefore I EMailed to gcc-bugs and got the following two answers:
|> > (1) is wrong. It should be:
|> > 1) string->string const->const char *
|> And
|> > Thanks for your bug report. Your analysis is incorrect, gcc selects
|> >the right conversion sequence. The candidate sequences are
|> >1) string -> string const & -> char const *
|> >2) string -> string & -> char* -> char const *
|> >because the implicit object argument must be converted to the
|> >appropriate reference. According to 13.3.3/1, the standard conversion
|> >sequences from the result of a user-defined conversion to the target
|> >type are only considered if no conversion sequence for the arguments
|> >is better, and. In conversion sequence 2), conversion for the
|> >arguments is better, since it does not involve a qualification
|> >conversion.
|> >The gcc authors find that this is a confusing rule, hence the warning.
They're not the only ones. I like their attitude.
|> Therefore I have rechecked (the final draft of) the C++ standard:
|> Section 9.3.2 paragraph 2 says: "In a const member function, the
|> object for which the function is called is accessed through a const
|> access path; therefore, a const member function shall not modify the
|> onject and its non-static data members."
|> As I understand it, this does not imply a conversion string -> const
|> string, since "const access path" does not mean, that the object has
|> to be converted to a const object first.
|> Section 5.2.2 does not give any additional information regarding
|> this case.
Start by reading, or trying to read, 13.3. Basically, overload
resolution depends on context: this is 13.3.1.5. If I remember
correctly, the basic logic is that overload resolution doesn't depend on
the return type, or what you do with the object. So you have two
possible functions, operator char*() and operator char const*() const.
And one "parameter", the implicit this, which has type string*. The
call to operator char*() is an exact match, and the call to operator
char const*() requires a cv conversion.
|> So if the conversion string -> const string is not needed, the best
|> conversion path would be: string -> const char *.
|> So the question is: which interpretation of the standard is right.
G++'s.
A different question might be whether there is a bug in the standard
here.
--
James Kanze mailto:kanze@gabi-soft.de
Conseils en informatique orient e objet/
Beratung in objektorientierter Datenverarbeitung
Ziegelh ttenweg 17a, 60598 Frankfurt, Germany Tel. +49(069)63198627
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Hyman Rosen <hymie@prolifics.com>
Date: 2000/03/03 Raw View
meixner@rbg.informatik.tu-darmstadt.de (Matthias Meixner) writes:
> class string {
> char *s;
> public:
> string(const char *c) {s=c;}
> operator char *() { return s; }
> operator const char *() const { return s; }
> };
>
> void foo(const char *s) { }
>
> main()
> {
> string a("test");
> foo(a);
> return 0;
> }
> t2.cxx: In method `string::string(const char *)':
> t2.cxx:8: assignment to `char *' from `const char *' discards qualifiers
I trust this is obvious? Member s is char *, and you are assigning a
const char * to it.
> t2.cxx: In function `int main()':
> t2.cxx:22: warning: choosing `string::operator char *()' over
> `string::operator const char *() const'
> t2.cxx:22: warning: for conversion from `string' to `const char *'
> t2.cxx:22: warning: because conversion sequence for the argument is better
Think of the two member functions as these equivalent non-members -
char *to_char_ptr(string *this);
const char *to_char_ptr(const string *this);
The conversion requires the call to_char_ptr(&a), and the best match is
the one whose parameter is string *, not const string *.
You can write
operator char *() { return s; }
operator const char *() { return s; }
operator const char *() const { return s; }
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Jens Kilian <Jens_Kilian@agilent.com>
Date: 2000/03/03 Raw View
Hyman Rosen <hymie@prolifics.com> writes:
> You can write
>
> operator char *() { return s; }
> operator const char *() { return s; }
> operator const char *() const { return s; }
No, he can't. No overloading on return type!
--
mailto:jjk@acm.org phone:+49-7031-464-7698 (HP TELNET 778-7698)
http://www.bawue.de/~jjk/ fax:+49-7031-464-7351
PGP: 06 04 1C 35 7B DC 1F 26 As the air to a bird, or the sea to a fish,
0x555DA8B5 BB A2 F0 66 77 75 E1 08 so is contempt to the contemptible. [Blake]
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Martin von Loewis <loewis@informatik.hu-berlin.de>
Date: 2000/03/04 Raw View
kanze@gabi-soft.de writes:
> |> g++ performs some strange implizit conversions, and it
> |> is my question, if my understanding of the C++ standard is
> |> wrong or if g++ makes an error.
>
> Does anyone really have an understanding of the C++ standard in this
> area?
Having had to explain this particular message in g++ a hundred times
so far, I'd claim that I now understand the rules ... until I'm proven
wrong.
> Apparently, the standard considers a conversion of the object type on
> which you call the member function a worse conversion than the others,
> supposing all other things equal.
No, it just prescribes a decision tree, where consideration of the
arguments comes before considering the standard conversion of
result. It works like this
A is better than B
- if the argument conversions for A are better than those of B, or, if
not that
- if B is a template and A is not, or, if not that
- if both are templates, and A is more special than B, or, if not that
- if, in a user-defined conversion, the conversion from the result of
A is better than the one of B.
It's actually quite easy to memorize this rule once you know it's
there :-)
> A different question might be whether there is a bug in the standard
> here.
I think coming up with a well-defined and consistent (i.e. not
self-contradictory) procedure for overload resolution for C++ is
tricky enough, and I understand the the final standard was a
*simplification* over the ARM in precisely that area (i.e. in the ARM,
things would be resolved arbitrarily which are now ambiguous).
So unless there is an alternative complete proposal that does not have
the 'confusing' border cases, I'd rather stick with what we have.
Regards,
Martin
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Pierre Baillargeon <pb@artquest.net>
Date: 2000/03/04 Raw View
kanze@gabi-soft.de wrote:
>
> meixner@rbg.informatik.tu-darmstadt.de (Matthias Meixner) writes:
>
> This is what any reasonable person would think. (Well, it's what I
> thought, anyway, until I was corrected:-).) In fact, there are *two*
> conversions which are being considered:
>
> - convert a from string to const string, in order to call operator
> const char* and have an exact match afterwards, and
>
> - convert the converted char* to a const char*, in order to call foo.
>
> Apparently, the standard considers a conversion of the object type on
> which you call the member function a worse conversion than the others,
> supposing all other things equal.
I think the problem is caused by having a single feature used for two
conflicting goals. Currently, the standard only support one goal. When
two versions of a function are provided (const and non-const), the goal
may be either:
1. That the function can be used on both types of objects. Calling on
const usually results in having more constraints on the result.
2. That the const version, knowing the object won't be modified, can be
optimized.
I'll give an example of both use.
The first example, is the string class, of the original poster, which
returns a const char * or a char *, for const and non-const string
objects.
The second example is a map-type container. If the container is
non-const, then it must allow for the possibility that the access may
also be intended as being an insertion. The const version can be
optimized by assuming that the access *must* be for an existing object.
I have written such a class (with asserts everywhere...).
So how could the compiler know which kind of goal one is after? Since
both are implemented using the same syntax (const and non-const versions
of a function) the compiler has no idea.
Currently the standard supports goal 1. The only way to achieve the goal
2 is by using explicit const references before calling the function, in
order the get the optimized version:
struct Opt
{
char * foo (); // slow.
const char * foo () const; // fast.
};
Opt a;
const char * pc1 = a.foo (); // slow.
const Opt & ra = a;
const char * pc2 = ra.foo (); // fast.
Annoying, but is there another trick to get the "desired" behavior?
Maybe a 5-pages long obscure template which can theorically be optimized
away, proving that, no, the standard does not need to address this issue
after all?
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: meixner@rbg.informatik.tu-darmstadt.de (Matthias Meixner)
Date: 2000/03/04 Raw View
kanze@gabi-soft.de wrote:
: meixner@rbg.informatik.tu-darmstadt.de (Matthias Meixner) writes:
:
[...]
:
: This is what any reasonable person would think. (Well, it's what I
: thought, anyway, until I was corrected:-).) In fact, there are *two*
: conversions which are being considered:
:
: - convert a from string to const string, in order to call operator
: const char* and have an exact match afterwards, and
:
: - convert the converted char* to a const char*, in order to call foo.
:
: Apparently, the standard considers a conversion of the object type on
: which you call the member function a worse conversion than the others,
: supposing all other things equal.
Hmm, trying the following with g++:
-------------------------------------------
#include <stdio.h>
class A { public: int x;};
void f(int &a, const A &b) { puts("a"); }
void f(const int &a, A &b) { puts("b"); }
main()
{
int a;
A b;
f(a,b);
}
-------------------------------------------
If the conversion of object types was considered worse, then
in this case the first version of f() should be called, but at
least g++ reports:
t3.cxx: In function `int main()':
t3.cxx:14: call of overloaded `f (int &, A &)' is ambiguous
t3.cxx:6: candidates are: void f(int &, const A &)
t3.cxx:7: void f(const int &, A &)
Back to the string example:
So even when assuming, that string needs to be converted to const string before
converting it to const char *, the question remains, why is
string -> char * -> const char * a better conversion sequence than
string -> const string -> const char *
Checking the rules in 13.3.3.2:
1) both are user defined conversion sequences
2) none of which is a subsequence of the other
3) the rank is the same
4) both return the same cv-qualified type (const char *)
5) the resulting type is not a reference
6) they do not contain the same user-defined conversion sequence
According to the rules in 13.3.3.2 they should be indistinguishable conversion
sequences, which would mean, that the call foo(a) would be ambiguous.
So the question still remains open, why the conversion sequence
string -> char * -> const char * should be the best sequence.
[...]
: |> >The gcc authors find that this is a confusing rule, hence the warning.
:
: They're not the only ones. I like their attitude.
[...]
: Start by reading, or trying to read, 13.3. Basically, overload
: resolution depends on context: this is 13.3.1.5. If I remember
: correctly, the basic logic is that overload resolution doesn't depend on
: the return type, or what you do with the object. So you have two
: possible functions, operator char*() and operator char const*() const.
: And one "parameter", the implicit this, which has type string*. The
: call to operator char*() is an exact match, and the call to operator
: char const*() requires a cv conversion.
Standard overload resolution does not work for conversion functions, since
if it would, you could not have more than one conversion function, since
all take the same set of parameters and only differ in the return type,
but the return type is not considered in overload resolution.
(13.1 paragraph 2: "Function declarations that differ only in the return type
cannot be overloaded")
According to 13.3.1.5 both conversion functions (operator char *() and
operator const char *()) should be considered.
According to 13.3.3 paragraph 1, 4th rule: operator const char *() would
be the better conversion sequence (identity).
So can anyone tell me, why string->char *->const char * should be the best
conversion sequence?
- Matthias Meixner
--
Matthias Meixner meixner@rbg.informatik.tu-darmstadt.de
Technische Universit t Darmstadt
Rechnerbetriebsgruppe Telefon (+49) 6151 16 6670
Wilhelminenstra e 7, D-64283 Darmstadt, Germany Fax (+49) 6151 16 4701
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Alex T <tamm_at_cs_dot_helsinki_dot_fi@no.spam>
Date: 2000/03/04 Raw View
Jens Kilian <Jens_Kilian@agilent.com> wrote:
:>Hyman Rosen <hymie@prolifics.com> writes:
:>> You can write
:>> operator char *() { return s; }
:>> operator const char *() { return s; }
:>> operator const char *() const { return s; }
:>No, he can't. No overloading on return type!
Yes, he can. The return type isn't overloaded here. The const qualifier
in the latter operator refers to the object from which the operator is
called.
The following works (with g++ -Wall -ansi -pedantic, g++ v. 2.95.2):
class S{
//...
operator char *() {return s;} // 1
operator char *() const{ return s;} // 2, called from const S
operator const char *(){ return s;} // 3
operator const char *() const{ return s;} // 4, called from const S
};
void func1(char *);
void func2(const char *);
//...
S s;
const S cs;
func1(s); // calls 1
func2(s); // calls 3
func1(cs); // calls 2
func2(cs); // calls 4
Alex
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: "Gene Bushuyev" <gbush@my-deja.com>
Date: 2000/03/04 Raw View
"Jens Kilian" <Jens_Kilian@agilent.com> wrote in message
news:sfn1ogqw0u.fsf@bstde026.bbn.hp.com...
> Hyman Rosen <hymie@prolifics.com> writes:
> > You can write
> >
> > operator char *() { return s; }
> > operator const char *() { return s; }
> > operator const char *() const { return s; }
>
> No, he can't. No overloading on return type!
>
Yes, he can :-)
That may seem like inconsistency in C++. It doesn't allow overloading
functions on return type (past discussion indicated that it could be done
but most people feel uncomfortable with such overloading) while allowing
conversion operators, that are logically can be seen as overloading on
return type.
--
Gene Bushuyev
visit us at http://www.systemc.org
Entia non sunt multiplicanda praeter necessitatem
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: "Gene Bushuyev" <gbush@my-deja.com>
Date: 2000/03/04 Raw View
"Matthias Meixner" <meixner@rbg.informatik.tu-darmstadt.de> wrote in message
news:89o517$b66$1@sun27.hrz.tu-darmstadt.de...
> kanze@gabi-soft.de wrote:
> : meixner@rbg.informatik.tu-darmstadt.de (Matthias Meixner) writes:
[snip]
>
> #include <stdio.h>
>
> class A { public: int x;};
>
> void f(int &a, const A &b) { puts("a"); }
> void f(const int &a, A &b) { puts("b"); }
>
> main()
> {
> int a;
> A b;
>
> f(a,b);
> }
>
> -------------------------------------------
>
> If the conversion of object types was considered worse, then
> in this case the first version of f() should be called, but at
> least g++ reports:
>
This is completely different example. In this case both functions require
exactly one conversion and none is better, the standard defines that case as
indistinguishable conversion sequences (13.3.3.2p1).
In the original example the question was which of the overloaded functions
(operators) was better: the one that requires conversion of "this" pointer
or the one that requires conversion of return type. The stadard is pretty
clear in this place (see 13.3.3p1): the return type conversion is the worst.
--
Gene Bushuyev
visit us at http://www.systemc.org
Entia non sunt multiplicanda praeter necessitatem
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Jim Cobban <thesnaguy@hotmail.com>
Date: 2000/03/06 Raw View
This is a multi-part message in MIME format.
--------------6027FBB933D9E3F457E4DE19
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
Matthias Meixner wrote:
> class string {
> char *s;
> public:
> string(const char *c) {s=c;}
> operator char *() { return s; }
> operator const char *() const { return s; }
> };
>
> void foo(const char *s)
> {
> }
>
> main()
> {
> string a("test");
> foo(a);
> return 0;
> }
>
> t2.cxx: In method `string::string(const char *)':
> t2.cxx:8: assignment to `char *' from `const char *' discards qualifiers
In the definition of your constructor you promised that you would never modify the value
of the passed parameter. But then you assigned its value to a pointer which does not
honor that promise. What you really want to do is copy the value of the parameter into
the string, for example by:
string(const char *c) {s= std::strcpy(new char[strlen(c) + 1],c);}
>
> t2.cxx: In function `int main()':
> t2.cxx:22: warning: choosing `string::operator char *()' over
> `string::operator const char *() const'
> t2.cxx:22: warning: for conversion from `string' to `const char *'
> t2.cxx:22: warning: because conversion sequence for the argument is better
This is just one of the many reasons to NOT define type conversion operators. It is NOT
an oversight that std::string does not have any, but rather the method c_str. Note that
the c_str method returns a const char * because you are not permitted to modify the
contents of the std::string object except through its own methods.
--
Jim Cobban jcobban@magma.ca
34 Palomino Dr.
Kanata, ON, CANADA
K2M 1M1
+1-613-592-9438
--------------6027FBB933D9E3F457E4DE19
Content-Type: text/x-vcard; charset=us-ascii;
name="thesnaguy.vcf"
Content-Transfer-Encoding: 7bit
Content-Description: Card for Jim Cobban
Content-Disposition: attachment;
filename="thesnaguy.vcf"
begin:vcard
n:Cobban;James
tel;fax:+1-613-592-9438
tel;home:+1-613-592-9438
x-mozilla-html:FALSE
url:http://www.magma.ca/~jcobban
version:2.1
email;internet:thesnaguy@hotmail.com
title:Consultant
adr;quoted-printable:;;34 Palomino Dr.=0D=0A;Kanata;ON;K2M 1M1;Canada
fn:Jim Cobban
end:vcard
--------------6027FBB933D9E3F457E4DE19--
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: kanze@gabi-soft.de
Date: 2000/03/06 Raw View
Pierre Baillargeon <pb@artquest.net> writes:
[Concerning function overloading...]
|> I think the problem is caused by having a single feature used for two
|> conflicting goals. Currently, the standard only support one goal. When
|> two versions of a function are provided (const and non-const), the goal
|> may be either:
|> 1. That the function can be used on both types of objects. Calling on
|> const usually results in having more constraints on the result.
|> 2. That the const version, knowing the object won't be modified, can be
|> optimized.
The standard doesn't pretend to address 2.
|> I'll give an example of both use.
|> The first example, is the string class, of the original poster, which
|> returns a const char * or a char *, for const and non-const string
|> objects.
Not a good example:-). A string class has no business every returning a
char*. But operator[] in an array would be a good example.
|> The second example is a map-type container. If the container is
|> non-const, then it must allow for the possibility that the access
|> may also be intended as being an insertion. The const version can be
|> optimized by assuming that the access *must* be for an existing
|> object. I have written such a class (with asserts everywhere...).
The standard procedure here is for the non-const version to return a
helper class which supports the insertion. The helper class typically
supports assignment, converting it into a put on the container, and type
conversion, implemented as a get on the container.
|> So how could the compiler know which kind of goal one is after?
It doesn't have to. The code is different in both cases.
|> Since
|> both are implemented using the same syntax (const and non-const versions
|> of a function) the compiler has no idea.
No, the second is normally implemented by means of a helper class.
|> Currently the standard supports goal 1. The only way to achieve the goal
|> 2 is by using explicit const references before calling the function, in
|> order the get the optimized version:
|> struct Opt
|> {
|> char * foo (); // slow.
|> const char * foo () const; // fast.
|> };
|> Opt a;
|> const char * pc1 = a.foo (); // slow.
|> const Opt & ra = a;
|> const char * pc2 = ra.foo (); // fast.
|> Annoying, but is there another trick to get the "desired" behavior?
|> Maybe a 5-pages long obscure template which can theorically be optimized
|> away, proving that, no, the standard does not need to address this issue
|> after all?
It's not a template, it's only about 10 lines long, and the compilers
I've used have optimized it away.
class Accessor // member of container type C of type T, with
{ //index type I.
public:
Accessor( C* owner , I index )
: myOwner( owner ) , myIndex( index ) {}
Accessor& operator=( T value ) const
{
myOwner.set( myIndex , value ) ;
return *this ;
}
operator T() const
{
return myOwner.get( myIndex ) ;
}
} ;
The non-const operator[] returns an instance of Accessor.
This idiom is often needed, independantly of the question of
optimization. If all of the functions of Accessor and the operator[] of
C are inline, most compilers *will* generate the same code for:
container[ index ] = value ;
as for:
container.set( index , value ) ;
--
James Kanze mailto:kanze@gabi-soft.de
Conseils en informatique orient e objet/
Beratung in objektorientierter Datenverarbeitung
Ziegelh ttenweg 17a, 60598 Frankfurt, Germany Tel. +49(069)63198627
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Pierre Baillargeon <pb@artquest.net>
Date: 2000/03/07 Raw View
kanze@gabi-soft.de wrote:
>
> Pierre Baillargeon <pb@artquest.net> writes:
>
> |> Annoying, but is there another trick to get the "desired" behavior?
> |> Maybe a 5-pages long obscure template which can theorically be optimized
> |> away, proving that, no, the standard does not need to address this issue
> |> after all?
>
> It's not a template, it's only about 10 lines long, and the compilers
> I've used have optimized it away.
>
> class Accessor // member of container type C of type T, with
> { //index type I.
> public:
> Accessor( C* owner , I index )
> : myOwner( owner ) , myIndex( index ) {}
> Accessor& operator=( T value ) const
> {
> myOwner.set( myIndex , value ) ;
> return *this ;
> }
> operator T() const
> {
> return myOwner.get( myIndex ) ;
> }
> } ;
>
That is a version of the solution I used in my collection class. I see
two drawbacks to this:
1. It is verbose and must be hand-coded each time the idiom is needed.
Maybe a template with pointers to member function would be possible and
keep the efficiency, but I doubt it.
2. While I'm ready to believe that, for simple index, most compilers are
able to produce the same code as the direct calls, it doesn't address
the issue of more complex indexes, where copying them may be expensive.
Maybe it is possible to use references instead, but I am not sure about
all the issues of lifetimes. A lot of time, the index is a temporary.
I had hoped someone would produce some magic trick. Fortunalety, this
issue is not common enough to be annoying.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]