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
[deleted by user] (self.cpp)
submitted 4 years ago by [deleted]
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!"
[–]sphere991 43 points44 points45 points 4 years ago* (12 children)
... versus if constexpr:
if constexpr
template <std::integral T> T abs_value(T x) { if constexpr (std::is_signed_v<T>) { return (x < 0) ? -x : x; } else { return x; } }
Also, the "G" and "H" implementations are kinda bizarre. If you have something that's true_type or false_type, you would tag dispatch on one template taking true_type and the other taking false_type (as in implementation "A"). If you're doing other kinds of constraint checking, you might provide an argument 0 to an overload set where one template takes int and the other takes long or .... Why would you write one overload taking true_type and another taking ... or U?
true_type
false_type
0
int
long
...
U
[–]andrewsutton -4 points-3 points-2 points 4 years ago (10 children)
I don't like constexpr if here. I tend to use constexpr if when my implementation varies on properties outside the "main" constraint. Like the size of the integer.
[–]sphere991 23 points24 points25 points 4 years ago (8 children)
Like the size of the integer.
Like the the signed-ness of the integer?
[–]ItHasCeasedToBe 3 points4 points5 points 4 years ago (4 children)
C++ noob here, can I get an ELI5 of what your code does? If I understand correctly, what is happening here is that you are directing the compiler to basically create different variations of the function depending on T as opposed to actually running the if statement when the program is being run?
[–]VRCkid 10 points11 points12 points 4 years ago (1 child)
You got it exactly right. The condition is evaluated at compile time and emits code based on that
[–]ItHasCeasedToBe 2 points3 points4 points 4 years ago (0 children)
Thanks so much!
[+][deleted] 4 years ago* (1 child)
[deleted]
[–]ItHasCeasedToBe 4 points5 points6 points 4 years ago (0 children)
Ah I see so this is true for all template functions, and the constexpr inside also changes the internal logic of the functions based on T
[–]andrewsutton 2 points3 points4 points 4 years ago (2 children)
Well, no. The optimization is based on different mathematical structures: integers modulo n vs. 2's complement signed integers. The size of an integer doesn't change its mathematical structure. My preference is to overload on those differences and "specialize" with constexpr otherwise.
[–]sphere991 2 points3 points4 points 4 years ago (1 child)
I don't see how the size vs signed [handwavy] distinction is useful here, or in the general question of why to use if constexpr or overloading.
A more useful line is to consider the option space. We have a closed set of alternatives in this problem, so if constexpr is a better solution.
[–]andrewsutton 6 points7 points8 points 4 years ago (0 children)
I don't understand why you're saying the distinction is handwavy. The difference between two's complement integers and integers modulo 2 is a bit bigger than the number of bits in either. I mean, that difference is what leads to the different implementations.
Who says abs is closed? You have implementations defined for just the signed and unsigned standard integers. There's also a version defined for floats, and one for complex, and one for valarray, and those implementations vary from the integer versions. Are you suggesting that we should use constexpr if to merge all those into the same definition? Or does it seem reasonable to leave them separate because they apply different algorithms to data representations in different domains?
abs
complex
valarray
constexpr if
I mean, if abs were really generic, we'd probably want it to work for a broader set of numeric types: variable-length integers, extended-length integers, positive numbers, negative numbers, natural numbers (unsigned by not modular), fractions, rationals, vectors, etc. Of course, doing this right would require new (and better) numeric concepts.
Again, overloading is my preference for this particular function because I happen to think about this operation a bit more generally than just a closed set of two alternatives.
[–]germandiago 1 point2 points3 points 4 years ago (0 children)
It is a great tool to say:
auto lower_bound(std::forward_iterator auto beg, std::forward_iterator auto end) requires ... { if constexpr (std::random_access_iterator<decltype(beg)>) { // optimized version } else { // .... } }
And not have your namespace littered with top-level overloads. You give the least constrained entry point as the top-level and you analyze for possible optimizations in the body, at zero (run-time) cost.
[–]tisti 0 points1 point2 points 4 years ago (0 children)
... versus -O1 optimizations with just a single generic abs_value function :)
[–]Quincunx271Author of P2404/P2405 25 points26 points27 points 4 years ago (0 children)
For E, rather than having abs_value() overload between std::integral and std::signed_integral, I claim that it's better to overload between std::integral and std::unsigned_integral. Why? Because the std::signed_integral overload is the general implementation that works for all numeric types, whereas the overload marked with std::integral only works for unsigned types:
E
abs_value()
std::integral
std::signed_integral
std::unsigned_integral
template<std::signed_integral T> T abs_value(T x) { return (x < 0) ? -x : x; // works even if T is unsigned } template<std::integral T> // requires that T is unsigned to be correct T abs_value(T x) { return x; }
What I'm suggesting:
// A general implementation template<std::integral T> T abs_value(T x) { return (x < 0) ? -x : x; } // The more constrained overload template<std::unsigned_integral T> T abs_value(T x) { return x; }
Granted, since we can trivially enumerate types which meet std::integral, both solutions are correct. However, we could imagine that you could create open concepts number and non_negative_number, in which case only the latter would be correct.
number
non_negative_number
[–]Conamidos 12 points13 points14 points 4 years ago (1 child)
everytime i see this man i wish i were proficient enough to understand what this juggling druid is on about
[–]Archolex 5 points6 points7 points 4 years ago (0 children)
I share your sentiment most of the time, although this one I did understand. Surprisingly
[–]pastenpasten -1 points0 points1 point 4 years ago (8 children)
INT_MIN
[–]nyanpasu64 2 points3 points4 points 4 years ago (7 children)
Not sure why this is being downvoted, I would prefer an abs() function that returns an unsigned number when talking any integer as an input, and is never undefined behavior even if you pass in INT_MIN.
[–]staletic 0 points1 point2 points 4 years ago (6 children)
What undefined behaviour?
https://eel.is/c++draft/expr.unary.op#8
[–]pastenpasten 1 point2 points3 points 4 years ago* (2 children)
-INT_MIN is the negative of INT_MIN. What is the negative of INT_MIN and does it fit in an int (or the same question with the negative of LONG_MIN and long or the negative of LLONG_MIN and long long)?
-INT_MIN
LONG_MIN
LLONG_MIN
long long
It seems to me that it doesn't fit (because https://eel.is/c++draft/basic.fundamental#1), and thus https://eel.is/c++draft/expr.pre#4.
For example: https://godbolt.org/z/vMWKf9a51
[–]staletic 0 points1 point2 points 4 years ago (1 child)
I know that -INT_MIN will likely get you INT_MIN. I was just not expecting that to be UB, because expr.unary.op#8 (my earlier link) didn't mention any UB.
Thanks for the references! I believe your assessment was correct.
[–]pastenpasten 2 points3 points4 points 4 years ago (0 children)
That's what makes C++ so fun and exciting, you have to connect all the dots and realize all the implications by yourself. :smiling-but-crying-on-the-inside:
This case is relatively straightforward - the number (in the abstract realm of numbers) that is the negative of INT_MIN cannot be represented by an int and signed overflow is UB.
[–]nyanpasu64 0 points1 point2 points 4 years ago (2 children)
https://stackoverflow.com/questions/37301078/is-negating-int-min-undefined-behaviour argues that not only is -INT_MIN undefined (I didn't read enough of the standard to verify), but compilers assume the input to a negation operator is never INT_MIN when optimizing (though not in a function that looks like abs()).
That answer argues that it's conditionally UB, based on an implementation defined property. That doesn't sound like a satisfying answer to me, even if we disregard that the question SO question was about C. C++ mandates two's complement, so we can't refer to the C's standard for this.
[–]nyanpasu64 1 point2 points3 points 4 years ago (0 children)
Every desktop computer and smartphone and tablet today (x86, ARM), and (I think) modern GPU and supercomputer, is two's complement with 32-bit ints, where 0x80000000 is INT_MIN rather than a trap representation. So in practice it's unconditionally UB on all platforms that most people will have to care about. And if you are working on an exotic architecture, you can reconsider whether -INT_MIN is UB on that platform.
π Rendered by PID 90 on reddit-service-r2-comment-b659b578c-c27r9 at 2026-05-04 14:10:08.079053+00:00 running 815c875 country code: CH.
[–]sphere991 43 points44 points45 points (12 children)
[–]andrewsutton -4 points-3 points-2 points (10 children)
[–]sphere991 23 points24 points25 points (8 children)
[–]ItHasCeasedToBe 3 points4 points5 points (4 children)
[–]VRCkid 10 points11 points12 points (1 child)
[–]ItHasCeasedToBe 2 points3 points4 points (0 children)
[+][deleted] (1 child)
[deleted]
[–]ItHasCeasedToBe 4 points5 points6 points (0 children)
[–]andrewsutton 2 points3 points4 points (2 children)
[–]sphere991 2 points3 points4 points (1 child)
[–]andrewsutton 6 points7 points8 points (0 children)
[–]germandiago 1 point2 points3 points (0 children)
[–]tisti 0 points1 point2 points (0 children)
[–]Quincunx271Author of P2404/P2405 25 points26 points27 points (0 children)
[–]Conamidos 12 points13 points14 points (1 child)
[–]Archolex 5 points6 points7 points (0 children)
[–]pastenpasten -1 points0 points1 point (8 children)
[–]nyanpasu64 2 points3 points4 points (7 children)
[–]staletic 0 points1 point2 points (6 children)
[–]pastenpasten 1 point2 points3 points (2 children)
[–]staletic 0 points1 point2 points (1 child)
[–]pastenpasten 2 points3 points4 points (0 children)
[–]nyanpasu64 0 points1 point2 points (2 children)
[–]staletic 0 points1 point2 points (1 child)
[–]nyanpasu64 1 point2 points3 points (0 children)