11 ms·
Exactly. I would add that this goes deeper than just coding styles. My current project relies on a number of widely-used C++ libraries (Qt5, OpenCV, ITK, VTK a
by Aeolos 11y ago
Exactly.
I would add that this goes deeper than just coding styles. My current project relies on a number of widely-used C++ libraries (Qt5, OpenCV, ITK, VTK and a homegrown framework) and each one of them redefines basic data types (std::string, QString, cv::String).
I could go on about how none of them even acknowledges the existence of <cstdint>. I'm sure there are good excuses why each individual library decides to do this (lack of common ABI, badly designed std::string), but the end result is a heap of forced runtime - and cognitive - overhead.
This is pretty sad considering that C++ is advertised as a language that doesn't add unnecessary runtime overhead.
- vidarh 11y agoA lot of it is simply age. Qt and VTK predates C++98 significantly. OpenCV is slightly newer, but it took a long time for people to get comfortable relying on it, and I don't know whether or not it was based on older, pre-existing code. But it's probably going to remain a drag on C++ for another couple of decades...
- Aeolos 11y agoOn the other hand, std::string already existed back then, but they still chose to reimplement it. This points to a more systemic problem in the C++ ecosystem. Has C++ evolved to the point where, say, a new library written today would not have to redefine std::string?
- vidarh 11y agoIt existed, but if you wanted interoperate with your older code, or wanted to run on various platforms, it often would not be available, or bugfree enough or fast enough. It was well after 2000 before everyone started trusting that they'd have a reasonably conformant C++98 environment. You'd still find people start new std::string alternatives up until then, for seemingly good reasons. Some of them valid, some of hem not so much. Today I don't think anyone would redefine std::string, but I haven't written much C++ for years.
- jasode 11y agoThe standard was finalized in 1998 but the implementations on a wide variety of necessary platforms didn't happen until later. Qt's QString predated 1998. Also, this SO q&a has more tidbits: http://stackoverflow.com/questions/1618798/why-is-there-a-different-string-class-in-every-c-platform-out-there http://stackoverflow.com/questions/1618798/why-is-there-a-di...
- unscaled 11y agoNot it didn't. The work on Qt standard on 1991, according to Wikipedia. The work on STL only started in 1994 and became a standard with C++98, and even then it took time for compilers to get decent standard support. So every library needed its own string implementation. New libraries generally use C++ string, unless they're have very strong opinions about performance that trump interoperability (e.g. Facebook's folly). But seriously, isn't that hypocrite to blame old C++ libraries for implementing their own string class, and then go espousing C? C of all languages - the language whose spartan standard library includes almost nothing (including usable string processing code, if you care even slightly about securing your code from memory errors), and each respectable C project ends up implementing their own lists, queues, maps, stacks and of course strings.
- reality_czech 11y agoNo, it isn't "simply age." I know projects started in 2014 that defined their own string types since there are a lot of things that std::string doesn't support. For example, you can't turn a C string into a std::string without copying. There is basically no usable unicode support in std::string. Copies of std::string use copy-on-write, which may create hidden race conditions when sharing data between threads. If you want to fix those problems, you need your own string type.
- paulddraper 11y agoHow does std::string copy on write cause race conditions?
- reality_czech 11y agoBecause if you "copy" a string and the copy really is just a reference to some shared data structure, changing the shared data structure later in another thread without memory barriers or other synchronization causes undefined behavior. Remember that the shared data structure will need a reference count to be updated whenever a reference gets deleted.
- slavik81 11y agoTwo things to note. std::string is pretty much barred from being CoW as of C++11. QString is CoW, but as of Qt4, cross-thread copies are safe to modify just like normal objects.
- nly 11y ago> you can't turn a C string into a std::string without copying. C and C++ use value semantics by default. std::string is a value., a char* is a reference, so this shouldn't be surprising. If you want an immutable, zero-copy, drop-in replacement for std::string, use boost::string_ref (a variant of which will soon be standard). It'll give you a memory unsafe (just like a char\) reference to a C string or* a std::string. Want to wrap a C string safely? Use it in combination with unique_ptr or shared_ptr<char> (for exception safety). > Copies of std::string use copy-on-write, Actually that's explicitly forbidden by the standard, since C++11. The interface for std::string always assumed mutation, which made COW really inefficient. > which may create hidden race conditions when sharing data between threads The COW versions of std::string, that I'm aware of at least, were always thread-safe.
- hellofunk 11y agoI'm curious why std::string is badly designed?
- Aeolos 11y agoI'm also curious why. I wonder if any of the original designers ever shared any insight into their design process. As for what is wrong with it, multiple things. My personal pet peeves are: 1. the lack of formatting or interpolation support (i.e. QString::number(3.14, 'f', 2) or QString("Hello, %d!").arg("world") 2. the utter lack of Unicode support I've seen other people complain about how it interacts with <algorithm>, inefficient support for common operations (join, split, copy) and mutability. I don't particularly care about these, given that its lack of Unicode support pretty much relegates it to a glorified std::vector<char> implementation for me.
- pjmlp 11y agoYes, you can read "The Design and Evolution of C++" and the "The Annotated C++ Reference Manual" aka C++ ARM. There you will understand why C++ is the way it is, when you are trying to sell a safer language with higher level abstractions to hardcore C developers at AT&T, with zero friction with existing C toolchains. Many like me hate the C underpinnings of C++, but if it wasn't for them, most likely no C vendor would ever have adopted it.
- reality_czech 11y agoI'm tired of people blaming the bad things in C++ on C. Most of the bad things in C++ came from C++ itself, not from anywhere else. The Modula-3 type system with its inheritance anti-patterns can't be found anywhere in C. "Guru meditation" template error messages can't be found anywhere in C, nor do C programs typically take hours to compile. In C, functions and types that are "static" to a file don't appear in header files... C++ "improved" that so that private types and functions must appear in header files, greatly extending compile times. Global constructors are not in C... you know what order your program will run in when using C. The set of things in C that were "fixed" by C++ is very small, possibly even the empty set for reasonably modern dialects of C. For example, having the compiler implicitly declare functions as returning "int" was on its way out with or without C++. Probably the worst thing about C was all the implicit type conversions-- between long and int, and char* and boolean. Of course C++ didn't fix this. They even made it worse by declaring that any C++ constructor that took one argument would be a candidate for implicit type conversion. So if you declared Foo::Foo(int i), in the future any time you have an int the compiler would consider promoting it to a Foo. Later they realized their mistake and added the "explicit" keyword so C++ gurus can avoid this error most of the time (when they remember).
- CyberDildonics 11y agoIt seems you are blaming C++ as a language for the design of the libraries you are using. I've also never seen a program actually be slow due to string manipulation (excluding grep). My guess is that if you profile, it will turn out that your performance is getting away from you in places you don't expect.
- Aeolos 11y ago> It seems you are blaming C++ as a language for the design of the libraries you are using. Precisely. In the same way that Java is criticized for proliferating the IAbstractFactoryVisitor design anti-pattern, C++ should be criticized for its weak standard library which causes an overproliferation of mutually-incompatible reimplementations of basic functionality. As to whether this is or is not a performance issue depends on the specifics of the application and the underlying hardware. This is besides the point to this discussion. Why don't C# libraries reimplement System.String like C++ libraries reimplement std::string? That's the real question here.
- pjmlp 11y agoBecause when C++ appeared, its standard library was basically C. Then you had the early adopters that were basically the same developers that were still writing C with lots of inline Assembly. So each developer, or team, had to write their own library, because they knew better. It took all the way up to ANSI C++ (1998) to finally have a proper minimal library. Minimal, because C++ needed to cater to the C mentality that the OS is the runtime. Then you had almost a decade until the C++ vendors were able to catch up the standard. Mind you that in the mid-90's there were still quite a few C compilers that were K&R only. This is why when Java appeared, many of us C++ devs that cared also about safety, jumped into it. As it provided a more portable experience.
- CyberDildonics 11y agoModern libraries don't reimplement std::string. The C++11-14 standard library is actually pretty solid.