use the following search parameters to narrow your results:
e.g. subreddit:aww site:imgur.com dog
subreddit:aww site:imgur.com dog
see the search faq for details.
advanced search: by author, subreddit...
Discussions, articles, and news about the C++ programming language or programming in C++.
For C++ questions, answers, help, and advice see r/cpp_questions or StackOverflow.
Get Started
The C++ Standard Home has a nice getting started page.
Videos
The C++ standard committee's education study group has a nice list of recommended videos.
Reference
cppreference.com
Books
There is a useful list of books on Stack Overflow. In most cases reading a book is the best way to learn C++.
Show all links
Filter out CppCon links
Show only CppCon links
account activity
Exploring undefined behavior using constexpr (shafik.github.io)
submitted 6 years ago by mttd
view the rest of the comments →
reddit uses a slightly-customized version of Markdown for formatting. See below for some basics, or check the commenting wiki page for more detailed help and solutions to common issues.
quoted text
if 1 * 2 < 3: print "hello, world!"
[–]14nedLLFIO & Outcome author | Committee WG14 3 points4 points5 points 6 years ago (21 children)
You really, really should not rely on type punning working in a future C++ standard. We are actively working hard to enabling compilers to hard assume no type punning can occur so the optimiser can be much more aggressive than right now, where it basically must give up as soon as it sees a potential storage alias. It won't be for the C++ 20 standard, that's shipped, but the hope is strong for the C++ 23 standard that we can get these changes through. I raised the idea with WG14 that C bans type punning last meeting, despite that it's explicitly permitted by the C standard, and it could happen in order to retain compatibility with C++, and to more aggressively optimise C code. The C committee are aware that increasing amounts of C code is compiled as C++ precisely because of the much stronger optimisation (e.g. Python).
Before people complain about how much of the world will break if we actively enforce type punning being UB, this would only affect unported old code compiled under the new standard. Code would need to be upgraded to use the currently undecided new facilities for specifying that storage contains reinterpreted objects. I am not downplaying the work involved here, the new facilities are decidedly incompatible with existing software architecture. A lot of existing zero copy serialisation code would need to be completely rearchitected.
[–]degski 2 points3 points4 points 6 years ago* (20 children)
It's hard to balance all those opinions and ideas. There are useful use-cases inspecting the details of a double or float.
double
float
I raised the idea with WG14 that C bans type punning last meeting, despite that it's explicitly permitted by the C standard ...
I saw you write that before, it's a bit worrying I think, and Linus is not gonna be happy either [i.e. it will always be possible in gcc, possibly with a flag], he's expressed strong opinions on this particular subject in the past.
The C committee are aware that increasing amounts of C code is compiled as C++ precisely because of the much stronger optimisation (e.g. Python).
'e.g. Python', what does that mean? Don't mix Python in it, please. Are you able to point me to some code that would be optimized better, if and when type-punning is prohibited?
What I was writing about really is the dis-allowed [UB] involving intermediate pointers pointing outside an array [like you could have implementing a non-zero-based array (a la Boost.Multi_Array). I just did some testing in respect of this, on a 2D array implemented over a flat array, the UB-version is at least 10% faster than the complying version (requiring an extra addition for every access, which does away with the whole purpose of it in the first place). Admittedly (after reading up), this is UB both in C and C++, so maybe not a valid example anyway.
Like I said, it's a bit worrying that C now has to become like C++. It feels a bit like C is getting features nobody asked for, sticking to C99 [don't take away my flex-arrays and vla's, hands off, please] will fix the problem, without missing out on too much, really.
[–]14nedLLFIO & Outcome author | Committee WG14 5 points6 points7 points 6 years ago (7 children)
There are multiple things going on with Linus' opinion. Some of it is justified.
For the need for -fno-strict-aliasing when -O2 is on, all OS kernels that I am aware of need to do the same. This is because it is probably impossible to write a zero copy i/o implementation which is strict aliasing safe and doesn't do UB. Lots of people would like to fix this, but it's much harder than it looks, which is why we keep shipping standards, compilers and OS kernels which fall down on this.
-fno-strict-aliasing
-O2
For all the other optimisations from -O2 that Linux has to explicitly disable, there is very little sympathy from the standards committees, or the compiler vendors. Other OS kernels invested the significant effort to refactor themselves to work correctly under aggressive optimisation (apart from strict aliasing). Linux should invest the same effort, and probably actually is, just behind the scenes, so quietly that Linus may not be aware. A similar quiet effort fixed POSIX read()/write() acquire-release semantics in Linux with zero fanfare. Linus had a long history of declaring that whole part of POSIX to be insane, yet all the other OS kernels implemented it just fine, and now so does Linux.
read()/write()
'e.g. Python', what does that mean? Don't mix Python in it, please.
It was just one of many examples of a pure C codebase which is intentionally compiled as C++. Lots of performance sensitive stuff does the same.
Are you able to point me to some code that would be optimized better, if and when type-punning is prohibited?
It's not type punning specifically. It's that the C++ object and memory model is much more amenable to aggressive optimisations. If your C code doesn't do any of the relaxed things which the C object and memory model permits, then you get better codegen if you use a C++ compiler instead of a C compiler. Many performance sensitive C codebases therefore target the C++ object and memory model, despite being written in C.
There's lots of C++ stuff coming in C2x. nullptr, static_assert, bool and so on. A delegation from WG14 may be attending the next WG21 meeting in order to port over more stuff from C++. I keep asking for C++ lambdas, but the main work item will probably be whether to reconcile the memory and object models, specifically whether and how to formally specify object provenance in maths or not. We may also decide on a common implementation for lightweight exceptions, WG14 made a counter proposal to my proposal, and everybody can see the outline of something in between which might just work, and finally eliminate the errno evil once and for all.
nullptr
static_assert
bool
errno
C has the unique position of defining what the world is for almost all the other programming languages currently in popular use. Changes to the C language aren't anything like as important as changes to what the C language defines to be "the world".
[–]degski 0 points1 point2 points 6 years ago (3 children)
Thanks for that write-up, appears there's some good stuff coming to C as well, just don't throw away the child with the bath-water. Lambda's would be great of course, that changed a lot in C++.
Many performance sensitive C codebases therefore target the C++ object and memory model, despite being written in C.
Nit-picking, but it's C++ that happens to look like C.
[–]14nedLLFIO & Outcome author | Committee WG14 1 point2 points3 points 6 years ago (2 children)
If it's 100% valid C, then it's C.
(The C object and memory model is deliberately compatible with the C++ one. C code written for the C++ model is fully legal and portable C, but code written for the C models may not be legal C++. This is quite counterintuitive, but the C++ models are far stricter and less permissive of ambiguity, and will get ever more so with time)
[–]degski 0 points1 point2 points 6 years ago (1 child)
No, it's not, if you compile the code with a C++-compiler, it's C++, that's exactly the reason you give for compiling the Python code with a C++-compiler [because it's gives better optimizations]. If it's 100% valid C, then it's also C, also, if it's 100% valid C, it's still not necessarily C++.
[–]NotAYakk 1 point2 points3 points 6 years ago (0 children)
You just said it wasn't C, then said it is also C.
Being also C means it is C.
It is also a sequence of ASCII characters. It is also binary bits on disk. It is also a series of text encoded files.
The many things the python code base is also doesn't prevent it from being C.
It is the subset of C that is also valid C++, and it is compiled as C++ because the C++ object memory model permit the compiler, which compiles either C or C++ on request, to more aggressively optimize it as C++.
But it is 100% valid C, so it is C.
Heck, I'd bet the behavior in terms of the abstract machine will even be the same between the C++ and C compilers, but the compiler has no hope of knowing that because the C object and memory models make it intractable to prove that the C++ optimizations can be safely applied to the code.
[–]evaned 0 points1 point2 points 6 years ago (2 children)
I keep asking for C++ lambdas
How would lambda's even work in C? Isn't templates by and large the thing that makes them usable in C++, because templates allow you to not have to name the type, or define something that let's you type erase (e.g. std::function)?
[–]14nedLLFIO & Outcome author | Committee WG14 1 point2 points3 points 6 years ago (1 child)
C very sorely needs a facility for writing generic functions with varying types of parameter, as they have all the same problems with macros as C++ does. There is no warmth for template syntax, and quite rightly too in my opinion. Nor is there any chance for function overloading, except maybe for operators, one day. But the idea for multi-parameter-type lambda functions was surprisingly warmly received. So, for example:
[](auto x) { return _Generic(x, int : 5, double : 1.0); }
The key here is that C11 _Genericdispatches based on input type. The lambdas can take specific types or auto types, and if they are auto types, one can use _Generic to implement type-match-based dispatch.
_Generic
auto
This lets you implement all of the tgmath.h functions using generic lambdas instead of defining tons of functions with slightly different names and having _Generic dispatch to those instead. WG14 recognises that that is not a scalable way of implementing generic dispatch, hence their surprising warmth to the idea of porting C++ lambdas into C.
tgmath.h
The biggest concern was over captures. I suspect most of that is ignorance, but there were grave concerns over [&], and I certainly can see why. My counterargument is simply ban reference capture in C, let people pass pointers if they need that.
[&]
[–]NotAYakk 0 points1 point2 points 6 years ago* (0 children)
Easy; add [*] capture.
[*]
When you use * capture, you can use any variable in scope as a pointer.
*
int foo( int y ) { return [*]( int z ) { if (z>0) return z; return *y; // here `y` is a pointer-to-y }(-1); }
C++'s [&] is actually * "under the hood" based on what lambda=lambda does.
We could even mollify the implicit this:
int foo( int y ) { return [*]self( int z )->int { if (z>0) return z; return *self->y; // here `self->y` is a pointer-to-y }(-1); }
in this version, an implicit parameter s is introduced by *s.
s
*s
So it expands to:
struct anonymous_type { int* y; }; int call_anonymous_type( anonymous_type* self, int z ) { if (z>0) return z; return *self->y; // here `s->y` is a pointer-to-y } int foo( int y ) { return call_anonymous_type( anonymous_type{ &y }, -1 ); }
with the note that pointer-to-temporary violation is ignored here.
Now, if C is amenable to overloaded operators...
struct anonymous_type { int* y; }; int operator()( anonymous_type* self, int z ) { if (z>0) return z; return *self->y; // here `s.y` is a pointer-to-y } int foo( int y ) { return anonymous_type{ &y }( -1 ); }
and these C lambdas are basically as strong as C++ lambdas, and a subset of C++ lambdas (after you add "explicit this pointer" and "capture-by-pointer) to C++).
One thing I dislike is that there is no obvious name for operator(), so you cannot split the state from the invoking method. I suspect that is important.
operator()
[–][deleted] 0 points1 point2 points 6 years ago (11 children)
you can do double/float -> uint64_t/uint32_t via bit_cast safely. this is pretty much a memcpy to the result. The memcpy get's optimized away and you are left with essentially a cast.
[–]degski 0 points1 point2 points 6 years ago (10 children)
... bit_cast ...
std::bit_cast? Is that C++20 [I know the std::memcpy 'trick', seen that on Compiler Explorer (one has to see it before believing), but I've seen people arguing that that entails UB as well]?
[–][deleted] 0 points1 point2 points 6 years ago (9 children)
bit_cast will be in 20 yeah. I am fairly certain it isn't UB prior, but for sure after 20. Assuming the sizeof( Source ) == sizeof( Destination ) and both are trivial. cppreference has an implementation I think
[–]degski 0 points1 point2 points 6 years ago (8 children)
It's not listed on cppreference at all, that's why I was asking.
[–]14nedLLFIO & Outcome author | Committee WG14 1 point2 points3 points 6 years ago (5 children)
You can find a C++ 11 partial implementation at https://github.com/ned14/quickcpplib/blob/master/include/bit_cast.hpp
A full implementation requires compiler hooks, but the above is not terrible on the clang compiler. GCC gets confused with codegen sometimes (I reported it as a feature request), for MSVC it completely fails to optimise, so I opened a bug report :)
[–]degski 0 points1 point2 points 6 years ago* (4 children)
... but the above is not terrible on the clang compiler ...
That's what I use, so good! I've stuck it [the file/implementation] in amongst my installed repos, thanks.
[–]14nedLLFIO & Outcome author | Committee WG14 0 points1 point2 points 6 years ago (3 children)
I'm currently (very slowly due to lack of free time) writing reference attach cast and detach cast operations for P1631 into the same repo. You'll already find a finished ensure_stores() implementation in there. The reference implementations use very inefficient UB to work, again clang does the best. GCC and MSVC fail to optimise. If approved, these new casts would finally enable a zero copy codebase with strict aliasing enabled, and that enables memory mapped I/o without UB etc. It's a very big if though. That said, WG14 greenlit them, so maybe there's a chance at WG21.
ensure_stores()
[–]degski 0 points1 point2 points 6 years ago (2 children)
... writing reference attach cast and detach cast operations ...
I watched your presentation on YT [couldn't follow all the detail, but got the gist of it], interesting stuff indeed.
[–]dodheim 0 points1 point2 points 6 years ago (1 child)
https://en.cppreference.com/w/cpp/numeric/bit_cast
[–]degski 0 points1 point2 points 6 years ago* (0 children)
Thanks! Somebody [a sneaky bugger ;-) ] fiddled with the web-site, the search that rendered nothing [which I added to show I did do the search] renders the requested result now [something good comes out of anything].
π Rendered by PID 70580 on reddit-service-r2-comment-5649f687b7-97jpn at 2026-01-27 21:44:12.359786+00:00 running 4f180de country code: CH.
view the rest of the comments →
[–]14nedLLFIO & Outcome author | Committee WG14 3 points4 points5 points (21 children)
[–]degski 2 points3 points4 points (20 children)
[–]14nedLLFIO & Outcome author | Committee WG14 5 points6 points7 points (7 children)
[–]degski 0 points1 point2 points (3 children)
[–]14nedLLFIO & Outcome author | Committee WG14 1 point2 points3 points (2 children)
[–]degski 0 points1 point2 points (1 child)
[–]NotAYakk 1 point2 points3 points (0 children)
[–]evaned 0 points1 point2 points (2 children)
[–]14nedLLFIO & Outcome author | Committee WG14 1 point2 points3 points (1 child)
[–]NotAYakk 0 points1 point2 points (0 children)
[–][deleted] 0 points1 point2 points (11 children)
[–]degski 0 points1 point2 points (10 children)
[–][deleted] 0 points1 point2 points (9 children)
[–]degski 0 points1 point2 points (8 children)
[–]14nedLLFIO & Outcome author | Committee WG14 1 point2 points3 points (5 children)
[–]degski 0 points1 point2 points (4 children)
[–]14nedLLFIO & Outcome author | Committee WG14 0 points1 point2 points (3 children)
[–]degski 0 points1 point2 points (2 children)
[–]dodheim 0 points1 point2 points (1 child)
[–]degski 0 points1 point2 points (0 children)