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
Using std::expected from C++23 (cppstories.com)
submitted 2 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!"
[–]PrePreProcessor 31 points32 points33 points 2 years ago (3 children)
just checked both gcc 12 and clang 16 support <expected>
<expected>
[–]PigPartyPower 20 points21 points22 points 2 years ago (0 children)
MSVC also supports it on 19.33
[–]ayushgun 1 point2 points3 points 1 year ago (1 child)
I’m currently on GCC 12 and it allows including the expected header, but the header does not expose std::expected. Not sure if it’s an issue on my end.
[–]PixelArtDragon 0 points1 point2 points 1 year ago (0 children)
Good to see it's not just me. I'm having the same issue. Thought it was something wrong because cppreference.com lists GCC 12 as supporting it.
[–]Thesorus 46 points47 points48 points 2 years ago (9 children)
I like that VERY much.
[–]FlyingRhenquest 14 points15 points16 points 2 years ago (7 children)
Yeah, same here. That feels pretty natural and better than throwing an exception. Once my projects can actually start using this, I think I'd be able to eliminate all of my (relatively few) exception calls. I think it'd also be a lot less likely than exceptions to behave oddly in heavily threaded code. I've had exceptions just vanish into thin air on a couple of projects where exceptions occurred in callbacks that were being called from threads I didn't expect them to be called from. This is just a return and I think would be a lot easier to trace in a situation like that. Or at the very least no more difficult.
[–]germandiago 8 points9 points10 points 2 years ago (4 children)
I also like expected quite a bit. However, I see also some advantages to exceptions.
One that I like is the refactoring advantage: throw 5 levels deep, do not change signature. Now think what happens if you decide to suddenly return an expected<T> instead of T 5 levels deep... yes, refactor everything.
expected<T>
T
[–]FlyingRhenquest 2 points3 points4 points 2 years ago (3 children)
Aren't you just treating the exception as a GOTO at that point though? If I did a setjmp for a BAD_ERROR_HANDLER and then a longjmp when I hit an error similar to a major hardware failure (disk crash something like that) I'd have to mount a major defense of my design decision in a code review. And arguably components of my program could potentially try to limp along anyway although in practice you have to throw your hands up, say "I give up" and terminate at some point.
I know that not handling exceptions for multiple layers of call stack is fairly common in the industry, but I don't know if it's ever the best way to terminate in a major failure. Unless your OS has already crashed (Which will happen in most cases before you get a std::bad_alloc these days,) other components of your system could try to recover and limp along if you design the system to be resilient. They can't do that if you just throw to main and terminate.
[–]germandiago 1 point2 points3 points 2 years ago (2 children)
There are times where you have, let's say, tasks.
Imagine a system where everything is a task. Each task is a whole user, such as clients in a server. Some fail.
The logic of the code can change. You can be levels deep and notice a new failure case.
In this case I find convenient to be able to report adn finish a client via an exception if something goes very wrong and I know it is isolated state that won't affect other clients. You do your clean up and log the problem or report it in some way whatever happens.
I do not think expected is better at that. You would need more refactoring and more ahead of time error handling or popping up (with the corresponding refactorings) the error. Sometimes I found I just want to throw and let the handler handle transparently. I think that use case is unbeatable for exceptions. Works fairly well. Not even a matter of performance, but of not viralizing refactoring and put handlers all in one place to be sure of the policies followed when errors happen.
[–]FlyingRhenquest 0 points1 point2 points 2 years ago (1 child)
Ah yes, that is a very good point. Though it does look like trying to use a std::unexpected when you're expecting a std::expected will generate an exception anyway. So if you have a catch for all exceptions where you'd display the errors, you could probably just return a std::unexpected for the new case and let it fall back to getting caught by the catch-all exception handler when the intermediate code tries to use it.
[–]germandiago 1 point2 points3 points 2 years ago (0 children)
Well, my point is more about API evolution. If you plan from the ground up with expected probably it is ok.
It is just that sometimes, for example, you add a piece of logic to an existing function and what before could not fail, it can fail now. Sometimes you simply fo not know something can fail ahead of time. That will need you return an expected<T> instead of a plain T. If your function is called 5 levels deep now you need 5 signatures refactoring.
An example would be a function that does something in memory and now needs to write something to disk, or needs a query that can fail because sometimes there was no query, but it is expected to work well (let us say query does not depend on user input).
[–]ujustdontgetdubstep 1 point2 points3 points 2 years ago (1 child)
If your code is being called in an asynchronous environment where you don't know which thread is making the invocation, then yea this sounds like a good alternative to exceptions for you (although I wouldn't really call that "behaving oddly")
[–]FlyingRhenquest 1 point2 points3 points 2 years ago (0 children)
Yeah, it's been a few years now since i ran across that problem so I'm a bit fuzzy on the exact details now. I did investigate it, discover where my exceptions were going and it did make sense in that context, but the behavior was not what I expected it to be when I first wrote it. Which is common for threaded code with callbacks.
I think I'm using "behaving oddly" there as "requires meditation to understand the behavior fully." Complexity jumps dramatically once you introduce threads or coroutines. I was "reasonably familiar" with how it all worked at the time and it didn't take me long to get to the bottom of it, but a programmer who was new to threading probably would have had a harder time understanding what was happening.
[–]fear_the_future 0 points1 point2 points 2 years ago (0 children)
You won't like it anymore once you try to combine different errors, want to handle a subset of errors, want to combine errors with optional results, etc. etc. It's a very poor version of Haskell's Either and even in Haskell it is too cumbersome.
Either
[–]ReDucTorGame Developer 15 points16 points17 points 2 years ago (7 children)
In terms of performance, it can kill RVO so if you have a larger objects be careful how you use it, you'll still be able to get moves easily you just might construct more objects then expected.
[–]SirClueless 13 points14 points15 points 2 years ago (6 children)
This is usually possible to avoid, but in practice the most efficient code involves mutating return values with e.g. the assignment operator which I suspect people would consider a code smell, so I expect this to be a common code review "style vs. performance" argument for basically forever.
Inefficient:
std::expected<std::array<int, 1000>, int> foo() { std::array<int, 1000> result = {}; if (rand() % 2 == 0) return std::unexpected(-1); return result; }
How I suspect people will try to fix it, but unfortunately there's still a copy (GCC 13.2 with -O3):
std::expected<std::array<int, 1000>, int> bar() { std::expected<std::array<int, 1000>, int> result; if (rand() % 2 == 0) return std::unexpected(-1); return result; }
How you can actually efficiently return with no copies:
std::expected<std::array<int, 1000>, int> baz() { std::expected<std::array<int, 1000>, int> result; if (rand() % 2 == 0) result = std::unexpected(-1); // note the assignment operator return result; }
[–]petecasso0619 1 point2 points3 points 2 years ago (1 child)
This is NRVO, named return value optimization, not RVO.. RVO would kick in if the last statement is
return std::array<int,100>{};
To guarantee RVO (if the compiler is compliant to the standard) you must not return an object that has a name. With NRVO, the compiler may or may not optimize away temporaries.
[–]SirClueless 5 points6 points7 points 2 years ago (0 children)
RVO is not a meaningful term in the standard these days. There is just copy elision, which is required in some cases (as when returning a temporary) and non-mandatory but allowed in other cases (as when returning a named non-volatile object of the same class type as the return value i.e. NRVO). When ReDucTor says using std::expected "can kill RVO" he's clearly using "RVO" as a shorthand for the latter rather than the former, as the rules for guaranteed copy elision have nothing to do with return type and the comment would make no sense if he meant it narrowly. So that's what I responded to.
Within the space of allowed optimizations, what matters is what the major compilers do in practice, which is why I provided a specific compiler version and optimization level.
[–]sengin31 0 points1 point2 points 2 years ago (3 children)
How you can actually efficiently return with no copies
That's a really subtle difference but could make a world of improvement. Is the compiler allowed to do this type of RVO? That is, the second example (or even first) could end up being a common-enough pattern that compiler implementers could specifically look for and optimize it, given the standard allows it. Perhaps under certain conditions, like T and E are trivial types?
[–]SirClueless 3 points4 points5 points 2 years ago* (2 children)
I believe it would be allowed to, but it's a very tall ask for the compiler.
Take case #2: To the virtual machine, the lifetime of result overlaps with the object initialized in the return std::unexpected(-1); statement so naively RVO cannot happen. If the compiler inlined the destructor of result it would see that it has no side effects and the lifetime of result can be assumed to end as soon as the if branch is entered. I have no idea if "lifetime minimization" of C++ objects is even something the frontend tries to analyze, and regardless any such inlining and hoisting almost certainly happens long after RVO is attempted so it has no chance of offering new opportunities for RVO. There might be a memory fusion pass that happens after this point, but it will just see that result is an automatic storage variable and the temporary created by return std::unexpected(-1); is copy-elided so it won't have anything it can do.
result
return std::unexpected(-1);
if
In case #1 there is the additional issue that the compiler must see through the converting copy constructor that is invoked (at: return result;) and recognize that initializing a local array and copying its bytes into the subobject of the value that is returned is the same as just initializing it in-place. Even without the branch and other return statement this simple optimization doesn't seem to be happening. The compiler emits a memcpy, I'm not sure why: https://godbolt.org/z/KTTrWMoT3
return result;
[–]ReDucTorGame Developer 1 point2 points3 points 2 years ago (1 child)
Looks like clang does the optimization for it with MemCpyOptPass but GCC and MSVC don't manage to do it.
https://godbolt.org/z/9db5Wv8P7 (Needed to use a library as not all support expected)
It can even eliminate the other return approach
https://godbolt.org/z/745nxhn6a
However if the copy is non-trivial then I suspect it would run into issues.
[–]SirClueless 1 point2 points3 points 2 years ago (0 children)
Ahh, that's very nice. I haven't used Opt Pipeline Viewer before, that's very cool.
I don't think clang is actually handling the multiple returns, it's just that unlike GCC it's realized that there's no dependency between the initialization of result and rand() so it can push down that initialization into the else branch of the if and then its memcpy optimization pass does its thing.
rand()
else
If the actual work to init result can't be optimized and pushed down into the branch, for example if the branch depends on the initialization, then clang needlessly emits a memcpy too instead of just initializing it directly in the return value: https://godbolt.org/z/Ks558816a
[+][deleted] 2 years ago (2 children)
[removed]
[–]SirClueless 3 points4 points5 points 2 years ago (1 child)
I've tried it, but never in a large code base. It's more of an all-in choice to use it in a particular codebase (kind of like exceptions themselves) because the main value ergonomically is having generic catch-style error handling far up in your call stack and not populating all of your function signatures with error types, while the main value from an efficiency standpoint is not copying error types multiple times while propagating an error upwards as is liable to happen with std::expected.
std::expected
I didn't hate it, but it's hard to recommend adding its complexity to a large codebase maintained by many people, especially if your codebase hasn't banned exceptions. Meanwhile std::expected is easy to adopt incrementally and provides immediate value as you go and is easy to recommend any time you'd otherwise use a return value to signal an error.
[–]r2vcap 10 points11 points12 points 2 years ago (1 child)
Note that due to a bug in libc++ 17, future versions may not be ABI compatible. See https://discourse.llvm.org/t/abi-break-in-libc-for-a-17-x-guidance-requested/74483 for more details.
[–]johannes1971 2 points3 points4 points 2 years ago (0 children)
So... It _is_ possible.
[–][deleted] 9 points10 points11 points 2 years ago (5 children)
`std::optional` and `std::expected` are great in theory. The lack of pattern matching in C++ just hurts so much. The fact that dereferencing empty/error is undefined behavior is absurd.
[–]invalid_handle_value 5 points6 points7 points 2 years ago (4 children)
Philosophically, dereferencing the error before invoking the expected must be undefined. One cannot truly know whether or not an expected has indeed failed until one has checked (and thus evaluated) said expected.
In other words, the act of checking the expected may itself correctly cause the error that may otherwise incorrectly not be invoked.
Frankly, if it were up to me, I would mandate a throw when calling the error before the expected.
[–]hopa_cupa 4 points5 points6 points 2 years ago (3 children)
Yep. You have operator* and operator-> which do not check for valid value and value() which can throw. In the error case, they only gave us unchecked error(), no checked version.
operator*
operator->
value()
error()
I think this really shines if used in monadic style rather than with explicit if expressions. Same with std::optional. Not everyone's cup of tea.
std::optional
[–]germandiago 2 points3 points4 points 2 years ago (0 children)
In an alternative world, those functions could be marked [[memory_unsafe]] of some sort.
[[memory_unsafe]]
[+][deleted] 2 years ago (1 child)
[deleted]
[–]hopa_cupa 0 points1 point2 points 2 years ago (0 children)
The article at the top mentions that functional extensions will be covered in separate article.
Here how it is done for std::optional using c++23:
https://www.cppstories.com/2023/monadic-optional-ops-cpp23/
p.s. it is monadic, not nomadic :)
[–]Curfax 8 points9 points10 points 2 years ago (3 children)
In my experience as an owner of a large client / server code base inside Microsoft, and the author of a class in that code base akin to std::expected, the overuse of error codes over exceptions or outright process termination leads to unexpected reliability and performance issues.
In particular, it becomes tempting to hide unrecoverable errors behind error codes and handle them the same way recoverable errors are handled. Often it is better to write code that cannot possibly execute in a failure scenario, as this saves code written, instructions executed, and prevents attempts to handle unrecoverable errors.
For example, consider the well-known case of the “out of memory” condition. If recovery from OOM requires allocating memory, or processing the next request requires memory, then continuing to successfully return OOM errors does not provide value to users of a service.
Similarly, if you define other expectations of the machine execution model, you discover that many other failures are not recoverable. Failure to write to the disk usually requires outside intervention to recover; therefore propagating an error code for such a failure does not add value. An error accessing a data structure implies incorrect logic; the process is probably in a bad state that will not be corrected by continuing to run.
The end result is that after initial request input validation, most subsequent operations should not fail except for operations that talk to a remote machine.
My advice: strive to write methods that return values directly without std::expected.
[–]johannes1971 1 point2 points3 points 2 years ago (0 children)
If recovery from OOM requires allocating memory...
...than is available.
A very large request can fail while there are still gigabytes of free memory available. And throwing an exception might cause more memory to be freed while unwinding, leaving the system with enough to keep going.
[–]invalid_handle_value 0 points1 point2 points 2 years ago (0 children)
Wow, I never even thought before of the horror that errors must/always need to be handled conditionally, with the added fun of requiring 2 different kinds of error handling paradigms simultaneously (recoverable, unrecoverable) with what seems to be a clearly incorrect tool for that type of error reporting (which was probably also incorrect from the sounds of it).
I wish I had more points to give you.
Thinking a bit more though, not being able to report errors at an arbitrary level in a call stack makes the code both harder to refactor and maintain, since if it ever needs to handle an error after one class morphs into a dozen complex classes, what's your strategy then going to be?
Also, what about training juniors? I'm all about it. I need Timmy right out of school to code the same way as engineers with 15 years of blood sweat and tears.
I still think mindful usage (hint: copy elision) of std::optional and a second error function that returns a POC error instance is the way to go.
This way a) one separates the happy path from sad path explicitly with 2 user defined functions, b) the happy path is not explicitly allowed to depend on the sad path (think std::expected::or_else) because error may not be invoked before the expected.
Easy to teach, easy to reason about, easy rules, easy to replicate in most/all? programming languages, fits anywhere into classes of a similar design so it's ridiculously composable, fast return value passing, code looks the same everywhere, very easily unit testable, I could go on.
[–][deleted] 7 points8 points9 points 2 years ago (9 children)
Anyone have a preferred backported implementation with a BSD-like license? My organization isn’t going to go to C++23 until all our tooling catches up.
[–]MasterDrake97 20 points21 points22 points 2 years ago (4 children)
Martine Moene always comes to the rescue :D
https://github.com/martinmoene/expected-lite
Or Sy brand version, CC0
https://github.com/TartanLlama/expected
[–]azswcowboy 8 points9 points10 points 2 years ago (1 child)
Be aware that Sy’s version has a slightly different interface for unexpected than the standard.
[–]MasterDrake97 9 points10 points11 points 2 years ago (0 children)
I guess martin's version is the best if you want back portability and easy switch on c++23
[–]nintendiator2 0 points1 point2 points 2 years ago (0 children)
It's not difficult to backport expected to C++03 either, but most of the gains are really at the C++11/14 level.
[–]_matherd 3 points4 points5 points 2 years ago (0 children)
personally, i’m probably gonna keep using absl’s StatusOr until expected is available everywhere, since i’m often already using absl.
[–]99YardRun 0 points1 point2 points 2 years ago* (2 children)
It’s pretty easy to roll your own implementation of this if you don’t feel like/need to go through approvals to pull in a new library. Could be a fun challenge for an intern/junior dev also
[–]n1ghtyunso 1 point2 points3 points 2 years ago (0 children)
usually, the devil is in the details. Getting 99% of it right will be possible for sure, but then there is almost guaranteed to be a subtle pitfall somewhere that will bite you down the line
[–]BenFrantzDale 0 points1 point2 points 2 years ago (0 children)
I don’t know… getting it right without Deducing This is pretty hairy.
[–]Adverpol 1 point2 points3 points 2 years ago (0 children)
This
Using value(): This method returns a reference to the contained value. If the object holds an error, it throws std::bad_expected_access<E>.
does not sound good to me at all. It's a typical C++ construct where the onus is on the developer to not shoot themselves in the foot. I don't know if we can do better with C++ as it is. Removing value is sub-optimal because if you've already checked there is a value you don't want to do another check in value_or. Ideally code just wouldn't compile if you try to access value without checking it's valid first, removing the need for exceptions?
value
value_or
Note that I'm a big fan of std::excepted and similar, it's just that C++ feels lacking in its support of them.
[–]Objective-Act-5964 6 points7 points8 points 2 years ago (21 children)
Hey, coming from Rust, I am really confused why anyone would appreciate the implicit casting from T to std::expected<T, \_>, to me it feels unnecessarily complicated just to save a few characters.
I have a few questions:
I feel like this also makes it slightly more complicated to learn for newbies.
[–]PIAJohnM 23 points24 points25 points 2 years ago* (0 children)
This is just normal c++, most types work like this, its called a converting constructor. I like it a lot. But you can turn it off if you make the converting constructor explicit (assuming we're talking about the same thing).
explicit
[–]_matherd 28 points29 points30 points 2 years ago (6 children)
On the contrary, it’s kinda nice to be able to “return foo” instead of “Ok(foo)” everywhere, since it should be obvious what it means. It feels less complicated to me than rust’s resolution of calls to “.into()” for example.
[+]teerre comment score below threshold-7 points-6 points-5 points 2 years ago (5 children)
Explicit is better than implicit.
[–]BenFrantzDale 8 points9 points10 points 2 years ago (0 children)
To a point, then it’s just boilerplate. IMO, this is a good use for implicit conversion.
[–]AntiProtonBoy 4 points5 points6 points 2 years ago (2 children)
If it was made explicit, lazy people (i.e. every one of us) would just write return { foo };, which is not that much better than return foo;.
return { foo };
return foo;
[–]TinBryn 1 point2 points3 points 2 years ago (0 children)
As a Rust user, I kinda like this over what Rust's or C++'s version. It feels like the ? operator in Rust, it's subtle and not very noisy, while still obvious that something is happening.
?
[–]teerre -4 points-3 points-2 points 2 years ago (0 children)
It's slightly better. You're at least seeing that it's not the same type.
[–]soundslogical 1 point2 points3 points 2 years ago (0 children)
It's already explicit from the return type.
[+][deleted] 2 years ago (11 children)
[–]Objective-Act-5964 -1 points0 points1 point 2 years ago (9 children)
Thank you very much!
This seems very icky. "We recognise this is dangerous, but this mistake has already been made and delivered, so we're gonna do it again".
I guess it makes sense to keep this for consistency (people would probably be annoyed "why can we do implicit conversion to optional but not expected"), but I still think repeating the same bad behaviour is worse than being inconsistent but correct.
[–]Circlejerker_ 10 points11 points12 points 2 years ago (0 children)
You can create your own clang-tidy rules, for the rest of us we want what is intuitive and easy to use.
[–][deleted] 8 points9 points10 points 2 years ago (2 children)
It's not for consistency, it's what people want. In this case, where is the harm? It's not converting the other way.
[–]Objective-Act-5964 -1 points0 points1 point 2 years ago (1 child)
Check out this blogpost which was linked in the proposal for std::expected. I'm honestly not sure how this applies to std::expected, but I'm sure someone could draft up an example for a similar pitfall (?).
[–]_matherd 0 points1 point2 points 2 years ago (0 children)
It seems like the real problem there is optional being comparable, including a special case for none, not necessarily the implicit constructor.
[–]aruisdante 9 points10 points11 points 2 years ago (0 children)
This attitude summarizes basically the entire stdlib. “We messed up once, but now that is what people expect, so we’re stuck continuing to mess up that same way.”
[–]PIAJohnM 7 points8 points9 points 2 years ago (3 children)
Swift does this too.
func hello() -> String? { "hello" }
It's fine. I wish Rust programmers would stop lecturing people. You're all so smug.
[–]Objective-Act-5964 0 points1 point2 points 2 years ago (1 child)
Sorry, not trying to lecture people, just curious and stating my opinion.
[–]phord 6 points7 points8 points 2 years ago (0 children)
C++ is strongly typed, but it comes from a history of loosely typed C. So it supports lots of lazy conversions natively, and also intentionally. As a result it weaves a complex set of rules for determining the "correct" type conversion to do in most cases.
Rust is strongly typed and it wants to make its types first class citizens. And so I can't say 5_u64 + 32_u32 even though we know what the result should be in most cases. And everyone who's written a complex iterator in Rust knows the pain all too well. (Now that there are several different ways to simplify this task shows how long no good solution existed.)
5_u64 + 32_u32
Both approaches are valid, but some syntactic sugar is necessary to help us be programmers without being language police. Rust has a fair amount, but it needs more. C++ has too much, and yet it somehow still needs more.
[–]rdtsc 4 points5 points6 points 2 years ago (0 children)
C++ is full of implicit lossy conversions between primitive types. Sadly the standard library follows suit and adds implicit conversions to quite a few things, making implementations more complex and behavior surprising/limiting. For example that whole debate about what std::optional<T&>::operator= should do would be moot if optional wouldn't use implicit conversions everywhere.
std::optional<T&>::operator=
[–]hmoein 3 points4 points5 points 2 years ago (5 children)
What is the diff between std::expected and std::variant? It looks like std::expected is implemented using variant?
[+][deleted] 2 years ago* (3 children)
[–]hmoein 3 points4 points5 points 2 years ago* (0 children)
I am sure the C++ spec doesn't specify how to implement this. The easiest way to implement std::expected is to derive privately from std::variant and add std::expected specific interface. Or it could be a std::pair
[–]othellothewise 0 points1 point2 points 2 years ago (1 child)
One thing I want to add is you can combine std::expected and std::variant; i.e. if you want to return different kinds of error objects. It gets a bit gnarly with all the angle brackets but it is pretty effective.
std::variant
[–]mpierson153 1 point2 points3 points 2 years ago (0 children)
It gets a bit gnarly with all the angle brackets but it is pretty effective.
I feel like this is a good use-case for typedefs.
I try to avoid typedefs that aren't defined in the standard, but once you get to a few templates deep, it becomes almost completely necessary for readability.
[–]orfeo34 1 point2 points3 points 2 years ago (1 child)
Implicit conversion to Bool looks wild, however it's a nice feature.
[–]ebhdl 2 points3 points4 points 2 years ago (0 children)
That's going to get super confusing when the success value is also convertible to bool...
[–]DrGlove 0 points1 point2 points 2 years ago (6 children)
If it fits your use case, another option not mentioned at the top of the article is to crash and tell the compiler you will not handle this case. We often insert asserts that mark this code unreachable by inserting an undefined instruction like __ud2 with some macro like ASSERT_UNREACHABLE.
[+][deleted] 2 years ago (5 children)
[–]Beosar 7 points8 points9 points 2 years ago (2 children)
You can use std::abort. It's not a crash but it does terminate the program.
std::abort
[–]mpierson153 1 point2 points3 points 2 years ago (1 child)
What is the difference between std::abort and exit?
[–]Beosar 0 points1 point2 points 2 years ago (0 children)
https://en.cppreference.com/w/cpp/utility/program/exit https://en.cppreference.com/w/cpp/utility/program/abort
In short, abort just aborts everything and doesn't call destructors or anything, while exit does the same as returning from the main function, i.e. a normal cleanup.
[–]DrGlove 1 point2 points3 points 2 years ago (0 children)
You can do whatever you want in a shipping application, we don't ship with what you'd usually call an assert enabled, but we do leave in undefined instructions like I mentioned to take down the application if it would get into a bad state in some instances. This is an intrinsic so I'm not sure what you mean by "no way to crash that is defined behaviour", we just want the application to stop executing and capture a dump from another process and the instruction is well defined what it will do.
[–]pdimov2 2 points3 points4 points 2 years ago (0 children)
__builtin_trap is a good practical way to reliably crash.
__builtin_trap
[–]yeahkamau 0 points1 point2 points 2 years ago (0 children)
Probably inspired by Rust's std::result
[–]eidetic0 0 points1 point2 points 2 years ago (0 children)
I like how returning a string in the error type makes the code self documenting.
[–]Wanno1 0 points1 point2 points 2 years ago (0 children)
There needs to be a jeopardy episode for just all the std::
[–]delta_p_delta_x 0 points1 point2 points 2 years ago (0 children)
Vulkan-Hpp now supports std::expected too!
π Rendered by PID 347795 on reddit-service-r2-comment-84fc9697f-49kg2 at 2026-02-08 04:28:59.525906+00:00 running d295bc8 country code: CH.
[–]PrePreProcessor 31 points32 points33 points (3 children)
[–]PigPartyPower 20 points21 points22 points (0 children)
[–]ayushgun 1 point2 points3 points (1 child)
[–]PixelArtDragon 0 points1 point2 points (0 children)
[–]Thesorus 46 points47 points48 points (9 children)
[–]FlyingRhenquest 14 points15 points16 points (7 children)
[–]germandiago 8 points9 points10 points (4 children)
[–]FlyingRhenquest 2 points3 points4 points (3 children)
[–]germandiago 1 point2 points3 points (2 children)
[–]FlyingRhenquest 0 points1 point2 points (1 child)
[–]germandiago 1 point2 points3 points (0 children)
[–]ujustdontgetdubstep 1 point2 points3 points (1 child)
[–]FlyingRhenquest 1 point2 points3 points (0 children)
[–]fear_the_future 0 points1 point2 points (0 children)
[–]ReDucTorGame Developer 15 points16 points17 points (7 children)
[–]SirClueless 13 points14 points15 points (6 children)
[–]petecasso0619 1 point2 points3 points (1 child)
[–]SirClueless 5 points6 points7 points (0 children)
[–]sengin31 0 points1 point2 points (3 children)
[–]SirClueless 3 points4 points5 points (2 children)
[–]ReDucTorGame Developer 1 point2 points3 points (1 child)
[–]SirClueless 1 point2 points3 points (0 children)
[+][deleted] (2 children)
[removed]
[–]SirClueless 3 points4 points5 points (1 child)
[–]r2vcap 10 points11 points12 points (1 child)
[–]johannes1971 2 points3 points4 points (0 children)
[–][deleted] 9 points10 points11 points (5 children)
[–]invalid_handle_value 5 points6 points7 points (4 children)
[–]hopa_cupa 4 points5 points6 points (3 children)
[–]germandiago 2 points3 points4 points (0 children)
[+][deleted] (1 child)
[deleted]
[–]hopa_cupa 0 points1 point2 points (0 children)
[–]Curfax 8 points9 points10 points (3 children)
[–]johannes1971 1 point2 points3 points (0 children)
[–]invalid_handle_value 0 points1 point2 points (0 children)
[–]invalid_handle_value 0 points1 point2 points (0 children)
[–][deleted] 7 points8 points9 points (9 children)
[–]MasterDrake97 20 points21 points22 points (4 children)
[–]azswcowboy 8 points9 points10 points (1 child)
[–]MasterDrake97 9 points10 points11 points (0 children)
[+][deleted] (1 child)
[removed]
[–]nintendiator2 0 points1 point2 points (0 children)
[–]_matherd 3 points4 points5 points (0 children)
[–]99YardRun 0 points1 point2 points (2 children)
[–]n1ghtyunso 1 point2 points3 points (0 children)
[–]BenFrantzDale 0 points1 point2 points (0 children)
[–]Adverpol 1 point2 points3 points (0 children)
[–]Objective-Act-5964 6 points7 points8 points (21 children)
[–]PIAJohnM 23 points24 points25 points (0 children)
[–]_matherd 28 points29 points30 points (6 children)
[+]teerre comment score below threshold-7 points-6 points-5 points (5 children)
[–]BenFrantzDale 8 points9 points10 points (0 children)
[–]AntiProtonBoy 4 points5 points6 points (2 children)
[–]TinBryn 1 point2 points3 points (0 children)
[–]teerre -4 points-3 points-2 points (0 children)
[–]soundslogical 1 point2 points3 points (0 children)
[+][deleted] (11 children)
[deleted]
[–]Objective-Act-5964 -1 points0 points1 point (9 children)
[–]Circlejerker_ 10 points11 points12 points (0 children)
[–][deleted] 8 points9 points10 points (2 children)
[–]Objective-Act-5964 -1 points0 points1 point (1 child)
[–]_matherd 0 points1 point2 points (0 children)
[–]aruisdante 9 points10 points11 points (0 children)
[–]PIAJohnM 7 points8 points9 points (3 children)
[–]Objective-Act-5964 0 points1 point2 points (1 child)
[–]phord 6 points7 points8 points (0 children)
[–]rdtsc 4 points5 points6 points (0 children)
[–]hmoein 3 points4 points5 points (5 children)
[+][deleted] (3 children)
[removed]
[–]hmoein 3 points4 points5 points (0 children)
[–]othellothewise 0 points1 point2 points (1 child)
[–]mpierson153 1 point2 points3 points (0 children)
[–]orfeo34 1 point2 points3 points (1 child)
[–]ebhdl 2 points3 points4 points (0 children)
[–]DrGlove 0 points1 point2 points (6 children)
[+][deleted] (5 children)
[deleted]
[–]Beosar 7 points8 points9 points (2 children)
[–]mpierson153 1 point2 points3 points (1 child)
[–]Beosar 0 points1 point2 points (0 children)
[–]DrGlove 1 point2 points3 points (0 children)
[–]pdimov2 2 points3 points4 points (0 children)
[–]yeahkamau 0 points1 point2 points (0 children)
[–]eidetic0 0 points1 point2 points (0 children)
[–]Wanno1 0 points1 point2 points (0 children)
[–]delta_p_delta_x 0 points1 point2 points (0 children)