35 ms·
C++23: The Next C++ Standard
- synergy20 3y agoHopefully clang++ can catch up to the new standard faster as clangd the LSP is used in so many intellisense tools that depends on clang++ implementation. Even though c++23 will be compiling fine with newest g++, clangd will still complain all those new syntax probably for a few years ahead, at the moment quite a few c++20 features are still unsupported by clangd(which depends on clang++). or, gcc can have its own c/c++ LSP, which is not the case.
- IAmLiterallyAB 3y agoHoping compilers will get their C++20 modules implementation working well enough that we'll get C++23 standard library modules soon. As an outside observer, it seems like progress is happening in spurts, but it feels kinda slow.
- pjmlp 3y agoYes, VC++ is still the only usable one.
- badpun 3y agoLast time I checked (which was roughly a year ago), even a toy project with modules slowed down IntelliSense to the point of it being unusable and having to be disabled. Do you know if it's better now?
- pjmlp 3y agoIt isn't perfect, but yes it has improved. I have a couple of C++ hobby projects on github, all done with modules nowadays.
- dataflow 3y agoDeducing this seems like a drastic change to the language, not a minor incremental one. People will be doing CRTP with it without realizing or fully appreciating the consequences now.
- quotemstr 3y agoIf they do, there's no harm done. The new this inference stuff is just a brevity enhancement, yes? You have to understand that it's a Sisyphean struggle to get people to use modern C++ features at all. You still see people passing around std::string instances by value and manually calling new and delete. They're ignorant of variants and think "final" is an advanced feature. I'm happy if they get as far as understanding even how to use CRTP. There's a vast gulf in skill between the expert C++ practitioner who appreciates a blog post like the one linked and one who's been dragooned without training into writing some enterprise C++ thing. The latter relates to C++ as an inscrutable Lovecraftian god who might eat him slightly later if he makes the right cultist noises and does the right syntax dance.
- jeremyjh 3y agoProbably thats also partly because they are being dumped into a large sprawling codebase already full of C++98 idioms. Even if you point them to the "newer sections" that are more modern, they will fall back to what they are working with all the time.
- dataflow 3y agoI wouldn't call it harmless. The feature might just be brevity enhancement for CRTP (and I think it's incredibly well-designed for that), but the advertisement/education around it usually just mentions constness-agnosticism and code deduplication as the use cases, which are precisely the wrong cases for deducing this. CRTP was never the solution for those and that hasn't changed with the syntax -- because both of these have effects on code semantics, not just syntax. But I will bet most people using it will use it for those purposes, rather than as a briefer syntax for when they would've otherwise used CRTP. It feels a lot like the push_back -> emplace_back thing, where the feature has important use cases, but plenty of people will use it merely because they're mistaught that it's the "modern way" to do things without being told it's a footgun that bypasses existing safety features in the language, and it becomes impossible to hold back the flood. And they get away with it the majority of the time, but every now and then they end up introducing subtle bugs that are painful to debug. But hey it's the shiny modern hammer, so obviously you can't just let it sit there. People can't just see a modern hammer and let you watch it sit there until you actually need it. You have to use it (and people will tell you to use it during code reviews) or everyone will look down on you for being so old-fashioned and anti-"progress".
- afavour 3y agoI've always been aware of C++ (obviously!) but it seemed impenetrable to me coming from my experience with C# and JavaScript. So I was really pleasantly surprised when I tried it out a while ago using the C++20 standard: it felt entirely usable! But then I tried Rust, which felt like that plus a pile of even better stuff. It's been difficult to find a reason to go back since but I'm glad to see even more progress is being made.
- snitty 3y agoI learned C++ in the late 90s and didn't touch it until recently and all the new stuff basically melted my brain. It feels like a different language now.
- afavour 3y agoAs someone who learned JavaScript in the late 90s I feel the same way sometimes! If I'd gone away from the ecosystem and returned recently I think it would feel extremely alien.
- gumby 3y agoIndeed. I was working in/on C++ back in the late 80s and the 90s and I decided a few years ago to do a project with it. I took the approach of learning it as a brand new language that I knew nothing about, and especially avoiding thinking about what I already knew about C++ and especially C. The result was a language that yes, is a pleasure to work in. Of course some context could not be ignored: there are about six ways to do many things because of back compatibility. But that back compatibility is why so many people use it. I write in one style, and just know the others for reading other people's code.
- zwieback 3y agoYeah, that's me, I used C++ professionally throughout the 90s and early 2000s, then switched to C# (and C for embedded). Unfortunately, the C++ code bases I work with are equally old so I also have to look for a brand-new project to re-learn modern C++.
- colatkinson 3y agostd::expected and a monadic interface for std::optional are very welcome changes. I've ended up with funky utility types to accomplish much the same thing in a couple projects, so an official interface is definitely nifty. I remember reading that clang was finally shipping std as a module, albeit experimentally. So this ought to be an interesting couple of years for C++ -- though I suppose it remains to be seen to what degree the ecosystem will keep up with all these changes vs using headers/exceptions/the traditional ways of doing things.
- jupp0r 3y agoFrom past experiences, it will take another decade or two for modules to get adapted to most existing code bases.
- deleted 3y ago[deleted]
- jonathankoren 3y agoGenuinely surprised and confused by “print” and “println”
- CoastalCoder 3y ago> Genuinely surprised and confused by “print” and “println” I was too. Looking at [0], I'm guessing it's meant to bring these benefits over old-school "printf": - Leverages the type system to avoid mismatches between the format string and the arguments. - Adds Python- / Rust-style support for position-based substitutions, e.g. "{1}". - Like Rust (I think; I'm still learning Rust) you can specify per-type formatters. But I'm still confused about: - How this relates to the standard library's iostream system. It seems pretty redundant. - Why "println" exists. [0] https://en.cppreference.com/w/cpp/io/print https://en.cppreference.com/w/cpp/io/print
- dxuh 3y agoiostreams are horrible to use, especially if you want to format your output and they blow up compilation to a mythical degree. People go to great lengths to avoid them and I agree with them. print/println are based on the fmt library (https://github.com/fmtlib/fmt https://github.com/fmtlib/fmt), which had it's first release in 2015, so it's roughly as old as Rust afaik. It's mainly inspired by Python formatting. Having per-type formatters is just a logical conclusion of having type-safe formatting. iostreams are for all kinds of io (which includes stdin/stdout), while fmt is entirely dedicated to formatting strings. Those things are related, but not the same. cout and cerr and such will probably be entirely superseeded by print/println (I hope), but it doesn't make iostreams generally redundant. println adds a newline and you want to be able to choose, so there is print and println.
- Karliss 3y agoMost of those benefits apply to std::format which was already introduced in c++20. But formatting a string you will often want to output it somewhere. You could do `std::cerr << std::format(....)`, but that just invites weird mixes of std::format and iostream based formatting. I look at print/println as partially just convenience function combing the existing std::format functionality with outputing to something. Not sure if standard permits it but print could also allow skipping some temporary heap allocated std::string which the std::format returns by directly writing to the output stream buffer. In C++20 if you wanted to print using std::format style formating (or it's variant) your options where: ``` std::cout << std::format("{}{}", arg1, arg2);// not the best syntax but less bad than everything else, slightly inefficient due to temp string std::string tmp = std::format("{} {}", arg1, arg2); fwrite(stdout, tmp.c_str(), tmp.length()); // more ugly, and still uses temporary string std::format_to(std::ostream_iterator<char>(std::cout), "{} {}", arg1, arg2); // avoids temp string, but what kind of monstrosity is this ``` But doesn't the std::format style formatting make the formatting part of ostream redundant -> it somewhat does. I guess that's why there are 3 types of print overloads: * accepting ostream as first argument * accepting c style "FILE*" as first output argument * no output stream argument, implicitly outputting to stdout One potential consideration to use ostream based versions instead of FILE* ones even though the formatting part is somewhat redundant, is RAII based resource management. If you want to use FILE* based versions, it means that you have to either remember manually close the File* handle which just like manual new/delete or malloc/free calls is something modern C++ tries to move away, or you have to create your own RAII wrappers around c style FILE* handles. An alternative would have been introducing new kind of output stream API which only concerns with outputing buffered stream of bytes and skips the formatting part of ostream, but that would have introduced different kind of redundancy -> having 3 kinds of API for opening and writing to file. Allowing to pass ostream to print, while discouraging use of << operator parts of it seems like a simpler solution. One more concern is how using the version of print which outputs to stdout without taking output File or ostream handle interacts with any buffering done by previous printf,and std::cout APIs and also synchronization with input streams. The same problem already existed before for interactions between printf and std::cout. For the most part if you don't mix them it doesn't matter too much, but if you care the standard defines how exactly they are synchronized. The new print probably either adds third case to this or is defined as being equivalent to one of the previous two. After looking reading docs a bit more, seems like std::basic_streambuf/std::file_buf did exist. The new print API, might have used that as abstraction around output streams without some of the ostream formatting baggage. I have only seen them mentioned as implementation details of ostream stuff, never seen anyone use them directly. There was also std::format_to in c++20 which avoid the temporary string std::format returns. I guess they could have extended that with additional overloads so that it can function more similar to std::print. But if they need to define new functions might as well call them something more familar to people coming from other languages like print, instead of having format_to(stdout, "formatstring", arg1, arg2);. Currently std::format_to outputs to output iterator. So to sumarize why print exists: - combine std::format introduced by C++20 with outputting somewhere with cleaner syntax compared to doing it manually. - sane looking hello world for beginner and people coming from other programming languages, this is probably also why println exists - (maybe) avoid some heap allocations that temporary string returned by std::format would cause. - avoid confusion of mixing two formatting approaches that `std::cout<<std::format()` implies - avoid C style manual resource management that would be required for doing `File\* f=fopen("");auto tmp=std::format();write(f, tmp.c_str())`
- CoastalCoder 3y agoI'm glad for this article. C++ has been my main language for a very long time, but I've been a grumpy skeptic of C++ since around C++14 due to the language spec's total complexity. So I've mostly stuck with C++11. But now that C++ has modules, concepts, etc., I'm starting to wonder if C++23 is worthwhile for new projects. I.e., the language-spec complexity is still there, but the new features might tip the balance. I'd been thinking to walk away from C++ in favor of Rust for new projects. But now I might give C++23 a chance to prove itself.
- ajross 3y agoReally the cognitive load of modern Rust is no less than C++$RECENT in my experience. Both require a ton of prima-facie concepts before you can productively read code from other developers. Of en vogue languages, Zig is the only one that seems to view keeping the "metaphor flood" under control as a design goal, we'll see how things evolve. But really, and I say this from the perspective of someone in the embedded world who still does most of his serious work in C and cares about code generation and linkage: I think the whole concept of these Extremely Heavy Systems Programming Languages is not long for this world. In modern systems, managed runtimes a-la Go/Swift/JVM/.NET and glue via crufty type-light environments like Python and Javascript are absolutely where the world has ended up. And I increasingly get the feeling that those of us left arguing over which monstrosity to use in our shrinking domain are... kinda becoming the joke.
- pjmlp 3y agoActually if you look back to 8 and 16 bit home computers, with C, C++, Object Pascal, BASIC, Modula-2, full of inline Assembly, in many cases that being the biggest code surface, it is quite similar. Nowadays C and C++ took the role of that inline Assembly, with higher level systems languages taking over the role of the former.
- ajross 3y agoSure. The point was more that Big System Engineering (in any particular domain, frankly including things like OS kernels), going forward, just won't be happening much in Rust or C++. And languages that large make for very poor "inline assembly", where C obviously does quite well and Zig seems to have a reasonable shot. I mean, literally yesterday I had to stop and write a "device driver" (an MMIO firmware loader for an on board microcontroller) in Python by mapping /dev/mem. That's the kind of interface and development metaphor we'll be seeing in the longer term: kernel driver and interface responsibilities will shrink (they are already) in favor of component design done in pedestrian languages like Go or whatever that mere mortals will understand. There's no market for a big C++ or Rust kernel framework.
- enriquto 3y ago#include <print> int main() { std::print("hello, world!\n"); return 0; } So, it has come to this. Much better than overloading bit-shift operators for input/output.
- fractalb 3y agoTime to rewrite helloworld programs. IIRC, Java is also making it simpler to a helloworld program.
- thibran 3y agoWhere is the std:: part coming from / why is it not just print(...)?
- goalieca 3y agoHundreds of not thousands of people made their own print over the years. Namespacing is important.
- aodonnell2536 3y agoThe function is part of the std namespace, just like std::cout.
- tialaramex 3y agoC++ has namespacing which makes sense because this language has an enormous amount of available 3rd party libraries and without name spacing you can't help stepping on each others toes. There are two ways you might want to have this work anyway despite namespacing. One option would be that you just import the namespace and get all the stuff in it, this is popular in Java for example, however in C++ this is a bit fraught because while you can import a namespace, you actually get everything from that namespace and all containing namespaces. Because the C++ standard library defines a huge variety of symbols, if you do this you get almost all of those symbols. Most words you might think of are in fact standard library symbols in C++, std::end, std::move, std::array, and so on. So if you imported all these symbols into your namespace it's easy to accidentally trip yourself, thus it's usual not to do so at all. Another option would be to have some magic that introduces certain commonly used features, Rust's preludes do this, both generally (having namespaces for the explicit purpose of exporting names you'd often want together) and specifically ("the" standard library prelude for your Edition is automatically injected into all your Rust software by default). C++ could in principle do something like this but it does not.
- nvy 3y agoFor people who are proficient in other languages but haven't touched C++ since CS036 in undergrad, some 15+ years ago, what would be the best way to learn what "modern C++", both the code and the dev stack, looks like? Asking for a friend.
- htfy96 3y agoA Tour of C++ for syntax, https://www.cpp-lang.net/tools/ https://www.cpp-lang.net/tools/ for dev tools
- mauvia 3y agoI don't really learn stuff in a structured way so this might not be helpful at all, but a youtube walk got me into watching CPPCon talks (https://www.youtube.com/@CppCon https://www.youtube.com/@CppCon) and I found them generally useful for getting an idea of what's going on in C++ and what all the magic words to research are. When a bunch of people talk about weird gibberish like SFINAE it becomes easy to figure out it's something you should search for on wikipedia (https://en.wikipedia.org/wiki/SFINAE https://en.wikipedia.org/wiki/SFINAE). note: SFINAE is simply a way to make overloading work better by failing gracefully if an overload fails to compile. There's a series of talks called Back to Basics that seems to have quite a few talks every year where they discuss C++ features in general like move semantics or how testing works, etc. There have also been talks from the creators of CMake or the guys working on the recently added ranges proposal, so it does cover tooling as well. I also quite enjoy following Jason Turner's C++ weekly series (https://www.youtube.com/@cppweekly https://www.youtube.com/@cppweekly) which also has quite a few episodes that are dedicated to new C++ features or new ways of handling old problems made available by the new features. They're generally quite short, each episode on average is 12 minutes. Just looking down the list of videos I see this is also kind of a direct response to your question, from only 8 months ago. https://youtu.be/VpqwCDSfgz0 https://youtu.be/VpqwCDSfgz0 [ C++ Weekly - Ep 348 - A Modern C++ Quick Start Tutorial - 90 Topics in 20 Minutes ] For experimenting: https://gcc.godbolt.org/ https://gcc.godbolt.org/ is a tool called compiler explorer, which is a really good place to experiment with toy code. It's a site where you can write some code and let it execute, to see the results, as well as see what ASM it compiles down to for various compilers. That last feature really helped me figure out whether the compiler really does pick up an optimisation I'm trying out. (and it's how I got really impressed by how powerful constexpr is (that's one of the new keywords)) For References: Generally the https://en.cppreference.com https://en.cppreference.com site is a really well maintained wiki that has good explanations of every concept and standard library feature. It sticks to the standard and has use examples and is heavily interlinked, as well as some concept pages to give an overview of certain topics like overloading, templates, etc. (they also have a SFINAE article https://en.cppreference.com/w/cpp/language/sfinae https://en.cppreference.com/w/cpp/language/sfinae)
- soulbadguy 3y agoReally excited about the deducing this features. Fun template kung-fu'ing ahead.
- bhouston 3y agoDoes C++ yet have something similar to async/await? I have a medium sized JavaScript codebase that uses this (http://github.com/bhouston/behave-graph http://github.com/bhouston/behave-graph) and I could really use a port to C++ so that it can be integrated with the USD project, who has expressed interest. I couldn't find an equivalent to async/await in my searches so I am fearful that porting this across to C++ is non-trivial.
- __jem 3y agohttps://en.cppreference.com/w/cpp/language/coroutines https://en.cppreference.com/w/cpp/language/coroutines But highly doubt you need anything like async/await for this kind of application. In fact, I'd go as far as to say async/await is almost never needed except for building networked services with truly massive performance demands.
- Kranar 3y agoIf you genuinely have massive performance demands, stay far away from coroutines. For whatever reason the approach C++ took makes them incredibly memory hungry and inefficient.
- jupp0r 3y agoThis is FUD. Watch https://www.youtube.com/watch?v=j9tlJAqMV7U https://www.youtube.com/watch?v=j9tlJAqMV7U.
- lionkor 3y agoYou can look into asio or boost::asio (same thing more or less). These libraries add pretty good async behavior. Of course, you need to know a lot of C++ to understand and use them properly, and they're very verbose. If you need to do things in parallel for performance, you may be better off spinning up a threadpool (like asio's thread_pool) and using a threadsafe queue or similar (i.e. asio's asio::post()) to pass messages and get results. Since you can do it with JS, you likely don't have massive perf requirements, and you just need to write it in simple, synchronous C++ and you may find it to be well fast enough. We also have coroutines, they're async/await. Haven't tried them though.
- gerash 3y agoI'm excited for more usability coming to C++. It's still far from the writability of Python. At the same time the Mojo language is going the other way: creating a system language out of Python.
- deleted 3y ago[deleted]
- optimalsolver 3y agoJust happy to have std::format. Can't believe I used to use a third-party library ({fmt}) to do string interpolation like some kind of caveman.
- whobre 3y agoStill at c++ 98, but it’s always nice to see what other people have…
- r2vcap 3y agos/absl::AnyCallable/std::move_only_function/
- Brystephor 3y agoWhat are some personal projects you'd use C++ for? I have a hard time imagining any use cases for myself where it makes sense to use C++ over another language. As someone who has never used c++, it seems like it's primarily useful when latency and performance really matters and the cost of that is ease of use when it comes to developer quality of life/productivity.
- okanat 3y agoWhen creating things where such things matter or you need lower level access to the platform since there is a tight connection between the C and C++ compilers and the platform they (were) built. I'd like to play with many gadgets, small embedded toys. Let's say it is custom a USB mouse. You may want to create a data structre that 1-1 represents whatever data you're pushing to the wire and the exact amount of time it takes you to push it over the wire. C++ lets me abstract things better than C. There is a level of control in C++ where you get the decide to the minute detail how the compiler builds your software. With a C++ compiler you can say to the compiler to optimize one function, while not the other one in the same source file. Yes, the standard language abstracts the underlying machine and it will suprise you since compilers obey it very well if you not tell them otherwise. But all of the C++ compilers, including the niche ones, also let you pierce through those abstractions by special attributes and linker directives. So you can have an almost assembly code next to very abstracted and crazy optimized code. C++ doesn't care how you build software, it is up to you to decide which kind of libraries, which libraries, what subarchitecture, what optimization level to use for each library. These sound crazy but current literature and internet is full of detailed documentation how to do these things since somebody at some point needed to do them to debug a particle accelerator or the latest PCIe bus or something and it is somehow useful for your stupid USB mouse. Rust as the language (syntax, rules) is better. Rust articulates better, it makes a lot of sense. However to appeal the newcomers and people who look different sa(n/f)er ways to do things, Rust generally limits you. You need to codify certain "features", or you need build.rs files. You need to find underdocumented or "nightly" features. Whatever you come up with would be better formally defined. However going against the grain of Rust and Cargo creates abominations.
- lionkor 3y ago