3 ms·
That's an extremely negative characterization of people who want more features in a language. It's not "change for the sake of change". It's change for the sa
by comex 7y ago
That's an extremely negative characterization of people who want more features in a language. It's not "change for the sake of change". It's change for the sake of making everyone's programs better.
C++ is a good demonstration of both the costs and benefits of adding new features. The costs are obvious: the language and standard library are absolutely full of duplicate features, where the old thing is deprecated in favor of the new thing, but the old thing still has to be supported for compatibility's sake.
But so are the benefits. C++ hasn't always moved so quickly, after all. For 13 years, from its initial standardization in 1998 to its first major revision in 2011, the language was effectively frozen. It was never a small language, but it was stable, not a constantly changing foundation.
It was also absolutely horrid.
This is how you iterate over a std::vector in C++98:
for (std::vector<int>::iterator it = vec.begin();
it != vec.end();
++it) {
int number = *it;
// use `number`
}
One of the features added in C++11 is the range-based for loop, which simplifies that to just:
for (int number : vec) {
// use `number`
}
The old style was perfectly working, and still works. The problem it solves has not changed. It's just that it is, and has always been, a terrible solution! The noisiness hurts not only ease of use (obviously), but also robustness and understandability: it tends to obscure the actual logic the programmer intended, making code harder to read.
Adding the range-based for loop did burden everyone with additional complexity – but it was clearly worth it. The new style is not just "more 'modern'", it's straight-out better. Sure, code that uses the old style does not need to change. Often it's best to leave it alone. But if so, that doesn't mean the existing code is perfect, just that the benefits of refactoring it don't outweigh the costs (such as the risk of introducing bugs). When writing new code, on the other hand, there's no reason not to use the new style.
Not all features are such a slam dunk. Usually the benefits are not so clear, and often the amount of complexity added is higher. The result is a difficult tradeoff, a competition between different people with different interests, just as you say. People are justified in thinking the benefits are not worth the cost.
But there are benefits, almost always. This pattern matching proposal, for example, adds a ton of syntax and duplicates a feature (the switch statement), and overall it seems more complex than it needs to be. I'm not a fan: I'm not sure whether C++ needs pattern matching at all, and if it does get it then I'd prefer a different design. But if this design were accepted, I'd still enjoy using it in my code! After all, pattern matching itself has decades of history in functional programming languages, and has proven to be an elegant and expressive way to write certain kinds of algorithms and use certain kinds of data structures – things that in today's C++ are rather awkward.
- userbinator 7y agoit tends to obscure the actual logic the programmer intended, making code harder to read for(int i = 0; i < vec.size(); i++) // do something with vec[i] That's even simpler and more in line with what vectors are usually used for, and when it comes time to debug, you don't have to deal with the template-hell that is the standard library iterator-framework. The for : may look simpler at first glance, but quick turns into a nightmare when you're trying to do some deep debugging (and if you haven't had to debug by reading the Asm, I think you haven't done enough C++...) because it obscures a significant amount of complexity which really shouldn't be necessary anyway.
- jcelerier 7y agoyour simpler code is at least theoretically less efficient - you get an int to size_t (unsigned long long) conversion twice (once when comparing with size() and once when accessing the vec) and you compare to the size every time. This looks like it is irrelevant in release mode, but it may end up having an effect on your debug performance which is important in many domains. You would have to write for(std::size_t i = 0, N = vec.size(); i < N; i++) // do something with vec[i] instead if you still insist in raw loops. But if you look at https://gcc.godbolt.org/z/8JwJbw https://gcc.godbolt.org/z/8JwJbw, you will notice that the range-based loop is actually the one which will produce the smaller code which may translate into more efficiency, and is also more readable.
- Too 7y agoChange the vector to std::list and you loose the [i] operator. Now how would you rather iterate that? 5 lines of begin() end() *it++, or a 2-liner foreach. We haven't even brought const- and reference-correctness into the picture here. That makes the number of potential errors in the it-example even worse. There are also iterators where the size is not known up front, streaming input for example. The point is, some features in a language can reduce complexity and improve readability (like foreach) while others can increase it (move assignment constructors?). This is only looking at it from a developers point of view though, compiler authors might disagree.