A
Arthur O'Dwyer
quuxplusone.github.io · Personal blog · on HN since 2018
Arthur O'Dwyer, a C++ programmer and standards participant, writes about C++ language details, compilers, interviews and text adventure history.
What HN saysHN links it for C++ technical posts, such as passing std::string_view by value, and for standards committee trip reports.
64HN people shared it
20linked it in comments
166stories submitted
6.4Kstory points
Aug 2026last shared
2018people per year · data ends Aug 20262026
Top posts on HN
- 1Slack’s new WYSIWYG input box is terrible1 people · 2.8K points · first shared 2019 · 1.1K comments on HN
- 2The best engineering interview question I've ever gotten4 people · 1.1K points · first shared 2022 · 448 comments on HN
- 3The use of `class` for things that should be simple free functions2 people · 514 points · first shared 2020 · 399 comments on HN
- 4Don’t blindly prefer emplace_back to push_back2 people · 328 points · first shared 2021 · 140 comments on HN
- 5Phrase origin: Why do we "call" functions?1 people · 305 points · first shared 2025 · 226 comments on HN
- 6Nash equilibria in Ballmer's binary-search interview game3 people · 147 points · first shared 2024 · 40 comments on HN
- 7Const all the things?1 people · 129 points · first shared 2022 · 158 comments on HN
- 8Bit Patterns of Float1 people · 103 points · first shared 2021 · 31 comments on HN
- 9What =delete means1 people · 99 points · first shared 2021 · 124 comments on HN
- 10Noexcept affects libstdc++’s unordered_set2 people · 96 points · first shared 2024 · 76 comments on HN
- 11When can the C++ compiler devirtualize a call?4 people · 4 points · first shared 2021 · discussion on HN
- 12Don’t put -Weverything in your build flags4 people · 3 points · first shared 2018 · discussion on HN
- 13Clang++ `[[trivial_abi]]` 1014 people · 3 points · first shared 2018 · discussion on HN
- 14Const Is a Contract3 people · 3 points · first shared 2020 · discussion on HN
- 15Castlequest exhumed “Lost game” Castlequest (1980) has been found4 people · 2 points · first shared 2021 · discussion on HN
- 16Reasons to pass std:string_view by value3 people · 2 points · first shared 2021 · discussion on HN
What HN people wrote when they linked it
quuxplusone · 2025-08-04
It's worth noting that you can target the Z-Machine (which gets you nice web platforms like Parchment) without using Inform as your source language. I informally maintain (I did not originally write) a C compiler for the Z-Machine, which I have used to port several games of a similar vintage: https://quuxplusone.github.io/Advent
It occurs to me that it would be nifty to make a BASIC compiler for the Z-Machine.
repsilat · 2023-09-17
Might be worth using values/copies even a bit bigger, so long as it's "simple" data. This[1] short post argues for passing `std::string_view` (~2 pointers) by value, for
- Omitting pointer indirections (loads),
- Not forcing the pointee to have an address (i.e. gotta be in memory, not just registers), and
- Eliminating aliasing questions, potentially leading to better codegen if the function isn't inlined.
1: https://quuxplusone.github.io/blog/2021/11/09/pass-string-view-by-valu…
dustfinger · 2024-03-06
> My kids are all on Linux computers
That is great to hear. My kids are both on pi 4s, but we customized the Debian distribution quite a bit to optimize its hardware acceleration capabilities and to overclock the hardware as much as possible. The pi boots from a fast nvme usb drive and i/o peripherals are connected via a fast usb hub. They are cooled by the ice tower [1]. They are both using exwm [2] and do not require a mouse. They both type on plank mechanical keyboards from olkb. All of this customization they found quite exciting. Especially being able to mess with their own keyboards.
> I'm trying to wean them off iPads and consumption devices. But it feels like addictive apps can draw them back very quickly (looking at you, YouTube).
We do not own any ipads. Only desktop computers, and I own a couple of laptops, such as the librem 14 and the mnt-reform. Youtube is a bit of a problem, I agree. They need access to it for their schooling at the moment, but the use of it does need to be limited, and the content limited as well, or they will just start watching brain numbing junk. I have decided not to block anything on our network with the goal of establishing a sense of trust, but I also don't allow them to have free rein. It is an endless exercise in finding the right balance :-). To be honest, it is much more of a problem with my son, then it is with my daughter, who spends a lot of her free time drawing and writing and isn't as entertained by youtube videos.
As for…
_huayra_ · 2021-07-16
Although I've been doing C++ for about a decade now, the one thing that is making me somewhat wary of its future is the difficulty of versioning key components of the language. Sure there are tricks with namespaces to version things to get around ABI breaks (to a degree; this is a world of problems), but fundamental features of the language are set in stone in a way that is very unfortunate.
The latest I've come across is the "R-value lifetime disaster". Arno gave a great talk at cppnow this year [0] highlighting this and Arthur O'Dwyer gave a great rebuttal / follow-up that is also worth considering [1]. The gist of it is that have const& also bind to r values (T&&) causes information about the lifetime to be thrown away. In reality, the "universal binding" ought to have been const&&, as that encodes "can't modify this thing" and "it may not live longer than this function call". This is quite a footgun, but I'm not sure if there's a way to change it with some sort of "language epochs", especially considering that this will have to be exposed in modules / headers so that different "epochs" don't try to link to or use each other's code!
[0] https://www.youtube.com/watch?v=sb7cj-3l1Kc
[1] https://quuxplusone.github.io/blog/2020/03/04/rvalue-lifetime-disaster…
pwdisswordfishy · 2025-11-21
https://quuxplusone.github.io/blog/2025/11/18/kona-trip-report/#p2786-… goes into more detail.
drysine · 2025-07-02
They can sometimes
https://quuxplusone.github.io/blog/2021/02/15/devirtualization/
gumby · 2024-04-01
You might enjoy this blog post which (after a few paragraphs) is about a programming language structured around roots similarly to how Arabic is structured: https://quuxplusone.github.io/blog/2024/03/31/ed-catmurs-triliteral/
resolutebat · 2024-03-25
That's pretty much what the original poster does in Part 2, although inevitably the actual source code is a little more complicated than that.
https://quuxplusone.github.io/blog/2022/01/07/memcached-interview-solu…
howinteresting · 2023-08-24
Do you mean the same C++ where isocpp harbored a sex predator (Arthur O'Dwyer) for years? If that's what professionalism means, then I'm proudly unprofessional and you should be as well.
https://quuxplusone.github.io/blog/
https://www.homefacts.com/offender-detail/NY49602/Arthur-Odwyer.html
CyberRabbi · 2023-04-20
> Given an optimizing compiler, the first function (count(a)) is likely to just immediately return the size of the backing vector. The function is nearly free.
The compiler is able to do that with count_inheritance() as well if it's able to prove which instance of iter_base is used in the call. I suppose even many experienced C++ developers are not aware of this. This optimization is known as "devirtualization" and is fairly well-implemented in Clang and GCC. It's even more effective since the advent of LTO. Some more info: https://quuxplusone.github.io/blog/2021/02/15/devirtualization/ https://blog.llvm.org/2017/03/devirtualization-in-llvm-and-clang.html
mikeryan · 2022-04-18
What this comes down to is can the candidate: figure out how to build the project, grep to existing implementation and copy, paste, change a plus to an asterisk. And also, can they articulate the work-to-be-done this simply.
While that’s the gist of it, it hardly seems that’s quite enough from the author’s solution, nor should it be enough for an interviewer. The question isn’t how to write, or copy paste a function but how to add the command interface as well which, if one doesn’t know memcached, can be more complex then the function itself and isn’t covered by this trite an answer.
https://quuxplusone.github.io/blog/2022/01/07/memcached-interview-solu…
130e13a · 2021-07-20
keep in mind though that -Weverything is not intended to be used in production: https://quuxplusone.github.io/blog/2018/12/06/dont-use-weverything/
SirYandi · 2021-06-30
Might be your lucky day. Just further down the thread Jabl posted:
> Recently an old text adventure game 'Castlequest' from 1980 was recovered (https://quuxplusone.github.io/blog/2021/03/09/castlequest/ ), and there are even some efforts to modernize it (https://gitlab.com/apthorpe/Castlequest).
jabl · 2021-06-30
Recently an old text adventure game 'Castlequest' from 1980 was recovered (https://quuxplusone.github.io/blog/2021/03/09/castlequest/ ), and there are even some efforts to modernize it (https://gitlab.com/apthorpe/Castlequest).
wahern · 2019-01-10
The advice to use -Weverything is very bad advice. See, e.g., https://quuxplusone.github.io/blog/2018/12/06/dont-use-weverything/
Using -Weverything other than for a one-off, manual build, is a sure fire way to result in one or several of 1) hacky code that works around some compiler author's style preferences, 2) less safe code because of the workaround hacks, or 3) coworkers quickly learning to ignore or disable (e.g. using inline #pragma's) diagnostics.
For both GCC and clang, -Wall comes close to the line of rejecting objectively correct and good code, but doesn't quite cross the line. -Wextra crosses that line (expect it to reject some correct and good code) but the pros often outweigh the cons. -Weverything blows past the line and wraps around the earth several times.
pcwalton · 2018-09-21
It's because defining "customization points" as operators make it easier to write templates, essentially. See "C++ doesn’t know how to do customization points that aren’t operators": https://quuxplusone.github.io/blog/2018/08/23/customization-point-or-n…
This is one of the downsides of not having typeclasses that is often forgotten about.
Mawr · 2025-01-25
> I hate coding interviews but I am sympathetic to people who want to do them because I've met people who are such good bullshitters that they could fool most people. If you're talking about someone with no working experience and who claims to be self-taught, you really have to make them write code.
The choice is not limited to made up toy problems vs not testing coding skills at all. You can give them real problems to solve.
> The interviewers tried to tell him to approach it like an industrial-grade solution, not a weird academic exercise.
Hahaha, and how exactly do you write an 'industrial-grade' FizzBuzz? ;)
Obligatory: https://github.com/EnterpriseQualityCoding/FizzBuzzEnterpriseEdition
> The whole point of the interview is to get hints about the candidate. There are times when interviewers read too much into what the candidate does or says, but this isn't one of them.
Oh but it is. If I were to ask you, the expert, to draw a blue line with red ink and then attempt to draw conclusions from your behaviour based on that question, could I ever get a valid assessment of you? If a test is faulty, so are its results. Garbage in, garbage out.
Interviewing is no trivial task. It is an attempt to test how well someone will do a thing without having them actually do it. By definition, that is impossible. Still, we can try to get good enough results by minimising the number of differences between our test environment (interview) and production (the job). That will…
Kranar · 2021-03-09
I do appreciate the effort you went to for this, but you make a lot of very strong claims that depend on very obscure minutia and unfortunately they end up being false under careful scrutiny.
>But who says my fancy pointers will even necessarily map 1:1 to a linear (and contiguous!) pointer space?
The standard as of C++11 does. std::vector<T> provides the member function T* data() which is required to return a pointer to the first element of a contiguous memory region spanning the entire vector:
https://en.cppreference.com/w/cpp/container/vector/data
Note that it specifically returns a T* rather than a my_pointer<T>, or what is referred to in standardese as a "fancy pointer":
https://en.cppreference.com/w/cpp/named_req/Allocator#Fancy_pointers
>What we see here is folly pretends to support custom allocators, but it cuts corners internally.
No such corners are cut. Folly has full support for custom allocators including fancy pointers and in this case it's giving you a compile time error for what could have been undefined behavior. That's an advantage in my book, I'll take compile time error over hard to debug memory corruption any day of the week.
Fancy pointers to T are required to be implicitly convertible to T* and while the small snippet of code you pasted doesn't make use of this requirement in GCC and clang, MSVC does make use of this requirement and you can see as per the link below that your allocator fails to work:
https://godbolt.org/z/7KrE41
You'll notice…
quotemstr · 2020-06-29
I was hoping that this article would be about C++'s terrible allocator interface and how to fix it. In particular C++ containers can only allocate and release memory, not grow existing allocations --- at least while using the standard allocator interface [1]. So when vector needs to grow, it always needs to copy all elements.
Why is this limitation important? Doesn't realloc copy anyway? Well, not always. Linux has this neat system call called mremap [2] that in theory allows an allocation to move in virtual address space but not in physical memory. (To be precise, mremap moves PTEs directly.) Realloc-via-mremap is much more efficient than relloc-via-copying, and it's a shame that limitations in C++ language design prevent our using it, at least with standard containers.
Yes, yes, a move constructor requires both source and destination addresses to be simultaneously valid, so we can't use mremap [3] in the general case. But lots of C++ objects (like, e.g., int) are trivially movable [4], and these objects would work just fine in an mremap-based vector.
[1] https://en.cppreference.com/w/cpp/memory/allocator
[2] https://man7.org/linux/man-pages/man2/mremap.2.html
[3] well, without the shared mapping dup hack, but that's specialized
[4] https://quuxplusone.github.io/blog/2018/05/02/trivial-abi-101/
comex · 2019-09-12
Indeed, RAII is a zero-cost abstraction compared to running the same destructors manually. On the other hand, C++ makes it really easy to write programs that copy and destroy things when it isn't necessary.
For example, if a function takes a `std::string` as an argument (by value), any string you pass in will be copied into a new allocation, which will then have to be deallocated. That's fine if the function really needs its own allocation – but it might not. In that case you can avoid the copy by changing the argument type to `const std::string &` or `std::string_view` (the latter being new in C++17)... but the difference is subtle enough that even an experienced programmer might not notice the extraneous copy.
Don't believe me? Consider that in 2014, "std::string was responsible for almost half of all allocations in the Chrome browser process"! [1]
(Rust does a better job here by requiring more explicitness if you want to make expensive copies.)
Oh, there's also an issue where the presence of a destructor pessimizes the calling convention for passing and returning objects of that type by value, but only slightly, and the issue will be addressed in the future. [2]
[1] https://groups.google.com/a/chromium.org/forum/#!msg/chromium-dev/EUqo…
[2] https://quuxplusone.github.io/blog/2018/05/02/trivial-abi-101/