C++ Club - Meeting #130

Episode Date: June 6, 2021

http://cppclub.uk...

Transcript
Discussion (0)
Starting point is 00:00:00 Hi, my name is Gleb, I live in London and I run a C++ club at work where we discuss C++ programming news and related articles. You can find our meeting notes at cppclub.uk. This podcast and the meeting notes contain public information only. This is episode 5 for the meeting number 130 that took place on the 3rd of June 2021. Pure Virtual C++ Conference by Microsoft Microsoft has published videos of the conference talks. Of a particular interest is the talk by Gabriel Dos Reis, C++++ modules, year 2021.
Starting point is 00:00:47 After a short introduction to modules, Gabriel gives an update on the current status of modules in different compilers. MSVC modules are production-ready. GCC 11 still in experimental mode. Clang has a feature branch for module development, which is still in experimental mode. Gabriel expects GCC and Clang has a feature branch for module development which is still in experimental mode. Gabriel expects GCC and Clang modules to reach production level quality by the end of 2021 or early 2022. Build tools that support modules include MSBuild production quality and experimental support is available in CMake, Build2 and Mison.
Starting point is 00:01:28 He mentions the following articles and modules in MSVC. A tour of C++ modules in Visual Studio. Walkthrough Build and Import Header Units in Microsoft Visual C++. Walkthrough Import STLL libraries as header units. He also lists the following talks on modules and how to use them. Gabriel Dos Reis. Programming with C++ modules.
Starting point is 00:01:57 Guide for the working programmer. Daniela Engert. Visibility, reachability, linkage. The three spices of C++ modules. Boris Kolpachkov, practical C++ modules. Gabriel Dos Reis, programming in the large with C++20. This was a meeting C++ 2020 keynote. I found this one to be very detail-heavy on module interface file IFC structure and implementation, which could be useful for tool developers, but perhaps not so
Starting point is 00:02:35 much for the ordinary programmer who wants to use modules. As an aside, Gabriel used a concept to prevent implicit conversion in a function. There was a function template, which went like this. template angle brackets std colon colon same as
Starting point is 00:02:57 angle brackets uint32 underscore t angle brackets i, which is the template parameter name. , void foo, open parenthesis, i, index,
Starting point is 00:03:13 close parenthesis, and then the function body. This means that the parameter index must be exactly of type uint32 underscore t, and not any other type implicitly convertible to uint32-t. Gabriel talks about the new opportunities for tooling enabled by the new semantic representation of the code provided by module interface build artifacts. He mentions his disappointment at the lack of common representation of the module interface across compilers, and his hope for an eventual convergence onto a common format. The binary representation IFC that MSVC uses for modules is based on the open-source internal program representation IPR
Starting point is 00:04:03 developed by Gabi and Bjarne Stroustrup 15 years ago. One thing that came up in the Q&A session after the meeting C++ 2020 keynote was the fact that the IFC files are compiler setting specific, but I don't remember any mentions of compiler flags being stored in IFC. I'm curious if Compilers and Tools will be able to check if an AFC file was built with compatible compiler flags. Modules present an opportunity to replace the commonly used interface with other languages, which is currently Xtern C, with something better. This is of a particular interest to me, as I use SWIG to interface with Java.
Starting point is 00:04:50 SWIG stands for Simplified Wrapper Interface Generator. And if you have something called simple, it is never that. Case in point, SOAP. I would really like to replace SWIG with something modern. Another interesting thing said in the Q&A session was the future possibility of embedding IFC in DLLs. This would provide tools with runtime introspection capability, much like.NET languages have today.
Starting point is 00:05:18 At the end of the talk, Gabriel asks all the interested developers to go and try using modules with all the compilers and build tools, and provide feedback to WG21 and tool developers. Visibility-reachability linkage, the three spices of C++ modules. A talk by Daniela Engert. Daniela has been building software since the late 1970s. She says, Folks, I just think we are doing this wrong now.
Starting point is 00:05:50 We follow the book of John. I mean John Lakers' book about layering software and designing large systems. End quote. She explains the drawbacks of the current header-based compilation model. Macros, ODR violations, and says that modules allow us to shift the library protection boundary from the current position between library interface and implementation to the more natural position between library as a whole and its consuming translation unit. Quote, this is the way, end quote.
Starting point is 00:06:27 A nice call-out to the Mandalorian there. Daniela goes through C++ name lookup rules and explains how modules allow better control of name visibility across translation units by using the export qualifier. She also explains the various types of linkage and how modules affect the picture. This is a good detailed talk worth your attention. Modules in managed C++ After the Meeting C++ 2020 keynote, someone asked Gabi if modules were supported in managed C++ or C++ slash CLI. He said no work has been done in that area.
Starting point is 00:07:10 Module support in MSVC requires std colon C++ latest switch, which requires MSVC standards compliant mode slash permissive minus This switch enables two-phase lookup, which is not supported with managed C++. I tried using modules in the Hello World app in Visual Studio 2019. I created a new Win32 console project that included iostream and wrote Hello World to std cout. This is a boilerplate generated by Visual Studio when you create a project like that. It has an include statement which includes iostream and then int main without parameters in which there is one line std cout stream out hello world and that's it. Then I went to project settings c++
Starting point is 00:08:09 language and set the following options. C++ language standard. I set it to preview features from the latest c++ working draft. The switch slashd colon C++ latest Enable experimental C++ standard library modules I set it to Yes and the corresponding switch is slash experimental colon module Note that this requires that you select the standard library modules component during Visual Studio installation. After that I replaced the include statement with import.
Starting point is 00:08:49 Now the first line reads import std.core. I left the rest alone, and when I did all that, in the currently available Visual Studio 2019 version 16.9.2, which was the currently available version at the time of writing. The program built and ran successfully. I didn't have to manually tweak the system module paths like in earlier versions. However, IntelliSense didn't seem to know about modules, the import keyword was highlighted red and stdcout appeared as an unknown symbol. When I did the above in the latest 2019 version 16.10 preview 4, everything worked including IntelliSense which didn't flag any errors. Gagneris. Just as I was writing this, Visual Studio 2019 16.10 was released. The main news was that all C++20 features were now available under the std colon C++ latest switch. It's the first compiler to be fully C++ 20 compliant.
Starting point is 00:10:06 A Redditor writes I love that every single time they put in release notes that they repaired IntelliSense for C++ 20 modules. Then I write a single hello world program and IntelliSense fails. End quote.
Starting point is 00:10:22 In my experience with a hello world program, IntelliSense in the new version seems to work, as opposed to the previous release, but I haven't used modules properly yet. Also, Visual Studio 2019 16.11 Preview 1 was released at the same time. You can visit the announcement page to see lots of pretty screenshots, lots of improvements in Git support, but I'm probably not going to use them as I prefer Git command line. Most Git tools hide the crucial details from you and then you end up with some weird history or a tragic merge you can't get out of. I gave it a go, and IntelliSense works well with modules.
Starting point is 00:11:08 I also tried importing Iostream as a header unit instead of stdcore into my Hello World program. And IntelliSense didn't flag any errors, however, the build failed because the compiler couldn't find the header unit. A quick aside about MSVC standards conformance mode compatibility. Starting with Visual Studio 2017, which corresponds to MSVC compiler
Starting point is 00:11:35 version 14.1, it is possible to opt into the standards conformance mode with the compiler switch permissive-. Quote, this option dis switch permissive-minus. Quote, this option disables permissive behaviors and sets the ZC compiler options for strict conformance. In IDE this option also makes the IntelliSense engine underline non-conforming code. This is a default mode for new projects created with Visual Studio 2017 version 15.5 and later. Quote,
Starting point is 00:12:10 Starting in Visual Studio 2019 version 16.8, the std colon C++ latest option implicitly sets the permissive minus option. It's required for C++20 module support. The conformant mode requires Windows SDK version 10.0.16299.0 or later, which corresponds to the Windows Fall Creators SDK. Codenames. Earlier SDK versions do not even compile in conformant mode. The two-phase lookup is not supported in C++ slash CLI, as I mentioned before. But also, OpenMP is not compatible with two-phase lookup until VS 2019 version 16.5. To disable two-phase lookup and leave other conformant behavior enabled,
Starting point is 00:13:07 you can use the switch ZC lowercase colon two-phase minus. WG21 May 2021 mailing is available. Here are some papers that caught my attention. Monadic operations for stdoptional. The author Cy Brand of Microsoft writes quote stdoptional is a very important vocabulary type in C++ 17 and up. Some users of it can be very verbose and would benefit from operations which allow functional composition. I propose adding map, end underscore then, and or underscore else member functions to stdoptional to support this monadic style of programming. End quote.
Starting point is 00:14:01 Imagine a set of image processing functions that return an image. To call them in sequence, you would use a series of nested function calls. For example, if your calling function were called getCuteCat, which took an image as a parameter, you would call in that function the following functions. Return addRainbow and then inside makeSmaller and then makeIceSparkle and addBowtie and cropToCat and inside all those you would have the initial image. Notice how you have to read the calls from the innermost function call outwards, which isn't very natural. If we want these functions to return an optional image or an error code, we can use std optional of image
Starting point is 00:14:57 for that. But now we have to check every call's return value so that we don't call the subsequent functions in if a call returned an error. This proposal makes it possible to change such function calls, and handles failures transparently for the entire call chain. If this was accepted, then the call would look like this. return CropToCat image .and then add bowtie..and then make eyes sparkle. And then.map make smaller. And then.map add rainbow.
Starting point is 00:15:36 This is how optional data type works in other languages. Optional in Swift and Java. Maybe in Haskell, Agda and Idris Option in Rust and Scala According to Cybrand, C++ is the only language that has an optional type without monadic API Mark all library static cast wrappers as no discard This paper by Hanna Dusikova is a great example of a small targeted proposal that makes sense and fits
Starting point is 00:16:10 on a single page. Quote. This paper proposes adding the attribute no discard to all library based cast function templates which only wrap language casts as they are meaningless without accessing the resulting value.
Starting point is 00:16:26 End quote. These templates are toInteger, forward, move, moveIfNoExcept, as const, toUnderlying, identity, and bitcast. HANA notes that Microsoft STL already marks these as no discard. Next paper was Pattern Matching with Exception Handling. The N plus 1 monster strikes again. This time it's about using the proposed pattern matching feature with exceptions. The author, Jared Waterloo, proposes to allow the inspect statement
Starting point is 00:17:06 to catch exceptions without having to use try-catch. This way, if a function returns a and throws b and c, the cases of the inspect statement for the function call would be able to match a, b and c in a uniform way. Reddit points out many flaws in this proposal. What happens if the inspected function returns A or variant of A and B, and also throws A? Compared with exception handling,
Starting point is 00:17:37 which you can and often should avoid doing for a single function call, the proposal adds quite a lot of error-checking machinery at call site. Some corner cases could also lead to hard-to-find bugs. As the Redditor Grassicot notes, imagine a function returning variant of a, b, and c being called using the new inspect statement that has the three cases. If the function signature changes to return variant of A and B, the inspect statement still compiles, but now the case C is silently a catch. If you had an enclosing catch C at a higher level,
Starting point is 00:18:14 it won't catch it anymore. The paper seems to miss quite a few important use cases, and it's not clear if the proposed feature actually improves anything, while introducing many potential breaks and subtle hard-to-find bugs. C++ has a Wikipedia page dedicated to criticisms of it. The first comment on the Reddit thread summarizes it nicely with a Bjarne Stroustrup quote. There are only two kinds of languages, the ones people complain about and the ones nobody uses. End quote.
Starting point is 00:18:54 The article has sections on slow compile times, Iostream, well, that's fair, iterators, uniform initialization syntax, exceptions, encoding of string literals of all things, and code bloat for some old implementations of C++. Why?
Starting point is 00:19:15 It also links to some articles by authors that seem to have an irrational hate for C++. I mean, it's just a programming language, you don't have to use it. Semantics of unsigned integers. A Redditor asks, what should be the semantics of unsigned integers? As it often happens, to get the right answer, someone has to post a wrong answer. And the Redditor FullSpectral was happy to oblige. They wrote, quote, I'm one of those that doesn't agree with the always use sign
Starting point is 00:19:50 types thing. If you don't understand the magnitude of the values involved, using sign types isn't going to magically make everything better. I believe in modeling the things you're operating on, and if that can never be negative, then I don't see how using signed values is better unless you always check the result.
Starting point is 00:20:13 To that Tony Van Erd replied, People expect numbers to act like numbers. Neither signed nor unsigned really work like numbers when you are near the boundaries, but unsigned puts a boundary at zero which may very well be the most common number in all programming. So avoid using unsigned numbers for numbers. Use signed.
Starting point is 00:20:39 The committee apologizes profusely for making sizeT be unsigned. Another Redditor wrote, quote, These are some valid use cases of modular behavior of unsigned arithmetic. Hashes, random numbers, implementing multi-precision types, cryptography, emulation of hardware, end quote. And bit operations operations of course another redditor reminded what the C++
Starting point is 00:21:10 core guidelines say about this in the section yes.106 don't try to avoid negative values by using unsigned quote the C++ core guidelines also have the unsigned for bitwise, signed for arithmetic rule.
Starting point is 00:21:28 End quote. And of course someone mentioned Rust. Quote, Rust does a better job of divorcing silentness from overflow behavior and what's undefined behavior, along with avoiding the implicit integer casts and promotions that make these subtleties problematic. This is it for today, and I'll leave you with this tweet by Sarah Dresner, who describes the ideal development workflow.
Starting point is 00:22:00 Make it work. Make it right. Make it fast. Make it work again because you broke it making it fast. That's it. Thanks for joining and I'll talk to you next week. Bye.

There aren't comments yet for this episode. Click on any sentence in the transcript to leave a comment.