6 ms·
I can't speak about the ISO as a whole for engineering fields, but the ISO standardization process has worked out horribly for the C++ community. Not only for t
by Kranar 6y ago
I can't speak about the ISO as a whole for engineering fields, but the ISO standardization process has worked out horribly for the C++ community. Not only for the issues Tim Sweeney points out, but the entire C++ standardization process is defacto a closed-off and secretive process where participation is limited to those who can physically travel from place to place and it's painfully obvious that the quality of features in C++ are much lower than what they could have been otherwise.
A common claim made by the ISO C++ committee regarding criticism of the language is that these guys are volunteers working in a mostly unpaid capacity on the language, and often have to hit tight deadlines to have any shot at getting a feature into the standard, and that's true exactly because of how arcane the ISO standardization process is. It's this pseudo-antagonistic process where maybe one or two individuals are tasked to "champion" a paper in front of their peers and then everyone is supposed to pretend that there's no politics involved and that the paper gets approved entirely on its technical merit.
C++ would have been much better served from ditching that and doing what Java, Python, and Rust do, have broad community feedback and input. It's hard to imagine what beneficial features are in C++ that would not still be there had there been involvement from the broader community of game developers, embedded device developers, desktop software developers and a host of people who use the language regularly, but it's clear many clumsy and awkward features would have been eliminated, including the now 50 ways of initializing variables, broken standard library features like std::variant, the now unusable std::regex, the minefield that is std::random, the upcoming bloated and error prone std::ranges, it's no wonder many C++ development teams are skeptical of the utility of the standard library and just roll their own alternatives.
I hope no other language goes down the road of using ISO to standardize its language.
- varjag 6y agoC++ was pretty horrible prior to C++98 as well (and likely 33 out of 50 ways to initialize a variable already existed by then). It did improve considerably within the past decade under the auspices of the committee.
- initplus 6y agoOne of the biggest impediments caused by the C++ standards committee is the tight scope of the standard. Anything outside of the language/library spec is entirely outside the realm of standardization. So any tooling improvements (dependency management, build process) are not able to be made to the language. Fractured solutions harm adoption, languages with good dependency management and good build processes have one solution they push on everyone.
- deckard1 6y agoC++ at least had the benefit of industry and OOP trend behind it. It was rather fortunate in this case. I've argued elsewhere on HN that Common Lisp died because they were closed and secretive at the exact moment they needed to go the opposite route. https://www.cs.cmu.edu/Groups/AI/html/faqs/lang/lisp/part4/faq-doc-10.html https://www.cs.cmu.edu/Groups/AI/html/faqs/lang/lisp/part4/f... Around 2004, Lisp was having a bit of a revival of sorts. Lisp was becoming trendy, various blogs and web sites were created. But the only documentation you could find was the HyperSpec. Which, as anyone that had the misfortune of reading, is awful as a reference. It's both too technical for casual software developers and not official enough for language implementers. There were two free, open source Lisps available (CMUCL, CLISP) and both were rather unloved and clunky at best. Even Linus had a bit of trouble getting his hands on POSIX standards. Imagine Linux dying because it couldn't follow standards that Linus could not acquire. By the mid-to-late '90s the writing was already on the wall. Perl, Python, PHP, Ruby followed no standard. It became common for the free implementation to be the standard. Clojure arrived and largely filled the Lisp void. Racket attempted a similar movement, by renaming itself from PLT Scheme to something that removes the emphasis on any particular standard. If you want Lisp today, though, you're probably doing Clojure.
- rlonstein 6y agoI agree with the thrust of your argument as I was learning Common Lisp around then but you make a factual mistake: > Around 2004... There were two free, open source Lisps available (CMUCL, CLISP) and both were rather unloved and clunky at best. SBCL and ECL existed and were quite usable. The documentation was as you say, another story. There was the HyperSpec, copies of CLtL, and a number of out-of-print or hard to find books that described some kind of Lisp. It was hard to be a tyro without a guide.
- varjag 6y agoHonestly, attempts to pin down Lisp's obscurity to a single cause are almost as old as Lisp itself. No, Lisp did not miss out because people could not read the docs; it simply was as far from XML/Java zeitgeist then as from UNIX/C/C++ before. > Perl, Python, PHP, Ruby followed no standard. It became common for the free implementation to be the standard. And I mean look how well it worked with transitions to Perl 6 and Python 3.
- dataflow 6y ago> it's painfully obvious that the quality of features in C++ are much lower than what they could have been otherwise. It's not obvious to me at all; in fact I'm more tempted to believe the opposite. C++ has its shortcomings, but when I (say) compare the C++ standard library against third-party libraries, I find the standard library design & implementations to be of much higher quality. They're often far more flexible and handle far more edge cases than open-source libraries do. So, while I would love for the C++ standard to be free, I think this would be more of an argument for not making it so.
- Kranar 6y agoAny specific examples come to mind? I usually find Folly [1], Abseil [2] or the EASTL [3] beat the standard library on almost every metric you can imagine, including the under appreciated compile time metric. And then of course there's boost [4], but people have very mixed opinions about it. The reason a lot of developers use the standard library in C++ is because dependency management in C++ such a nightmare that many people writing a library are forced to use the standard if they want any hope of adoption even when far superior options exist. It's literally something people writing C++ libraries will advertise "Dependency free header only library!" because they know without that a lot of developers won't bother using it. Anyways, I would be interested to know what part of the standard library you find is better than third party options. [1] https://abseil.io/ https://abseil.io/ [2] https://github.com/facebook/folly https://github.com/facebook/folly [3] https://github.com/electronicarts/EASTL https://github.com/electronicarts/EASTL [4] https://www.boost.org/ https://www.boost.org/
- dataflow 6y agoBefore I give an example, note a couple of things: - You've picked some of the best C++ libraries as if they're somehow representative of the ocean of C++ code that's out there, whereas I was talking more about the general landscape. - It's hard to do an apples-to-apples comparison for a library (like Abseil) that tries to avoid replicating what's already in the standard library, so those aren't necessarily the best examples to discuss here. That said, OK, here's one trivial example. It is a major time sink to dig these up and write self-contained examples for the sake of argument (it took me 1 hour to write this entire comment), so I hope this example can be sufficient to get my point across. So folly has FBVector and it supports custom allocators, right? OK, so just try making a vector with a custom pointer type: #include <vector> // #include <folly/FBVector.h> template<class T> struct my_pointer { typedef my_pointer this_type; typedef T element_type, value_type; typedef ptrdiff_t difference_type; typedef this_type pointer; typedef value_type &reference; bool operator!=(this_type const &other) const { return !(*this == other); } bool operator==(this_type const &other) const { return this->p == other.p; } difference_type operator-(this_type const &other) const { return this->p - other.p; } explicit operator bool() const { return !!this->p; } friend this_type operator +(difference_type n, this_type me) { return me + n; } explicit my_pointer(T *p) : p(p) { } my_pointer(std::nullptr_t p) : p(p) { } my_pointer() : p() { } reference operator *() const { return *this->p; } template<class U> using rebind = my_pointer<T>; this_type &operator++() { ++this->p; return *this; } this_type &operator+=(difference_type n) { this->p += n; return *this; } this_type &operator--() { --this->p; return *this; } this_type &operator-=(difference_type n) { this->p -= n; return *this; } this_type operator+(difference_type d) const { return this_type(this->p + d); } this_type operator++(int) { this_type copy(*this); ++*this; return copy; } this_type operator-(difference_type d) const { return this_type(this->p - d); } this_type operator--(int) { this_type copy(*this); --*this; return copy; } value_type *operator->() const { return this->p; } reference operator[](difference_type d) { return this->p[d]; } private: T *p; }; template<class T> struct my_allocator { std::allocator<T> base; typedef T value_type; typedef size_t size_type; typedef my_pointer<T> pointer; template<class U> struct rebind { typedef my_allocator<U> other; }; pointer allocate(size_type n) { return pointer(this->base.allocate(n)); } void deallocate(pointer p, size_type n) { return this->base.deallocate(&*p, n); } }; namespace std { template<class T> struct iterator_traits<my_pointer<T> > { typedef typename my_pointer<T>::pointer pointer; typedef typename my_pointer<T>::reference reference; typedef typename my_pointer<T>::value_type value_type; typedef typename my_pointer<T>::difference_type difference_type; typedef std::random_access_iterator_tag iterator_category; }; } int main() { #ifdef FOLLY_CPLUSPLUS folly::fbvector #else std::vector #endif <int, my_allocator<int> > numbers; numbers.push_back(1); return 0; } This compiles and runs fine with GCC, Clang, and MSVC (on, say, C++17). But now try to uncomment the #include so that it uses folly and you suddenly get errors like this: /usr/include/folly/FBVector.h:148:27: error: no viable conversion from 'folly::fbvector<int, my_allocator<int>>::Impl::pointer' (aka 'my_pointer<int>') to 'int *' S_destroy_range(b_, e_); /usr/include/folly/FBVector.h:365:34: note: passing argument to parameter 'first' here static void S_destroy_range(T* first, T* last) noexcept { Funny, so S_destroy_range is used internally, and it requires raw pointers. But who says my fancy pointers will even necessarily map 1:1 to a linear (and contiguous!) pointer space? What we see here is folly pretends to support custom allocators, but it cuts corners internally. (!) Which is awful not only because of the inflexibility, but because it misleads you, too. If they're introducing unfounded assumptions internally just out of sheer convenience, how am I supposed to trust the implementation? Heck, if I had implemented implicit conversions to raw pointers so that the code compiled, I might not have even discovered there's a latent bug in my program. In contrast, in my experience, actual standard library implementations pay attention to the details and don't tend to cut corners like third party libraries do. Now, again, keep in mind this is what we get with some of the best libraries, whereas I was talking about the general landscape, so the situation isn't even remotely this good on average.
- passivate 6y agoIts clear that C++ is very popular, and a lot of people chose to use it, for better or for worse. I'd like to hear your thoughts referencing specific issues you have w.r.t. the language (not libraries). As it stands, I'll take your comment as a passionate plea :)
- saagarjha 6y agoI’m not sure if you meant it, but your comment comes off as being in exceptionally bad faith. Of course C++ is a popular language and people put up with the decisions ISO makes-that doesn’t mean it doesn’t have issues. The distinction between “the language” and “libraries that ship with the language” is not useful but even if it was the comment presents initialization a wart in the core language.
- passivate 6y ago>The distinction between “the language” and “libraries that ship with the language” is not useful but even if it was the comment presents initialization a wart in the core language. I think it is extremely useful, as the standard library is easily (and often) replaced. We have a difference of opinion, and that is perfectly fine, but please do realize that this doesn't mean my comment is in bad faith. Every library has a goal, and the standard library's goal is not to serve as a industry-ready plug-in for high-performance code. Writing high-performance code in C++ is an advanced task that necessitates more control, which makes the standard library not a good fit. The model of (language) + (library) makes it easy for the end user to pick a library of their choice, for their application. >comment presents initialization a wart in the core language. Okay, that is one point. When people say "X sucks" or "X is horrible" there is very little a reader can gain out of that. If a person's opinion is formed by deep experience with that X, then I am interested in knowing specifics that lead to that opinion.
- saagarjha 6y agoThe distinction is useful in the context of a discussion about alternative standard libraries, but in the context of the ISO working group that does the design for both it is not. I understand that you intention was to get more information, but I wanted to make sure you're aware that responding to someone who is listing out their complaints with what is essentially "a bunch of people use the language productively, can you please give me information that you just went over, otherwise I am going to disregard your comment" can be interpreted as bad faith because it's a common troll/asymmetric effort tactic.