Re: A question regarding *s++
Quote:
Originally Posted by
monarch_dodra
Maybe you are confusing evaluation order?
Regardless of type, when you write:
Both p++ and q++ are evaluated first (but in undefined relative order).
Once this is done, operator= is called on the
return values of p++ and q++, ie, the old values of p and q. (making it look like the assignment took place before increment)
There is no special magic or rules that applies only to PODs that do the assignments first,
and then increments the values of p or q.
...
Either that, or I seem to not understand what you are saying. Your example (rewritten since incomplete) seems to work correctly:
Code:
#include <iostream>
#include <string>
int main()
{
char pArray[20] = { '\0' };
char* p = pArray;
std::string helloStr = "Hello";
//force the null terminator into string //Undefined behavior, but defined in practice
helloStr.c_str();
std::string::iterator q = helloStr.begin();
while (*p++ = *q++); //note that this reads string.end(), but should point '\0'. May crash in ranged debug
std::cout << pArray << std::endl;
}
Was this your full example?
Regards,
No, it was from my memories ;-)
Here is the code that compiles:
Code:
#include <iostream>
int main()
{
char * q = "Hello";
char buf[20] = { '\0' };
char * p = buf;
while (*p++ = *q++);
std::cout << buf << std::endl;
return 0;
}
If incrementation would happen before assignment the p[0] would not be set correctly.
I will add the string class example soonly.
Regards, Alex
Re: A question regarding *s++
Quote:
Originally Posted by
itsmeandnobodyelse
If incrementation would happen before assignment the p[0] would not be set correctly.
Sure it would, given the post-increment semantics which are at the heart of what we're discussing.
Re: A question regarding *s++
Here the full sample
Code:
#include<iostream>
class String
{
char * ps;
int siz;
int len;
public:
String(const char * psz)
{
siz = strlen(psz)+1;
ps = new char[siz];
strcpy(ps, psz);
}
~String() { delete []ps; }
const char * c_str() { return ps; }
friend class StringIterator;
};
class StringIterator
{
int pos;
String * s;
public:
StringIterator(String & str) : s(&str), pos(0) {}
char & operator*() { return s->ps[pos]; }
StringIterator& operator++(int)
{
pos++;
return *this;
}
};
int main()
{
char * q = "Hello";
char buf[20] = { '\0' };
char * p = buf;
while (*p++ = *q++);
std::cout << buf << std::endl;
String s("World");
String t(" ");
StringIterator i(s);
StringIterator j(t);
while (*j++ = *i++);
std::cout << t.c_str() << std::endl;
return 0;
}
And output is
Hello
orld
Regards, Alex
P.S.
I don't think the above is a real problem. However, it was that what invoked me to not using post-increment on class types anymore.
Re: A question regarding *s++
Quote:
Originally Posted by
Lindley
Sure it would, given the post-increment semantics which are at the heart of what we're discussing.
Quote:
Originally Posted by
itsmeandnobodyelse
StringIterator& operator++(int)
{
pos++;
return *this;
}
The real problem is that you implemented post-increment as pre-increment, breaking standard conventions and assumptions.
I'm pretty sure 4 or 5 people will tell you the same in a 5 minute time span.
Re: A question regarding *s++
Quote:
Originally Posted by
itsmeandnobodyelse
Here the full sample
A correct implementation of post-increment would be:
Code:
StringIterator operator++(int)
{
StringIterator copy(*this);
pos++;
return copy;
}
This would give the correct result. However, the expense of the copy is the reason why post-increment is sometimes slower.
Re: A question regarding *s++
Quote:
Originally Posted by
Lindley
A correct implementation of post-increment would be:
Code:
StringIterator operator++(int)
{
StringIterator copy(*this);
pos++;
return copy;
}
This would give the correct result. However, the expense of the copy is the reason why post-increment is sometimes slower.
Ok, looking at that code makes it clear why the compiler couldn't optimize away the additional overhead (under normal circumstances), even if I don't use the returned temporary object.
But could it do that if the implementation of the operator would be inlined? :rolleyes:
Re: A question regarding *s++
Personally, I would replace the following incorrectly implemented post-increment operator:
Code:
StringIterator& operator++(int)
{
pos++;
return *this;
}
with
Code:
//pre-increment: ++i
StringIterator& operator++()
{
++pos;
return *this;
}
//post-increment: i++
StringIterator operator++()
{
StringIterator orig(*this);
++(*this);
return orig;
}
EDIT:
But I would like to ask the question... why are you implementing a string type anyway? Why not use std::string?
Re: A question regarding *s++
Quote:
Originally Posted by
monarch_dodra
The real problem is that you implemented post-increment as pre-increment, breaking standard conventions and assumptions.
I'm pretty sure 4 or 5 people will tell you the same in a 5 minute time span.
I thank you very much for pointing out my error. It was a very old issue (maybe 16 years old) and I am very glad that I now know the solution.
Quote:
But I would like to ask the question... why are you implementing a string type anyway? Why not use std::string?
I am using std::string since 2003. The various string classes I made are all older than 10 years where STL wasn't available for all compilers or were not allowed to be used in projects.
Private string classes can have a much better functionality than std::string. Especially for streaming, editable substrings and codeset support. The (only?) disadvantage is that they were not available with the compiler and must be installed (and be allowed) at each new platform.
Regards, Alex
Re: A question regarding *s++
Quote:
Originally Posted by
itsmeandnobodyelse
The (only?) disadvantage is that they were not available with the compiler and must be installed (and be allowed) at each new platform.
Another disadvantage is that std::string is standard whereas your custom string class is not. A new team member wouldn't have to spend any time learning the 'Alex String Library'. He/she could instead be using a well documented, well tested, well known library. If he/she doesn't already know std::string, he/she could learn it & know that the knowledge will still be relevant if he/she changed companies (unlike effort spent to learn alex::string). When there's a bug they can be 99% sure its not a bug in the string class (although there seems to be no shortage of programmers that blame the compiler). They could post questions on programming forums about how to use std::string but not alex::string.
Re: A question regarding *s++
Quote:
Originally Posted by
Martin O
Another disadvantage is that std::string is standard whereas your custom string class is not. A new team member wouldn't have to spend any time learning the 'Alex String Library'. He/she could instead be using a well documented, well tested, well known library. If he/she doesn't already know std::string, he/she could learn it & know that the knowledge will still be relevant if he/she changed companies (unlike effort spent to learn alex::string). When there's a bug they can be 99% sure its not a bug in the string class (although there seems to be no shortage of programmers that blame the compiler). They could post questions on programming forums about how to use std::string but not alex::string.
That isn't so much a problem. Actually I added all standard member functions to my own string class just to meet that requirement. You should also see that the source code of existing STL implementations is without any comments and ugly to hell. So, debugging my own string class is much less frustrating than debugging into the basic_string. Did you ever debug into the 'traits' and didn't get lost somewhere? Same applies to documentation of basic_string which I wouldn't name 'well-documented'. IMO is really bad readable mostly due to the fact that they made it a template class which adds a complexity to the implementation and documentation that is unnecessary for everyone who knows which char type he was using.
Also I don't share the idea that private implementations of a library can't have the same quality than a standard library. Actually I experienced more bugs and shortcomings of the various implementations of STL as it was with my own libraries which didn't change for years and are well-proved in many projects. For example all my containers were thread-safe and have no problems to be passed via dll boundaries. Last is, there was no alternative in the years before C++ standard ;-)
Regards, Alex
P.S.
This wasn't a pleading for self-made libraries or for not using STL. On the contrary, I am a consequent user of those standards wherever it is possible. But I wasn't afraid of making or using my own libraries if it was required by the project or by the customer. And the basic_string class actually is a poor string class.
Re: A question regarding *s++
Quote:
Originally Posted by
itsmeandnobodyelse
You should also see that the source code of existing STL implementations is without any comments and ugly to hell.
Yes, STL implementations are typically geared towards getting the most out of the compiler they're written for. They are not intended to be readable directly.
Quote:
So, debugging my own string class is much less frustrating than debugging into the basic_string. Did you ever debug into the 'traits' and didn't get lost somewhere?
No, there's no need to debug into basic_string because it doesn't have any significant bugs at this point. If the debugger tries to step into it, you just "Step out" and then "step in" again to make another try at getting where you intended to go.
Any bug which seems to be in basic_string is simply the programmer's misuse or corruption of the object.
Quote:
Same applies to documentation of basic_string which I wouldn't name 'well-documented'.
Eh, it's just fine for everything I need....
http://www.cplusplus.com/reference/string/
Quote:
IMO is really bad readable mostly due to the fact that they made it a template class which adds a complexity to the implementation and documentation that is unnecessary for everyone who knows which char type he was using.
Since basic_string is rarely instantiated with anything other than char or wchar_t, an argument could be made that it didn't have to be a template class. But I still think the template approach is superior to the CString solution, which is to have the observable class internals change depending on a preprocessor flag. That's just a bit nuts IMO.
Re: A question regarding *s++
I'm all for std::string, for the above reasons (Standard+already debugged).
IMO, there is nothing wrong with templates. Once you get used to it, it really doesn't make any difference.
Besides, a template form is needed for wstring...
I DO think that std::string is a bit lacking in the interface/usability department.
Sure, you can always get your work done by combining algorithms, search_first_of and erase/remove, but is it so much to ask for a "trim"?
Re: A question regarding *s++
Ah, but the great thing about the design of the STL----including, for the most part, std::string----is that it's easily extensible.
That's why we have options like the Boost String Algorithms library. Which does, by the way, include trim().
Re: A question regarding *s++
Quote:
Originally Posted by
Lindley
Ah, but the great thing about the design of the STL----including, for the most part, std::string----is that it's easily extensible.
That's why we have options like the
Boost String Algorithms library. Which does, by the way, include trim().
Really? You can't safely derive from it, can you? You can't add new member functions therefore, right?
Enhancements via function templates hardly can be used for praising a class design. On the contrary, they are global functions and I share the opinion that global functions mostly is poor OOP and the need for those functions show the heavy shortcomings of this class.
Even my very first string class in the early 90's had better functionality and the missing 'trim' was only one of many evidences that they had many problems to integrate string semantics like 'whitespace', 'words', 'sentences', and more to their string class which IMO is not much more then a container for char types - where even a vector<char> has some advantages.
Or take the case where you need to convert from wstring to string or vice versa or let alone character encoding like UTF-8 to ANSI and back. It is not alone that the basic_string doesn't give any concepts for this, it adds additional complexity to those conversions whenever different char types are involved.
Regards, Alex
Re: A question regarding *s++
Quote:
Originally Posted by
itsmeandnobodyelse
Really? You can't safely derive from it, can you? You can't add new member functions therefore, right?
Enhancements via function templates hardly can be used for praising a class design. On the contrary, they are global functions and I share the opinion that global functions mostly is poor OOP and the need for those functions show the heavy shortcomings of this class.
Even my very first string class in the early 90's had better functionality and the missing 'trim' was only one of many evidences that they had many problems to integrate string semantics like 'whitespace', 'words', 'sentences', and more to their string class which IMO is not much more then a container for char types - where even a vector<char> has some advantages.
Or take the case where you need to convert from wstring to string or vice versa or let alone character encoding like UTF-8 to ANSI and back. It is not alone that the basic_string doesn't give any concepts for this, it adds additional complexity to those conversions whenever different char types are involved.
Regards, Alex
Well actually, some would say that in good OOP design, all these functions should NOT be member functions. The less member functions you have, the better.
I mean, boost was able to expand on string (or string-like containers) an entire string library algorithm. If that's not Enhancement, I don't know what is.
I'll grant you that basic_string is not great for holding (variable-sized) UTF, but it can hold char or wchar just fine, as well as any fixed size characters. You can convert one string type to another quite easily using iterator construction, provided you can construct the basic char type from the other type.
No, what I think is that there should have been a <string_algorithm> class, just like boost's, but right in the STL.
I know the STL philosophy is to not provide a tool if the combination of existing tools can do it for you (and they can), but I think there should have been an exception for strings, inside a library that operates specifically on strings.
My choice of words "std::string is a bit lacking in the interface/usability department" may have been less than ideal, and I will correct myself to: "the STL offers little practical facilities for string manipulations, forcing the user into more direct (and bulky) string iterator+algorithm+functor manipulation". And I think it's a pity.