14 ms·
C++20 Ranges
- piinbinary 8y agoGoogle cache: http://webcache.googleusercontent.com/search?client=ubuntu&channel=fs&q=cache%3Ahttp%3A%2F%2Fericniebler.com%2F2018%2F12%2F05%2Fstandard-ranges%2F&ie=utf-8&oe=utf-8 http://webcache.googleusercontent.com/search?client=ubuntu&c...
- mimi89999 8y agoI only see a database error on this website.
- johnisgood 8y ago+1 > Error establishing a database connection
- feikname 8y agoIt's the infamous HN hug of death.
- eric_niebler 8y agoI just upgraded my GCE instance. Let's see if it can withstand this withering assault. <makes popcorn>
- nindalf 8y agoWeb Archive mirror -> http://archive.is/lnrTw http://archive.is/lnrTw
- krackers 8y agoWhat's the difference between this and something like python-esque generators which also appear to be lazy and have a much saner syntax? Doesn't C++ plan to support coroutines which should provide a similar way to lazily evaluate lists? Also the example has a lot of boilerplate code that reminds me of template metaprogramming hell. Is this something that's expected to be wrapped up nicely by Boost & co. for end users?
- mikeloomis 8y agoA c++20 range is just a bounded container. instead of having to write, `(container.begin(), container.end())` for any function that uses iterators to bound itself, you just write `(container)` and it knows its a range. The range function in python is similar only in name, the c++20 range concept is not a generator. 2. There is a coroutine feature branch, I believe developed by Gor Nishanov, https://github.com/GorNishanov https://github.com/GorNishanov. Also not related to c++20 ranges. 3. Eric Niebler used a single templated function. This is not anywhere close to template metaprogramming hell, and I think you should look into templates as once you learn about them they become way less intimidating. Also has nothing to do with c++20 ranges.
- amelius 8y agoI have yet to see a non-managed systems programming language which supports coroutines properly. Rust supports async/await, but it's not the same thing, as this comment illustrates: https://news.ycombinator.com/item?id=15121199 https://news.ycombinator.com/item?id=15121199
- mikeloomis 8y agoIt'll be after 20 for sure, we're still waiting for the executor TS for async networking to be able to come in.
- Sharlin 8y agoThe "for_each" (aka flatmap, or bind, or =<<), "maybe_view", and "yield_if" are basically a DSL for writing (admittedly ugly) lazy list comprehensions (generator expressions in Python or for comprehensions in Scala) in C++ without special language support for them. You're not supposed to have to implement these sorts of building blocks yourself, but they're not voted into the standard either at this point.
- mattnewport 8y agoUnlike Python, this compiles to pretty optimally efficient code.
- ddavis 8y agoVery excited to be able to use both ranges and concepts soon. I started writing C++ just before the 2011 standard and it’s been fun to follow and use the improvements over the last 8 years. I can’t imagine how different the language will look (after the 2020 standard) to the eyes of veteran C++ devs. It must already feel like a completely different language.
- mark-r 8y agoYes, it does feel like a completely different language. The sample code in the article is nearly unreadable to this C++ veteran. And based on the verbosity of the result I'm not sure it's an improvement.
- a1studmuffin 8y agoI have to agree. Pumping out C++ revisions every 3 years means I can no longer assume a game written in C++ will port relatively painlessly from one C++-compatible platform to another, as it all depends on which C++ standard is supported by the platform SDK/toolset I'm forced to use.
- cjhanks 8y agoIs the C++ standards committee trying to make the language as incomprehensible to its users as possible? I cannot even begin to comprehend what assembly is going to be generated in this code sample. Are those calls indirect? Can they be vectorized? How much stack space is this going to use? What (if anything) gets put on the heap?
- saagarjha 8y agoThe C++ standard has nothing to do with these, and you won’t find a mention of them at all in the text of the standard. The standard defines an abstract virtual machine for running C++ code, and it lays out the guidelines for what compilers are allowed to do with regards to the optimizations you mentioned.
- repsilat 8y agoThis is kinda true in theory, but about as far from the truth as you can be in practice. Zero-overhead abstraction is a core part of the language's philosophy, and that means features are designed to be translated to "efficient" machine code. If nobody believed that optimising compilers could wring something decent out of these features they wouldn't have been standardised.
- saagarjha 8y agoThe abstract machine is designed to be relatively easy and efficient to implement, but specific features such as vectorization are not part of the standard. Remember, C++ runs on machines that don’t support any “advanced” features, so there is a limit to what can be required in the standard.
- cjhanks 8y agoI understand what you are saying, and I agree that it's true in principle. But, if C++ did not provide me predictable optimizations - it would be worthless to me. I know scientific computing is only one domain of computing. But without this level of intuition for code -> asm. My day becomes filled with reading objdump outputs, I don't want that.
- fourthark 8y agoCongratulations Eric! Awesome work.
- aaaaaaaaaab 8y agoWhy would anyone invest in this? I thought C++ was basically in maintenance mode given that greenfield software tends to be written in Rust...
- saagarjha 8y agoThere is at least one order of magnitude more C++ code than Rust code, and not all projects can switch over at the drop of a hat.
- hendzen 8y agoI would guess at least 3 or 4 orders of magnitude.
- TillE 8y agoThat's much more realistic. Right now if you were to guess the number of people currently employed primarily as C++ vs Rust programmers, the difference is going to be well over 100x. Not to mention the long history of C++. Rust has a very long way to go to catch up.
- war1025 8y agoC++ is extremely widely used. Especially since C++11, the language has received a ton of attention for making things more ergonomic. As projects update compilers, they are able to take advantage of these updates. C++ is anything but in maintenance mode. Rust fits in a similar niche, but it has a much smaller following. Several of it's main contributors just happen to be HN regulars, so it gets more attention than it otherwise would.
- aaaaaaaaaab 8y agoBy the amount of downvotes I got you seem to be right. I was genuinely under the impression that C/C++ was being progressively phased out in favor of Rust, but looks like this is hardly the case. I guess I should probably peek outside the HN filter bubble more often...
- alacombe 8y agoHaving switched away from C++, I've got the feeling that this kind of code: inline constexpr auto for_each = []<Range R, Iterator I = iterator_t<R>, IndirectUnaryInvocable<I> Fun>(R&& r, Fun fun) requires Range<indirect_result_t<Fun, I>> { return std::forward<R>(r) | view::transform(std::move(fun)) | view::join; }; is a sort of magical incantation you spend 3 days to tweak, it essentially just works, but becomes un-understandable within 2 weeks (even from the author), un-reviewable and code that everybody is afraid to touch (or even get close to) ? Don't get me wrong, there is definitively a lot of flexibility I'm missing from C++, even the problem can be addressed otherwise with other language, but things can get very, if not utterly... convoluted.
- htfy96 8y agoThis should be a library function that will not be exposed directly to most developers, who only need to know for_each(Range, fun) which is pretty straightforward.
- alacombe 8y agopeople will end up using that... A former colleague spent a week simplifiying a 10 lines templates to use C++14's std::integer_sequence, nobody could review his code. Doesn't really matter at the end. I'm fairly certain the code in question was canned later on by more "old school" devs...
- DoofusOfDeath 8y agoI've heard that line of reasoning before, and it doesn't make sense to me. Specifically, I find it alarming that it assumes two tiers of competent c++ developers: a lower tier that just uses libraries, and a higher tier that can write good libraries. I see two problems with this view. First, in my experience most large codebases are structured as many layes of libraries. So the envisioned non-library developer may be in the minority. Second, it's a red flag that the language's complexity dangerously high. If nothing else, one of the envisioned non-library developers may unwittingly write code that uses or misuses these features, and still need to debug incomprehensible compilation- or runtime-errors.
- Sharlin 8y agoAt first I wondered why he calls the monadic flatmap operation "for_each" but it makes sense in that he's actually creating a (lazy) list comprehension DSL here. The code within main() is mostly equivalent to the following Python code: triples = ((a, b, c) for c in itertools.count() for a in range(1, c+1) for b in range(a, c+1) if a*a + b*b == c*c) for (a,b,c) in itertools.islice(triples, 10): print("{}, {}, {}".format(a,b,c)) The equivalent in Rust, just because I'm currently learning it: let triples = (1..) .flat_map(move |c| (1..=c) .flat_map(move |a| (a..=c) .flat_map(move |b| Some((a, b, c)) .filter(|_| a*a + b*b == c*c)))); for (a,b,c) in triples.take(10) { println!("{}, {}, {}", a, b, c) }
- blub 8y agoI was anyway thinking that his example looked incomprehensible, but your Python example makes a complete mockery of it. The difference is night and day, I'm dismayed at how horrible that C++ code is, hope I never have to deal with such crap.
- Sharlin 8y agoThe big difference is that it's a pure library solution in C++. The code inside main is not too bad once you have the building blocks in place (implemented in a library, of course, not by yourself).
- mehrdadn 8y ago> but your Python example makes a complete mockery of it. I mean, try getting the same kind of performance and static verification in Python? So much of the complexity of C++ is due to the static typing and the optimizations that can come with it. If you're willing to give up and make everything dynamic then of course it'll simplify your code, but you get a massive penalty both in terms of performance and in terms of error-checking.
- Sharlin 8y ago
- Aardwolf 8y agoIn current C++, lots of std functions are annoying because you need to give both .begin() and .end(), while in 99% of the cases when using a C++ container you want to do your algorithm on the whole container (a function with 2 parameters is good to have for the other 1% of cases and the case of 2 pointers of course). What took so long and why are "ranges" needed for that? Most other languages have sort, transform, ... with a single parameter (such as a container or array), and those don't require something called "ranges" for that. Why couldn't C++ at least already have long had convenience functions that just take a container and do the .begin() and .end() for you? I'm all for having "std::transform" and stuff, but if it requires you to type just as much as writing it manually with a for loop due to having to type the name/expression of your container twice, what's the point. EDIT: oh, and it's going to be std::ranges::sort(v) instead of just std::sort(v)? What's wrong with naming it just std::sort(v)? Do C++ users really need to be reminded it took a "ranges" concept just to sort a simple container every single time they'll use it?
- repsilat 8y agoI agree. The "flexibility" of being able to operate on a subset of the container was never a good argument, because you could trivially make a "view"/slice template type to fake begin/end to any pair of iterators. Make the common case short and the uncommon case possible.
- saagarjha 8y agoRanges unify C arrays and C++ standard library types in a rather elegant, general purpose way. Though, I’m still of the opinion that every function that takes a range should also be overloaded to operate on the whole container as well (and my personal C++ “library” does this already).
- int_19h 8y ago> because you could trivially make a "view"/slice template type to fake begin/end to any pair of iterators. In C++, that was not trivial at all. Implementing a custom container with iterators (which you'd have to do for this - you can't just propagate iterators as is) is very verbose, since there's no syntactic sugar for it, like say generator functions in Python.
- rsp1984 8y agoI know I'm not going to make a lot of friends with this opinion, but this is a perfect example of everything that's wrong with modern C++. Seriously who, except for a small circle of academics, actually believes that this is good, readable, concise, maintainable code? Who asked for this? When I read inline constexpr auto for_each = []< Range R, Iterator I = iterator_t<R>, IndirectUnaryInvocable<I> Fun>(R&& r, Fun fun) requires Range<indirect_result_t<Fun, I>> { return std::forward<R>(r) | view::transform(std::move(fun)) | view::join; }; I can't help but being reminded of Java [1][2]. Meanwhile it's 2019 and C++ coders are still - Waiting for Cross-Platform standardized SIMD vector datatypes - Using nonstandard extensions, libraries or home-baked solutions to run computations in parallel on many cores or on different processors than the CPU - Debugging cross-platform code using couts, cerrs and printfs - Forced to use boost for even quite elementary operations on std::strings. Yes, some of these things are hard to fix and require collaboration among real people and real companies. And yes, it's a lot easier to bury your head in the soft academic sand and come up with some new interesting toy feature. It's like the committee has given up. Started coding C++ when I was 14 -- 20 years ago. [1] https://docs.spring.io/spring/docs/2.5.x/javadoc-api/org/springframework/aop/framework/AbstractSingletonProxyFactoryBean.html https://docs.spring.io/spring/docs/2.5.x/javadoc-api/org/spr... [2] http://projects.haykranen.nl/java/ http://projects.haykranen.nl/java/
- deleted 8y ago[deleted]
- stefan_ 8y agoThis has been the story with C++ forever. I think currently half the standardization and compiler implementation bandwidth is taken up by turning C++ into the slowest virtual machine ever devised (constexpr). The constexpr story is presumably very similar to what happened with templates. There was a genuine niche use case, and that was perfectly covered in the initial implementation. But the feature just lends itself perfectly to extremely clever, single A4 page example code. No one ever went "ooh" and "aah" at a basic_string::split paper.
- dman 8y agoThis looks like something a library author would write while implementing a range and not something that end users would write while using ranges. Could you point to an implementation in a different language that offers a similar abstraction in a more succinct manner (While offering the same type safety and low runtime overhead).
- slavik81 8y agoHow does one try out these work in progress features? I tried compiling the example on godbolt.org with gcc-trunk and wasn't sure how to get it working. https://godbolt.org/z/YSPXLu https://godbolt.org/z/YSPXLu
- azinman2 8y agoI feel like it should be called c::
- utopcell 8y agoSyntax should be dead-simple so that correctness is obvious, compilers don't dump incomprehensible messages on trivial typos, and programmers can focus on efficiency. For example, in something as simple as: int z; while(++z) for(int x = 1; x <= z; ++x) for(int y = x; y <= z; ++y) if(x*x + y*y == z*z) emit_triple(x, y, z); a programmer would easily spot that x and y should never reach z, y should be initialized to x+1 and that this will stop working as soon as z outgrows 16-bit values. A programmer would also see that this is a horribly inefficient algorithm.
- CamperBob2 8y agoAlso, an electric shock should be emitted via the USB port whenever the compiler detects that a programmer has written 'for', 'if', and 'while' without a space, making them difficult to distinguish at a glance from function calls.
- AnimalMuppet 8y agoFunction calls can be written with spaces, too...
- mark-r 8y agoMay you burn in hell forever if you code your for/if/while without spaces and your function calls with spaces... Remember that a compiler is not the only entity reading your code, other humans have to read it too. Have pity on them, they're not as flexible as your compiler.
- utopcell 8y agoAnd let us not forget the blasphemy of bracketless blocks of code. Or uninitialized variables.
- tom_ 8y agoI'd been working for probably about 5 years before a colleague moaned at me for not doing this - and that is how I discovered that it was a thing people did. I looked again at the code, and... well, what do you know. About 75% of my colleagues did it too! I'd never noticed.
- countryqt30 8y agoWhere do all these C++19 / C++20 standard "improvements" REALLY add value, instead of making everything more complex and convoluted? Is it just slightly different syntax for doing exactly the same? ... get<0>(triple)
- GnarfGnarf 8y agoI've been writing C++ since 1995, and programming since 1965. I'm sorry but this stuff is incomprehensible, opaque and cryptic. I don't see how it improves productivity and maintainability. Although I do find the STL very productive.
- ModernMech 8y agoThank God I'm not the only one. I looked at this and my eyes glazed over.
- stinos 8y agoI don't see how it improves productivity and maintainability I find that quite hard to believe for someone with admittedly a lot of experience. I mean, just look at the most basic example: func(vec.begin(), vec.end()) becomes func(vec) Do you really not see that can have advantages when it comes to productivity and maintainability?
- lenkite 8y agoI think every HR reader just skimmed this article, saw that for_each example and exploded in fury. He does say the below: "I’m being a bit pedantic for didactic purposes here, so please don’t let that trip you up.I also could have very easily written for_each as a vanilla function template instead of making it an object initialized with a constrained generic lambda." He needs to clean up the article and write another which doesn't 'play around' syntax quite so much.
- pjmlp 8y agoIt is C++, so it is going to be bashed not matter what, regardless that many languages of similar age have their own set of quirks and breaking changes even across minor versions.
- MichaelMoser123 8y agomy biggest concern is that Scott Meyers will not be around to explain all the new revelations (like concepts) to us mere mortals - he says he was done with C++.
- laythea 8y agoI think the C++ committee has gone a step or few too far. This code is horribly ugly.