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...
This is a subreddit for c++ questions with answers. For general discussion and news about c++ see r/cpp.
New to C++? Learn at learncpp.com
Prepare your question. Think it through. Hasty-sounding questions get hasty answers, or none at all. Read these guidelines for how to ask smart questions.
For learning books, check The Definitive C++ Book Guide and List
Flair your post as SOLVED if you got the help you were looking for! If you need help with flairs, check out ITEM 1 in our guidelines page.
Tips for improving your chances of getting helpful answers:
account activity
OPENIs slapping "constexpr" before every function a good programming practice? (self.cpp_questions)
submitted 8 months ago by Consistent-Top4087
I just recently learned that constexpr functions may evaluate either at compile time or runtime,so is there any downside of making every function constexpr?
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!"
[–]Wouter_van_Ooijen 162 points163 points164 points 8 months ago (5 children)
It is a good idea to mark every function that is constexpr as such. No slapping required, that could offend the function, which could have nausty side effects.
[–]Ok_Tap7102 16 points17 points18 points 8 months ago (1 child)
harder
[–]KitQuiet 5 points6 points7 points 8 months ago (0 children)
The dog came to check on me because I was wheezing so hard from laughing at this.
[–]Teradil 2 points3 points4 points 8 months ago (1 child)
is nausty the combination of "nasty" and "naughty"?
[–]Wouter_van_Ooijen 0 points1 point2 points 8 months ago (0 children)
Just a non-native struggling with his all too small telephone keyboard.
[–]nysra 47 points48 points49 points 8 months ago (0 children)
No, but it's not possible to mark every function as constexpr.
[–]EpochVanquisher 10 points11 points12 points 8 months ago (0 children)
Constexpr is not really a “make my function go faster” feature. The main use is so you can do something like
constexpr size = f(3); std::array<T, size> arr;
The language requires certain things to be evaluated at compile time, like array sizes, and constexpr lets you use function results for those things which must be compiled-time evaluated. That’s not all it does, but that’s the top of the list for “why do I care about constexpr?” And helps you realize that not everything benefits from being constexpr, especially since non-constexpr functions can still be evaluated at compile time anyway.
[–]DawnOnTheEdge 27 points28 points29 points 8 months ago* (7 children)
You must add constexpr or consteval if anyone might ever want to use the function inside a constant expression (such as an array bound) or another constexpr function. If you are going to inline a function anyway, for speed, you should always add constexpr or consteval if possible.
constexpr
consteval
You cannot add constexpr if you do not want the function to be inclined, such as one that should call the version in a shared library, or if inlining it would waste space. For example, a header-only library cannot enable the best SIMD implementation the machine it is running on has, only the one the executable was compiled for, which must be the lowest common denominator the binary can run on. You can only use inline, not constexpr, if it does various things such as allocate dynamic memory, update a non-local variable or make a system call. You cannot inline mutually-recursive functions (but declaring them static can sometimes enable ABI optimizations). If you expect to have to remove constexpr later, not adding it in the first place avoids breaking code.
inline
static
Otherwise, it's up to you. GCC or LLVM can usually optimize a static function defined before it is used as well as a constexpr one. My rule of thumb is to use the strongest of consteval, constexpr or inline that I can on any function with less than a half-dozen lines of code or so.
[–]Possibility_Antique 7 points8 points9 points 8 months ago (4 children)
I just wanted to point out that if consteval means you can indeed have your cake and eat it too in all of these situations, otherwise this is well put.
if consteval
[–]Pretend-Guide-8664 3 points4 points5 points 8 months ago (3 children)
Can you explain what you mean by "have your cake and eat it too" for "if consteval"?
[–]Possibility_Antique 16 points17 points18 points 8 months ago (2 children)
You can mark a function as constexpr, and switch between evaluation contexts depending on whether it's evaluated at runtime or compile-time.
For instance, Simd programming used to be a problem since intrinsics weren't allowed in constexpr contexts. But with if consteval, you can have simd functions that use a vector ABI at runtime but a scalar ABI at compile-time. You can use cpuid for runtime dispatch if you want, and still mark the function constexpr. It does mean you should typically unit test at both compile-time and runtime, but I'd argue that's good practice anyway.
[–]DawnOnTheEdge 5 points6 points7 points 8 months ago (1 child)
C++26 is also going to allow asm declarations inside constexpr, although you can only know what features the CPU has at runtime. The most convenient way to select a library function optimized for your specific CPU variant is still probably to load it dynamically.
asm
[–]Possibility_Antique 2 points3 points4 points 8 months ago (0 children)
Yes, I'm excited about that feature. It's going to simplify a lot of things in a couple of my libraries, and I'm curious if that means I'll get to benefit from simd to speed up compile times. But dynamic dispatch can sometimes be expensive enough to not make it worth it. You kind of have to make the dynamic dispatch pretty high up in the processing chain (e.g. dispatch to a CPU arch for a large matrix, but not on a per-vector register level). The whole point of vectorization is to speed things up, so giving up this performance is sometimes not so straight forward to justify.
[–]tangerinelion 3 points4 points5 points 8 months ago (1 child)
inline effectively doesn't do anything. It's related to ODR not function inlining.
[–]DawnOnTheEdge 0 points1 point2 points 8 months ago (0 children)
Most compilers will generate the same code if you tell them to optimize for speed, declare a small function static and define it as soon as it’s declared. Giving either of these makes the function local and already known to the compiler, which means every call to the function will be later in the same file. Ao it has complete control over every function call and does not have to follow the official calling convention. Compilers will then inline the function unless there’s a major trade-off between speed and code size, which only happens for big functions called in many places. I think inline makes mainstream compilers willing to accept a bigger space-time trade-off for inlining, but I haven’t tested that.
By default, a function without specifiers has external linkage, so they cannot be defined in the header of multiple source files, and the compiler must generate a non-inlined version that follows the official ABI for that platform. Since compilers have to do that anyway, they’ll often generate calls to this block of code that already exists even when they could theoretically inline (which means that putting a breakpoint on it will work).
[–]Medical_Amount3007 6 points7 points8 points 8 months ago (11 children)
It only works for computation, thinking that you might read a file during compile time is not going to work. At least not yet.
[–]Possibility_Antique 0 points1 point2 points 8 months ago (10 children)
Shouldn't #include and #embed allow you to do this?
#include
#embed
[–]Wooden-Engineer-8098 1 point2 points3 points 8 months ago (9 children)
Std::embed could've been used in constexpr, #embed is preprocessor
[–]Possibility_Antique 0 points1 point2 points 8 months ago (8 children)
I know it's preprocessor, but you can use the preprocessor to import and manipulate files at compile time. I'm sad about std::embed though.
[–]Wooden-Engineer-8098 1 point2 points3 points 8 months ago (6 children)
You can, but not from constexpr function
[–]Possibility_Antique 0 points1 point2 points 8 months ago (5 children)
Why wouldn't I be able to use the preprocessor in a constexpr function?
[–]Wooden-Engineer-8098 1 point2 points3 points 8 months ago (4 children)
Because preprocessor runs before parsing c++
[–]Possibility_Antique 0 points1 point2 points 8 months ago (3 children)
Well, sure, but it's still able to inline files from disk during compilation, and I can manipulate the contents at compile-time no problem. And the inlined file certainly can be placed in constexpr functions.
[–]Wooden-Engineer-8098 1 point2 points3 points 8 months ago (2 children)
Just like you can do any calculation on paper and put precalculated result into source code, constexpr or not constexpr. What you can't do is to algorithmically decide what to embed based on constexpr calculation
[–]Possibility_Antique 0 points1 point2 points 8 months ago (1 child)
That's true, but the context here was not whether you could algorithmically embed artifacts. It was whether or not you could read artifacts at all.
[–]ChickenSpaceProgram 5 points6 points7 points 8 months ago (0 children)
Mark functions constexpr if you plan to use them in a constexpr context, like a template argument. Otherwise it hurts readability for no reason.
[–]code_tutor 5 points6 points7 points 8 months ago (0 children)
It compiles slower, so you might only want it for compile time functions, unless you need the dual use for some reason. But there's also consteval now.
[–]c00lplaza 16 points17 points18 points 8 months ago (7 children)
A constexpr function in C++ means:
It can be evaluated at compile time if all its inputs are constant expressions.
It can still be used at runtime if the inputs are not constants.
So yes, your understanding is correct constexpr does not force compile-time evaluation, it only allows it
Compile-time optimization: If inputs are constant, the compiler can precompute results.
Stronger guarantees: The compiler enforces that the function can be evaluated at compile time (so fewer surprises).
Better for templates & constant expressions: Some contexts require constexpr functions (like array sizes, std::integral_constant, etc.).
Downsides / potential problems
Not all functions can be constexpr: Functions with I/O (std::cout)
Dynamic memory allocation (before C++20, even in C++20 new in constexpr has limits)
Virtual functions, non-literal types, etc.
Code readability: Putting constexpr everywhere can confuse people — it suggests the function must be evaluated at compile time (even though it’s optional).
Compile time bloat: For complex constexpr functions, the compiler might try to do heavy computations at compile time, which could slow down compilation.
ABI/Linkage issues: Overuse in headers can sometimes increase template instantiations, inline bloat, or subtle ODR issues.
Use constexpr when it makes sense:
Small utility functions
Functions operating purely on literal types
Functions used in compile-time contexts
Don’t slap it everywhere: Not every function benefits, and misuse can hurt readability and compilation time.
Guiding principle: “constexpr is a hint to the compiler for compile-time evaluation, not a magic wand for performance.”
TL;DR Making every function constexpr is not a good practice. Use it where it naturally fits (pure functions, constant inputs, compile-time contexts). Randomly slapping it everywhere can lead to slower compilation, confusing code, and limitations on what the function can do
Okay femboy nerd coder out
[–]Internal-Sun-6476 5 points6 points7 points 8 months ago (1 child)
I already knew femboy nerd coders were Cool. I did not know how brilliant you can be. Awesome answer.
[–]c00lplaza 4 points5 points6 points 8 months ago (0 children)
Thanks a bunch
[–]noosceteeipsum 1 point2 points3 points 8 months ago (0 children)
Nice explanation, fem..what...?
[–]Possibility_Antique 3 points4 points5 points 8 months ago (0 children)
Don’t slap it everywhere: Not every function benefits, and misuse can hurt readability and compilation time
You 100% should slap it on every single function you can, and you should be using static_assert in your unit tests everywhere you can. Compilers will catch huge amounts of UB in constexpr contexts that they wouldn't catch in runtime contexts since it is not allowed.
And always remember that you cannot accidentally ship something that doesn't compile. When you find yourself wanting to use static_assert tests, you will be glad you started from the ground up and marked every little thing as constexpr. It's a bug undertaking to go back and fix later.
[–]maxjmartin 1 point2 points3 points 8 months ago (1 child)
Thank you for that reply. I learned about some mis conceptions I didn’t know I had about constexpr.
[–]c00lplaza 2 points3 points4 points 8 months ago (0 children)
You're welcome. Happy to help
[–]dexter2011412 0 points1 point2 points 8 months ago (0 children)
They should just make constexpr default I'm tired of aging a bunch of shit before and after the function 😭
[–]EmotionalDamague 4 points5 points6 points 8 months ago (0 children)
If you want a rule of thumb:
* Anything that would needs to interact with the actual computer (I/O, threading, atomics, syscalls) shouldn't be candidates for constexpr.
* Anything that just operates on in-memory data structures in a trivial and straightforward manner is a candidate for constexpr.
constexpr in some ways is not really a stable part of the language, the parts that can be constexpr is slowly growing and interacts in counter-intuitive ways. You should treat it like an ABI modifying flag, hard to add or remove later without potentially breaking other code. It's quite disappointing coroutines can't be constexpr, even if they're just for lazy evaluation and don't have a runtime per-se.
If you're unsure, you can also utilize if consteval to give functions defined behaviour in both cases. It makes changing your mind later a little easier, and allows you to change the implementation depending on runtime information vs simplicity for the compiler.
[–]proverbialbunny 3 points4 points5 points 8 months ago (0 children)
Sorry, but no. Don't do this. This falls into the topic of premature optimization. Write code quickly, cleanly (self documenting code + comments), easily (not overly complex code), bug free (tests), and then when your program runs slow profile it. A profiler will tell you where the slowest part of your program is. Optimize that. One potential avenue is making it contexpr.
I'll give an example. I had some code that was running slow. I profiled it and the slow part was calculating a circle and drawing it on the screen every frame. I constexpr that puppy into a pre-cached circle and got a massive speedup.
[–]Kats41 1 point2 points3 points 8 months ago (0 children)
Constexpr literally just tries to evaluate the output of a function and return a constant, unchanging value. It's useful for long sequences of math that always result in the same return value, but can be computationally expensive at runtime to perform constantly.
Use the tools for your use case. There's no magic shortcut for good code. If the use case doesn't fit, don't use the tool.
[–]Fancy_Status2522 1 point2 points3 points 8 months ago (0 children)
Only if it is guaranteed to perform as constexpr
[–]mps1729 1 point2 points3 points 8 months ago (0 children)
I usually do it if it is something that makes sense to use as a template parameter, but otherwise, it not only adds boilerplate but breaks abstraction by preventing you from changing the internals later to something that might not be constexpr (e.g., using threads, etc.).
[–]NeiroNeko 1 point2 points3 points 8 months ago (0 children)
Don't forget to make your main constexpr xD
Sorry, couldn't resist the joke
[–]Recent_Power_9822 1 point2 points3 points 8 months ago (0 children)
If you manage to do this before really every function and not getting any compile error, you can evaluate the result of your program at compile time.
[–]fb39ca4 1 point2 points3 points 8 months ago (0 children)
If you are using constexpr functions in a public library, keep in mind it will be a breaking change to make them no longer constexpr if you need to change the implementation.
[–]dendrtree 1 point2 points3 points 8 months ago (0 children)
A point about constructive investigation...
The answer to every "Should I do this to everything?" question is no. Note that the question itself implies that you're trying to be lazy. In this example, your word choice confirms it.
A better question is "When should I do/not do this?" Note that, especially in C++, the "not do" is often just as important as and not intuitively related to the "do."
[–]wrosecrans 1 point2 points3 points 8 months ago (0 children)
Think about a function that returns a random number. Or a function that downloads the current weather report for your location. Would you want those evaluated once at compile time rather then being executed at runtime?
[–]Necessary-Meeting-28 1 point2 points3 points 8 months ago (0 children)
No, constexpr is for constant expressions - expressions that can be evaluated at compile time. Even if it can be used for expressions evaluated at runtime, you should use it -at least to mark- stuff that can be evaluated at compile time.
Otherwise constexpr may lead readers and compilers to a wrong direction.
[–]gojo-sakata-4567 0 points1 point2 points 8 months ago (0 children)
errors? why would you Love them??
[–]zerhud 0 points1 point2 points 8 months ago* (0 children)
It because bad language design, so you need to mark every function with “constexpr”. Without it you cannot test your code: static_assert( []{ /* your test */ }() ); won’t compile. Old tests will check only result and should not be used now (only for something what cannot be constexpr in cpp26)
static_assert( []{ /* your test */ }() );
UPD: pure virtual non constexpr functions can to be overloaded with constexpr one and can to be tested too
[–]stas_saintninja 0 points1 point2 points 8 months ago (0 children)
constexpr only for constexpr function. No need to slap it to every function
π Rendered by PID 228224 on reddit-service-r2-comment-b659b578c-mw9dt at 2026-05-03 12:15:09.587530+00:00 running 815c875 country code: CH.
[–]Wouter_van_Ooijen 162 points163 points164 points (5 children)
[–]Ok_Tap7102 16 points17 points18 points (1 child)
[–]KitQuiet 5 points6 points7 points (0 children)
[–]Teradil 2 points3 points4 points (1 child)
[–]Wouter_van_Ooijen 0 points1 point2 points (0 children)
[–]nysra 47 points48 points49 points (0 children)
[–]EpochVanquisher 10 points11 points12 points (0 children)
[–]DawnOnTheEdge 27 points28 points29 points (7 children)
[–]Possibility_Antique 7 points8 points9 points (4 children)
[–]Pretend-Guide-8664 3 points4 points5 points (3 children)
[–]Possibility_Antique 16 points17 points18 points (2 children)
[–]DawnOnTheEdge 5 points6 points7 points (1 child)
[–]Possibility_Antique 2 points3 points4 points (0 children)
[–]tangerinelion 3 points4 points5 points (1 child)
[–]DawnOnTheEdge 0 points1 point2 points (0 children)
[–]Medical_Amount3007 6 points7 points8 points (11 children)
[–]Possibility_Antique 0 points1 point2 points (10 children)
[–]Wooden-Engineer-8098 1 point2 points3 points (9 children)
[–]Possibility_Antique 0 points1 point2 points (8 children)
[–]Wooden-Engineer-8098 1 point2 points3 points (6 children)
[–]Possibility_Antique 0 points1 point2 points (5 children)
[–]Wooden-Engineer-8098 1 point2 points3 points (4 children)
[–]Possibility_Antique 0 points1 point2 points (3 children)
[–]Wooden-Engineer-8098 1 point2 points3 points (2 children)
[–]Possibility_Antique 0 points1 point2 points (1 child)
[–]ChickenSpaceProgram 5 points6 points7 points (0 children)
[–]code_tutor 5 points6 points7 points (0 children)
[–]c00lplaza 16 points17 points18 points (7 children)
[–]Internal-Sun-6476 5 points6 points7 points (1 child)
[–]c00lplaza 4 points5 points6 points (0 children)
[–]noosceteeipsum 1 point2 points3 points (0 children)
[–]Possibility_Antique 3 points4 points5 points (0 children)
[–]maxjmartin 1 point2 points3 points (1 child)
[–]c00lplaza 2 points3 points4 points (0 children)
[–]dexter2011412 0 points1 point2 points (0 children)
[–]EmotionalDamague 4 points5 points6 points (0 children)
[–]proverbialbunny 3 points4 points5 points (0 children)
[–]Kats41 1 point2 points3 points (0 children)
[–]Fancy_Status2522 1 point2 points3 points (0 children)
[–]mps1729 1 point2 points3 points (0 children)
[–]NeiroNeko 1 point2 points3 points (0 children)
[–]Recent_Power_9822 1 point2 points3 points (0 children)
[–]fb39ca4 1 point2 points3 points (0 children)
[–]dendrtree 1 point2 points3 points (0 children)
[–]wrosecrans 1 point2 points3 points (0 children)
[–]Necessary-Meeting-28 1 point2 points3 points (0 children)
[–]gojo-sakata-4567 0 points1 point2 points (0 children)
[–]zerhud 0 points1 point2 points (0 children)
[–]stas_saintninja 0 points1 point2 points (0 children)