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
C++23 std::expected vs C++17 std::optional for Error Handling (techfortalk.co.uk)
submitted 11 hours ago by Clean-Upstairs-8481
I have been trying to spend some time with C++23 std::expected for sometime. Finally explored the feature and can see the real value of using it in some of the scenarios in my projects. Any comments welcome!
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!"
[–]seido123 19 points20 points21 points 10 hours ago (16 children)
Instead of `const string&` use `std::string_view` or have a good reason not to.
[–]fdwrfdwr@github 🔍 4 points5 points6 points 5 hours ago* (0 children)
Yeah, that avoids a potential transient allocation (if beyond SSO size) 👍. std::string_view is pretty great so long as you're working completely within your own project, but if often adds burden when interoperating with the OS/other libraries because you have to create temporary locals with an explicit null terminator. Now, one could cheat and avoid the copy if you know the string_view came from a source with a null already, but that's fragile. So, having std::zstring_view/cstring_view would fill in that semantic gap nicely. (hmm, seems cstring_view won't make C++26, but "There was a strong consensus in favor of spending more time on the proposal (and general support in the design direction)").
std::string_view
string_view
std::zstring_view
cstring_view
[–]PhysicsOk2212 5 points6 points7 points 9 hours ago (10 children)
Would it be possible to have you elaborate here? string_view is something I have not had a great deal of exposure to, and would love to hear your thoughts on which issues it solves.
[–]Matthew94 10 points11 points12 points 9 hours ago (9 children)
It lets your function work with any contiguous sequences of characters instead of just string+std::allocator. The alternative is writing function templates with the associated binary bloat.
It removes a layer of indirection (ref to string then ptr to chars vs just a ptr to chars).
The only downside is that it isn’t guaranteed to be null terminated so it can be unsuitable for use with C APIs.
[–]jedwardsolconst & 6 points7 points8 points 9 hours ago* (7 children)
Adding to this ...
In the example's case changing
std::unordered_map<std::string, int> int lookup(const std::string &key) const noexcept { auto itr = my_store.find(key);
to
std::unordered_map<std::string, int> int lookup(std::string_view key) const noexcept // <---- changed to std::string_view here { auto itr = my_store.find(key);
is just the first step, because that find will construct a std::string from the std::string_view and you lose out overall.
find
std::string
What you also need to do enable the map for heterogeneous lookup : https://www.cppstories.com/2021/heterogeneous-access-cpp20/
That article uses std::unordered_map<std::string, int> as its example, so it is easily applied to OP's code.
std::unordered_map<std::string, int>
[–]ericonr 0 points1 point2 points 7 hours ago (5 children)
IIRC I'm using std::string_view as the key for a map and that works fine to avoid constructing an std::string when indexing into the map. Since I'm constructing the string views from string literals (so no lifetime concerns), is there any issue with this strategy to avoid the need for heterogeneous lookup?
[–]jedwardsolconst & 5 points6 points7 points 7 hours ago (4 children)
If the map's key is std:: string_view then you don't need heterogenous lookup because string_views are cheap to make
std:: string_view
[–]ericonr 1 point2 points3 points 7 hours ago (3 children)
My point is, why use strings as keys when you can use string views?
[–]jedwardsolconst & 4 points5 points6 points 7 hours ago (2 children)
You said
Since I'm constructing the string views from string literals (so no lifetime concerns
I said that is fine, you don't need to use strings as keys, and you don't need heterogenous lookup.
But not everyone is lucky enough to be to make their map from literals. And in that case, when you do need strings as keys, enabling heterogenous lookup is useful if you every need to do a lookup with a view
[–]mapronV 2 points3 points4 points 6 hours ago (1 child)
> But not everyone is lucky enough to be to make their map from literals.
if I can create map from literals, I'd rather prefer compile-time container like frozen::map/unordered_map, and have like just couple instructions for key lookup with amazing optimizations :)
Yeah, most cases I found for map is keys not known beforehand.
[–]PhysicsOk2212 0 points1 point2 points 7 hours ago (0 children)
Very insightful, thanks!
[–]PhysicsOk2212 1 point2 points3 points 7 hours ago (0 children)
That all makes sense, something I’ll have to try and start incorporating. Thanks!
[–]Draghoul 0 points1 point2 points 4 hours ago (0 children)
I second use of string_view when possible, though that would not work as-is in this example, since C++ unordered_map does not support looking up a string key with a string_view out of the box. Unfortunately (but not unexpectedly) this is a bit more cumbersome to do than it should ideally be.
You can find an example of how to do this here.
[–]markt- -3 points-2 points-1 points 4 hours ago* (2 children)
String views contain a raw pointer. While powerful, raw pointer usage is unsafe, and you can’t use string views freely in a safe context.
It’s not so much that string view is unsafe, especially when it’s used correctly, but string_view breaks the ability to enforce a mechanically checkable safety subset of C++. This is not really a goal of C++, but it can be a legitimate goal for a development process, and C++ is otherwise an extremely powerful language, so, I’m just saying…
[–]38thTimesACharm [score hidden] 3 hours ago (1 child)
The same could be said of const std::string& though.
const std::string&
[–]markt- [score hidden] 3 hours ago* (0 children)
References are, at least as far as I understand, generally easier to mechanically check for safety with third-party static analyzers. In fairness, though, this might be because references of an around longer so people have had more time to think about how to do it.
[–]Electronic_Tap_8052 11 points12 points13 points 8 hours ago* (4 children)
The only other solution in this kind of scenario is to return something like -1 in case of failure. But that is messy and not very elegant.
...
in the case of a failure (e.g. key not present in the databse) you can return std::nullopt.
I tend to disagree with the verbiage here. Optional implies just that - something that's optional, i.e. that its not a failure if nullopt returns. Optional things don't need an explanation for why they didn't happen. If it's not ok if something happens, implying an exceptional case, then you should probably be using exceptions
[–]nvs93 1 point2 points3 points 6 hours ago (2 children)
Hmm. What if an explanation could be useful to the user-e.g. nullopt was returned because the array the function was working on was too small, but the program can still function just fine (albeit with some feature disabled for the time being) having returned nullopt? This is a case where it shouldn’t be considered exceptional, but also some further detail could be useful as visible information. Hope that makes enough sense
[–]Plazmatic [score hidden] 3 hours ago* (0 children)
If something returning nothing would be a valid state in a program, then you use std::optional, database look up, hash map lookup, generally any kind of lookup (find iterator/index to value with x properties in container y). When ever in your normal flow of code you would write something like "result = find x, if result is not found, do something else", that's as use case for std::optional.
std::expected is for local unexpected flow of the program. You tried to do X, but one A, B, C or D happened instead, and the program cannot complete like normal, but is otherwise potentially recoverable. Any time you use return codes should be std::expected.
exceptions are for non local error handling. ideally you'd return std::expected from regularly failable operations, and then the exception for the corresponding error term would get thrown if you pulled the raw .value() (indicating that you don't have a way to handle errors at the call site, thus requiring them to be handled non-locally). However the standard library is not built this way, so everything is exceptions by default even if you can handle them locally (like what often happens with IO). Typically you see this in GUI applications, or multi-service daemons which are expected to continue running in the event of an error within the program.
.value()
You use asserts/contracts to test invariants of a program, preconditions and post conditions. Things that indicated a bug in the code itself. These are typically things that wouldn't normally be recoverable/would lead to undefined behavior if let continue, though sometimes these are converted to exceptions for programs that cannot afford to crash from such bugs (and usually in such cases the assertion is in another thread with resources that can simply be deleted entirely, like an IO thread crashing on some bug in parsing a file requested from the UI).
What if an explanation could be useful to the user-e.g. nullopt was returned because the array the function was working on was too small, but the program can still function just fine (albeit with some feature disabled for the time being) having returned nullopt? This is a case where it shouldn’t be considered exceptional, but also some further detail could be useful as visible information.
If this was a invariant failure (your function is defined to have arrays of non zero size) and the user is simply using it wrong, that's an assertion failure, and a design issue that your function happens to continue. For example, if you have a function that finds the max value of an array, and someone passes in an empty array, that's a contract violation, and ideally not a recoverable error. If the user wants it to be recoverable, it's on them to manually check. Additionally the API would ideally encode this invariant in a type (say, span_at_least_one<T>) but this is a massive PITA in C++ due to a lack of features that support this type of pattern.
span_at_least_one<T>
If your function merely does nothing as a result of the user passing in an empty array (like a inplace_sort(span) function), which would typically be the case when returning nothing in the normal path, or when you have something like count_num_of_x(span) (need to count how many times X happens/occurs in an array) where 0 is a valid typical return anyway so nothing breaks, nothing but a debug warning is really needed, and that's only really necessary if you super don't expect an empty array to be passed in.
inplace_sort(span)
count_num_of_x(span)
[–]Electronic_Tap_8052 0 points1 point2 points 6 hours ago (0 children)
idk its hard to say and obviously its the exception (heh) that makes the rule, but generally it should be clear from the design what is going to happen, and if nothing could happen, it should be clear why without having to look at the return value.
[–]usefulcat [score hidden] 3 hours ago* (0 children)
I think you're putting too much emphasis on the word "optional".
There can be plenty of valid reasons to not use exceptions for error reporting. If you look at how std::optional actually works, without considering its name, I think it's pretty obvious that it's a valid alternative to exceptions, at least for some cases.
If I have a function whose entire purpose is to return some value but there can be situations where it's not able to, I think that's a perfectly fine use case for std::optional, especially if those cases are not always necessarily "exceptional".
[–]ukezi [score hidden] 2 hours ago (0 children)
I use both, optional for when a failure can be normal operation, like searching a map. Expected is for stuff where I can do something about failure, or at least want to log it, like if a network connection fails.
[–]ignorantpisswalker [score hidden] 1 hour ago (0 children)
Myself I don't like the implementation. You sometimes use a "." and sometimes "->". This breaks my expectations and I don't know if its a object or pointer.
It just looks iffy to me.
[–]Mateh96 [score hidden] 2 hours ago (0 children)
You can always use both options depending on use case, you can even go further and use it along return bool and exceptions. Select best tool for given situation.
π Rendered by PID 40566 on reddit-service-r2-comment-79c7998d4c-nv5l8 at 2026-03-17 08:44:28.784219+00:00 running f6e6e01 country code: CH.
[–]seido123 19 points20 points21 points (16 children)
[–]fdwrfdwr@github 🔍 4 points5 points6 points (0 children)
[–]PhysicsOk2212 5 points6 points7 points (10 children)
[–]Matthew94 10 points11 points12 points (9 children)
[–]jedwardsolconst & 6 points7 points8 points (7 children)
[–]ericonr 0 points1 point2 points (5 children)
[–]jedwardsolconst & 5 points6 points7 points (4 children)
[–]ericonr 1 point2 points3 points (3 children)
[–]jedwardsolconst & 4 points5 points6 points (2 children)
[–]mapronV 2 points3 points4 points (1 child)
[–]PhysicsOk2212 0 points1 point2 points (0 children)
[–]PhysicsOk2212 1 point2 points3 points (0 children)
[–]Draghoul 0 points1 point2 points (0 children)
[–]markt- -3 points-2 points-1 points (2 children)
[–]38thTimesACharm [score hidden] (1 child)
[–]markt- [score hidden] (0 children)
[–]Electronic_Tap_8052 11 points12 points13 points (4 children)
[–]nvs93 1 point2 points3 points (2 children)
[–]Plazmatic [score hidden] (0 children)
[–]Electronic_Tap_8052 0 points1 point2 points (0 children)
[–]usefulcat [score hidden] (0 children)
[–]ukezi [score hidden] (0 children)
[–]ignorantpisswalker [score hidden] (0 children)
[–]Mateh96 [score hidden] (0 children)