Newsgroup: comp.lang.c++
Subject: Why string's c_str()? [Overloading const char *()]
From: DSF <notavalid@...>
Date: Wed, 30 Oct 2013 15:00:26 -0400
Hello group!
I have been using/writing my own string class for some time now. A
while back, I discovered the wonderful ability to overload const char
*. I was now able to use my string anywhere I could use const char *.
But... I had always wondered why the STL string class uses c_str()
instead of overloading const char *(). My first thought on the
subject is that it frees the string class to store the string in any
manner the coder chooses. One option would be to use the format of
[length of string][string]. But then I started reading articles
online stating that overloading const char *() is a bad idea because
it can allow unintended implicit conversions. Of course, most of
these articles used the typical overkill terms such as "dangerous" and
"evil", etc. Without going into detail of the specific dangers and
evils.
I came upon a discussion at the site below that intrigued me.
http://www.dreamincode.net/forums/topic/260662-operator-const-char-and-operator-caveats-with-overloads/
Since the site thread is fairly old, I decided to ask here.
I've reposted a small section here. (I hope they don't mind.)
//start
D.I.C Lover
Re: operator const char* and operator[] - caveats with overloads?
Posted 21 December 2011 - 02:18 PM
The problems will arise from ambiguous conversions. In C++, if you
have a statement with two different types, the compiler will try to
find a cast for one or the other so that the statement can be
evaluated. Now when you start adding conversions like this, you can't
prepare for every possible use of your class. Because of this, someone
who doesn't fully understand the language might try to use your class
in such a way that ambiguous conversions occur. The fact that the
designers of the std::string class left out a conversion operator, is
enough of an explanation to tell me that it should be avoided.
View Postmonkey_05_06, on 21 December 2011 - 03:52 PM, said:
What would be considered "accidental" or "unintended" conversions to
char*?
Things that come to mind are.
01 String a, b;
02 if (a==B) {}
03 if (a=="str") {}
04 if ("str"==a) {}
05 if ("str"!=a) {}
06 if (a > B) {}
07 if (a <= B) {}
08 if ("str" < a) {}
09 *a;
10 (a + 5);
All these things will suddenly just compile, but none of these will do
what you expect from a String class.
What Karel-Lodewijk said is exactly what I am talking about. Without a
conversion operator, most of those statements will not compile. With a
conversion operator they WILL compile, but not do what you expected.
If you feel like chasing around hard to find bugs, then leave it in
there, if not just add a function like the std::string::c_str().
//end
The examples above along with "none of these will do what you expect
from a String class" aroused my curiosity. Except for 09 and 10, I
was pretty certain the rest would do what I expect them to.
So I compiled the above with my string class, adding the harmless
getch() (wait for a keypress) within all of the {} so the whole thing
wouldn't be optimized away and to test the result of the if
statements. I also ran it with string 'a' initialized to "str".
Every single one of the first 8 did exactly what I expected.
9 did nothing (of course), but walking through the assembly code
confirmed it returned a pointer to the first character of string 'a'.
I added a char c; statement, then c = *a; then a printf using 'c' and
it worked. Funny, the compiler won't optimize *a; away, but with the
statement c=*a; it will optimize away the c= if you don't use the 'c'
leaving the *a code intact.
10 I wasn't sure about. Of course, it also did nothing on the
surface, but below it got a pointer to 'a', added 5 to it and returned
the resulting pointer. An overrun with a = "" or a = "str", but
that's not the point.
So what is the "danger" of overloading * (or in the case of above *
and [])? Everything I've written so far has worked as I expected, and
it's very convenient and looks more elegant than the alternatives when
one needs to pass a const char * to an API call, etc.
"'Later' is the beginning of what's not to be."
D.S. Fiscus
Subject: Why string's c_str()? [Overloading const char *()]
From: DSF <notavalid@...>
Date: Wed, 30 Oct 2013 15:00:26 -0400
Hello group!
I have been using/writing my own string class for some time now. A
while back, I discovered the wonderful ability to overload const char
*. I was now able to use my string anywhere I could use const char *.
But... I had always wondered why the STL string class uses c_str()
instead of overloading const char *(). My first thought on the
subject is that it frees the string class to store the string in any
manner the coder chooses. One option would be to use the format of
[length of string][string]. But then I started reading articles
online stating that overloading const char *() is a bad idea because
it can allow unintended implicit conversions. Of course, most of
these articles used the typical overkill terms such as "dangerous" and
"evil", etc. Without going into detail of the specific dangers and
evils.
I came upon a discussion at the site below that intrigued me.
http://www.dreamincode.net/forums/topic/260662-operator-const-char-and-operator-caveats-with-overloads/
Since the site thread is fairly old, I decided to ask here.
I've reposted a small section here. (I hope they don't mind.)
//start
D.I.C Lover
Re: operator const char* and operator[] - caveats with overloads?
Posted 21 December 2011 - 02:18 PM
The problems will arise from ambiguous conversions. In C++, if you
have a statement with two different types, the compiler will try to
find a cast for one or the other so that the statement can be
evaluated. Now when you start adding conversions like this, you can't
prepare for every possible use of your class. Because of this, someone
who doesn't fully understand the language might try to use your class
in such a way that ambiguous conversions occur. The fact that the
designers of the std::string class left out a conversion operator, is
enough of an explanation to tell me that it should be avoided.
View Postmonkey_05_06, on 21 December 2011 - 03:52 PM, said:
What would be considered "accidental" or "unintended" conversions to
char*?
Things that come to mind are.
01 String a, b;
02 if (a==B) {}
03 if (a=="str") {}
04 if ("str"==a) {}
05 if ("str"!=a) {}
06 if (a > B) {}
07 if (a <= B) {}
08 if ("str" < a) {}
09 *a;
10 (a + 5);
All these things will suddenly just compile, but none of these will do
what you expect from a String class.
What Karel-Lodewijk said is exactly what I am talking about. Without a
conversion operator, most of those statements will not compile. With a
conversion operator they WILL compile, but not do what you expected.
If you feel like chasing around hard to find bugs, then leave it in
there, if not just add a function like the std::string::c_str().
//end
The examples above along with "none of these will do what you expect
from a String class" aroused my curiosity. Except for 09 and 10, I
was pretty certain the rest would do what I expect them to.
So I compiled the above with my string class, adding the harmless
getch() (wait for a keypress) within all of the {} so the whole thing
wouldn't be optimized away and to test the result of the if
statements. I also ran it with string 'a' initialized to "str".
Every single one of the first 8 did exactly what I expected.
9 did nothing (of course), but walking through the assembly code
confirmed it returned a pointer to the first character of string 'a'.
I added a char c; statement, then c = *a; then a printf using 'c' and
it worked. Funny, the compiler won't optimize *a; away, but with the
statement c=*a; it will optimize away the c= if you don't use the 'c'
leaving the *a code intact.
10 I wasn't sure about. Of course, it also did nothing on the
surface, but below it got a pointer to 'a', added 5 to it and returned
the resulting pointer. An overrun with a = "" or a = "str", but
that's not the point.
So what is the "danger" of overloading * (or in the case of above *
and [])? Everything I've written so far has worked as I expected, and
it's very convenient and looks more elegant than the alternatives when
one needs to pass a const char * to an API call, etc.
"'Later' is the beginning of what's not to be."
D.S. Fiscus
via Usenet Forums - Usenet Search,Free Usenet - comp.lang.c++ http://www.pocketbinaries.com/usenet-forums/showthread.php?118599-Why-string-s-c_str()-Overloading-const-char-*()&goto=newpost
View all the progranning help forums at:
http://www.pocketbinaries.com/usenet-forums/forumdisplay.php?128-Coding-forums