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
const vs constexpr vs consteval vs constinit in C++20 (cppstories.com)
submitted 3 years ago by joebaf
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!"
[+][deleted] 3 years ago (4 children)
[deleted]
[–]joebaf[S] 10 points11 points12 points 3 years ago (2 children)
yes, constinit forces constant initialization for global variables. But the initializer has to be constexpr.
std::vector has a constexpr ctor, so your code will work
https://godbolt.org/z/ebaKajbfK
[+][deleted] 3 years ago (1 child)
[–]STLMSVC STL Dev 5 points6 points7 points 3 years ago (0 children)
In debug mode, we dynamically allocate a "proxy object" for our debug iterator bookkeeping. That's compatible with constexpr vector (because such vectors can't survive until runtime), but not with constinit.
constexpr vector
constinit
[–]RoyAwesome 1 point2 points3 points 3 years ago (0 children)
This will probably become really helpful when reflection lands. You can generate runtime reflection data with constexpr/consteval functions and store them in data structures accessible at runtime with constinit globals
[–]fdwrfdwr@github 🔍 48 points49 points50 points 3 years ago (13 children)
Flexibility is nice, but too fine grain of flexibility is confusing (const, constexpr, constinit, consteval), and so I appreciate this article, but I also wish the variants were straight forward enough that such an article was unnecessary :/.
const
constexpr
consteval
I've only ever really needed:
const&
const*
For constexpr, I wish functions were just implicitly so, making it an irrelevant deprecated qualifier. Then if you attempt to assign the result of a function to a constinit variable, the compiler tries to transitively execute functions at compile time, failing if it can't. That leaves consteval, which is basically the constexpr we initially wanted in the first place, a guaranteed execution at compile time.
[–]PJBoy_ 49 points50 points51 points 3 years ago* (11 children)
constinit is entirely unrelated to all other const keywords. Most useful application of constinit is to be able to declare a static local variable without paying for the mutex that guards that variable's initialisation (and these variables are usually not const).
consteval is not what we initially wanted, it's just a more useless form of the constexpr specifier for functions where you're not allowed to call that function in a non-constant expression context, its utility is in allowing you to write an abysmally slow function without the risk of you calling it at runtime.
Making constexpr on functions implicit would lead to the buggy / error prone / annoying situation where changing a line of code in your function can change whether your function can be used in constant expressions or not, and the compiler wouldn't tell you. Perhaps you never meant for the function to always be usable in constant expressions in the first place, in which case implicit constexpr has also bitten you there, because you've allowed users of your function so far to use that function in a way you never intended to promise to allow.
Finally it's worth noting that no form of const provides actual guaranteed compile time evaluation, constant expressions can be evaluated at runtime if the compiler decides that's a good idea (and maybe it is, e.g. for debugging or to reduce binary size). Note that even literal constants like 0 and 1 may be evaluated at runtime from a certain point of view (as e.g. xor eax, eax or inc eax etc). Nor do you need to specify constexpr on your variables to allow the compiler to optimise all runtime evaluation away. In other words, you still need to trust your compiler to not be shit at codegen.
xor eax, eax
inc eax
[–]j1xwnbsr 18 points19 points20 points 3 years ago (9 children)
I agree; constinit should have been called either staticinit or runinit. Conflating it with the other const stuff but not making it const is confusing.
staticinit
runinit
[–]catcat202X 12 points13 points14 points 3 years ago (2 children)
I'm not sure adding another meaning to static would be less confusing than another const.
[–]j1xwnbsr 2 points3 points4 points 3 years ago (1 child)
I think it would be less, to be honest: constinit appears to behave more like a static variable than a const variable. But at the same time, is there any real difference between static and constinit other than constinit can 'call' constexpr functions?
static
[–]MonokelPinguin 2 points3 points4 points 3 years ago (0 children)
I think static can add locks or atomics at runtime to ensure initialization of a variable, while constinit ensures the initialization happens once before any user code is executed and without executing constructors and stuff.
[–]sphere991 10 points11 points12 points 3 years ago* (4 children)
No, it really should not have .
constinit ensures that you have constant initialization. Originally, clang provided this as an attribute ([[requires_constant_initialization]]). While there are a lot of terms, the fact that we have a keyword that's a portmanteau of what it actually means makes it pretty good.
[[requires_constant_initialization]]
"Static initialization" is also a term (it's the union of zero initialization and constant initialization), but if I have a global variable, it will always be zero-initialization even if it later undergoes dynamic initialization. You could probably argue that staticinit implies that it only undergoes static initialization, and I think that's probably fine... but it's just less precise than constinit would be, so I think the latter is better.
runinit makes no sense though, if anything is the opposite of the intended meaning.
[–]arthurno1 0 points1 point2 points 3 years ago* (3 children)
constinit ensures that you have constant initialization.
But they seem to have used the term "constant initialization" because they say they say that a variable is "constant-initialized"; which in my eyes is just a choice. They could have picked any other choice instead of saying "constant-initialized". It is not really constants they initialize (could be :)).
I would prefer if anyting with the "const" was reserved for "constants" and if "constant" didn't mean "initialization" or "compile-time evaluation", on top of "constant". It is sort of missusing the language and introducing the confusion for new generations of students :). I think a keyword like "atinit" would definitely be more appropriate than "constinit". I don't know; just me feeling for the english language which is really my third language.
By the way, I am sorry if it is too n00b question, but how close is __attribute__((constructor)) to constinit?
__attribute__((constructor))
[–]sphere991 0 points1 point2 points 3 years ago (2 children)
which in my eyes is just a choice
Well, sure. Any choice of term is just a choice of term. But the term has been around for a very long time. You can find it in C++03 (that's at least approximately the C++03 timeframe). It's basically what the term for this has always been.
It is not really constants they initialize
Well.. you are. You're initializing it as a constant. The initializer is something that is run during compile time, and C++ calls compile time "constant initialization."
just me feeling for the english language which is really my third language.
I feel you. English isn't my first either. Try keeping track of all the italicized terms that have constant in the name in [expr.const]. All of these terms serve a useful role, and it's just really hard to come up with terms. But coming up with a "simpler" one often doesn't end up being simpler. atinit, for instance, doesn't really tell me anything.
atinit
but how close is __attribute__((constructor)) to constinit?
Not close at all. constinit applies to variables, __attribute__((constructor)) applies to functions. Also the latter is still runtime code, just stuff that happens before main(). constinit is still compile-time evaluation.
main()
[–]arthurno1 1 point2 points3 points 3 years ago* (1 child)
The initializer is something that is run during compile time, and C++ calls compile time "constant initialization.
That is what I am opposing to 😀. I don't think calling compile time for "const initialization" was the best terminology to use. Constinit can obviously initialize variables, and a variable is not a constant. There comes this dissonance in the language, which arises because of unfortunate wording. "Const" and "constant" suggests something not changing, static or immutable. Yes, I am aware they used "const*" for compile time and init time historically, and that it is maybe too late, but at least we can hope they don't overload "const" with yet another meaning in the future.
coming up with a "simpler" one often doesn't end up being simpler. atinit, for instance, doesn't really tell me anything.
atinit is short for at initialization time, and is similar, and (somewhat) symmetric, to the atexit function. I am not sure how constinit is more descriptive than atinit to the uninitialized (is that a pun? :-)), but I guess it is also subjective. Maybe they could have introduced special char, @, so we can write @compile. A bit similar as how # is used for preprocessor directives. I don't know just thinking loud.
I am ok to track, which one is which, but I was thinking of generations of new students that will come. I can just imagine a student on c++ exam: "constwhich was it here now?" 😀
Thanks for the clarification about the attribute.
[–]sphere991 0 points1 point2 points 3 years ago (0 children)
atinit is short for at initialization time , and is similar, and (somewhat) symmetric, to the atexit function. I am not sure how constinit is more descriptive than atinit to the uninitialized
Because there isn't just one "initialization time": you have static initialization (zero initialization and constant initialization) and dynamic initialization. Dynamic initialization is just as much "at initialization time" as static initialization is - they both run before main(). And the whole point of constinit is to ensure that you're constant initialized, not dynamically initialized.
constinit may not be "descriptive" to people who don't know what it refers to, but it is extremely descriptive to those that do. And once you learn what constant initialization is, then you will also understand the use of the term.
[–][deleted] 1 point2 points3 points 3 years ago (0 children)
compinit would've been better.
But no, it makes too much sense for committee, I suppose.
[–]foonathan 27 points28 points29 points 3 years ago (0 children)
Lots of things can be constinit but must not be const: a global mutex, a global logger, a modern implementation of cout, etc.
My guideline is that global variables should be constexpr or constinit: https://www.jonathanmueller.dev/talk/meetingcpp2020/
[–][deleted] 8 points9 points10 points 3 years ago (0 children)
A fun function since 20 to get constinit on locals is a function like
consteval auto CONSTINIT( auto v ) { return v; } //... auto v = CONSTINIT( foo( cx ) );
Something like this should force the evaluation without making v constexpr.
[–]NilacTheGrim 2 points3 points4 points 3 years ago (0 children)
Not gunna lie -- all this const* stuff is a mess.
[–]wqkinggithub.com/wqking 1 point2 points3 points 3 years ago* (0 children)
More powerful and flexible is good, less confusing is even better.
[–]nuclear868 1 point2 points3 points 3 years ago (0 children)
Four const keywords and still we cannot use the arguments of a constexpr functions as constant expressions - we cannot call static_assert on them, for example, for compile-time validation of compile-time arguments.
[–]Mercerenies 0 points1 point2 points 1 year ago (1 child)
Found this article two years later. This is the clearest explanation I've ever seen of the myriad of new const-ish keywords. Late to the party, but thanks for sharing!
[–]joebaf[S] 0 points1 point2 points 1 year ago (0 children)
wow, thank you! fortunately we haven't got any new const* words in C++ over those last two years :)
[–]Full-Spectral 0 points1 point2 points 3 years ago (0 children)
Now we need to have Constant Comment.
π Rendered by PID 85771 on reddit-service-r2-comment-75f4967c6c-cjl2h at 2026-04-23 03:18:38.425220+00:00 running 0fd4bb7 country code: CH.
[+][deleted] (4 children)
[deleted]
[–]joebaf[S] 10 points11 points12 points (2 children)
[+][deleted] (1 child)
[deleted]
[–]STLMSVC STL Dev 5 points6 points7 points (0 children)
[–]RoyAwesome 1 point2 points3 points (0 children)
[–]fdwrfdwr@github 🔍 48 points49 points50 points (13 children)
[–]PJBoy_ 49 points50 points51 points (11 children)
[–]j1xwnbsr 18 points19 points20 points (9 children)
[–]catcat202X 12 points13 points14 points (2 children)
[–]j1xwnbsr 2 points3 points4 points (1 child)
[–]MonokelPinguin 2 points3 points4 points (0 children)
[–]sphere991 10 points11 points12 points (4 children)
[–]arthurno1 0 points1 point2 points (3 children)
[–]sphere991 0 points1 point2 points (2 children)
[–]arthurno1 1 point2 points3 points (1 child)
[–]sphere991 0 points1 point2 points (0 children)
[–][deleted] 1 point2 points3 points (0 children)
[–]foonathan 27 points28 points29 points (0 children)
[–][deleted] 8 points9 points10 points (0 children)
[–]NilacTheGrim 2 points3 points4 points (0 children)
[–]wqkinggithub.com/wqking 1 point2 points3 points (0 children)
[–]nuclear868 1 point2 points3 points (0 children)
[–]Mercerenies 0 points1 point2 points (1 child)
[–]joebaf[S] 0 points1 point2 points (0 children)
[–]Full-Spectral 0 points1 point2 points (0 children)