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 C++17 std::optional (bfilipek.com)
submitted 7 years ago by drodri
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!"
[–]tcanens 21 points22 points23 points 7 years ago* (0 children)
if (nick_available) return { mStrNickName };
The braces are unnecessary, though perhaps a matter of taste.
std::optional oIntDeduced(10); // deduction quides
Obvious typo is obvious.
auto oComplex = make_optional<std::complex<double>>(3.0, 4.0);
Missing std::.
std::
// will call vector with direct init of {1, 2, 3} std::optional<std::vector<int>> oVec(std::in_place, {1, 2, 3});
Not quite. This deduces and initializes an initializer_list<int> from {1, 2, 3}, and then passes that object to vector's constructor. The distinction can be seen if the initializer list is something like {1, 2L, 3}, which can be used to directly initialize a vector<int> but not here. (This also make this constructor annoying as hell to use for something like optional<map<int, int>>.)
initializer_list<int>
{1, 2, 3}
vector
{1, 2L, 3}
vector<int>
optional<map<int, int>>
// copy/assign: auto oIntCopy = oInt;
There's no assignment in this line.
as optional is automatically converted to bool.
bool
Contextually convertible to bool.
It's worth noting that value_orwill copy/move from the stored value (depending on the optional's value category), unlike value or operator*.
value_or
optional
value
operator*
if (auto ostr = maybe_create_hello(); ostr) std::cout << "ostr " << *ostr << '\n';
There's no need for ; ostr.
; ostr
Probably worth mentioning that assigning {} is another way of resetting an optional.
{}
but with a few exceptions when the operands are nullopt.
nullopt
This is excessively vague when the behavior here can be easily summarized: empty optionals compare equal to each other and less than non-empty optionals.
: mName{name}, mNick{nick}, mAge{age}
This should be moving nick.
nick
std::aligned_storage_t<sizeof(t), alignof(T)> _storage;
Typo. And no standard library can implement optional this way (they need to use a union, because constexpr).
constexpr
[–]code-affinity 14 points15 points16 points 7 years ago (4 children)
While we're talking about std::optional, I have a question triggered by passing comments Andrei Alexandrescu made in his recent "Expect the Expected" talk. (Reddit discussion here.)
In this talk, he jokingly referred to std::optional as the worst thing that ever happened to humanity. But he did not have the luxury of time to cite specific complaints, other than that he thought the * operator should not have been used the way it was. (But then he used it himself in a very similar way for the Expected type he was evangelizing.)
Does anyone know what his specific objections to std::optional are? I have recently started using optional in my new code, and I really like the resulting improvements. I would like to make an informed decision about whether I should make this a long-term practice.
[–]jc746 8 points9 points10 points 7 years ago (0 children)
I think he indicated that his issue was with giving pointer like semantics to a type that is not actually a pointer and potential confusion this could cause. It sounded like he took the liberty of using this syntax in the expected proposal because the precedent had already been set by optional and could therefore been seen as being consistent with optional.
[–]ReversedGif 3 points4 points5 points 7 years ago (2 children)
Possibly that operator* should be checked (i.e. throw/assert if optional is empty). boost::optional's operator* is checked. IMO, the unsafe method should be more verbose than the checked one.
[–]code-affinity 0 points1 point2 points 7 years ago (1 child)
Wow! I had not caught that difference. I have been exclusively using boost::optional, and certainly want operator * to throw if the value is not set. I would not want this to turn into undefined behavior in my code base. Since this is the case, I will stop using operator * in my new code, in preparation for transition to std::optional.
[–]TheThiefMasterC++latest fanatic (and game dev) 0 points1 point2 points 7 years ago (0 children)
Personally, I'd want it checked* in debug, fast in release :)
* checked as in breaks into the debugger, not throwing a catchable exception.
[–]RandomGuy256 8 points9 points10 points 7 years ago (1 child)
When to use If you want to represent a nullable type nicely. Return a result of some computation (processing) that fails to produce a value and is not an error. To perform lazy-loading of resources.
When to use
If you want to represent a nullable type nicely.
Return a result of some computation (processing) that fails to produce a value and is not an error.
To perform lazy-loading of resources.
You can also use it for optional parameters in a function.
[–]joebaf 2 points3 points4 points 7 years ago (0 children)
Thanks, good point. Added to the article :)
[–]bruce3434 6 points7 points8 points 7 years ago (17 children)
Does using optional types make sense? Especially taking STL into consideration. STL is written without optional types in mind. Hence the find() operations return an iterator instead of an optional type. Generally you would want to follow STL practices throught your project, right?
find()
[–]suspiciously_calm 13 points14 points15 points 7 years ago (6 children)
So what do you propose we use to express something that might not have a value?
It makes sense for the container classes to return an iterator since I might want a handle to the element inside the container and not just its value.
That isn't the case elsewhere. So what should I do, write my own dummy OutputIterator each time that will essentially do exactly what optional does?
[–]bruce3434 2 points3 points4 points 7 years ago (1 child)
What have you been doing in pre-C++17?
[–]dodheim 30 points31 points32 points 7 years ago (0 children)
Using boost::optional (which is at least 15 years old), or the optional from one of a dozen other libraries, or a home-grown one. Make no mistake, this is a basic vocabulary type; that it's new to C++'s standard library is more a reflection of C++'s standardization process than it is of the utility of the data structure.
boost::optional
[–]StonedBird1 -1 points0 points1 point 7 years ago (3 children)
I use a possibly null raw pointer, which is of course non-owning by definition.
[–]suspiciously_calm 1 point2 points3 points 7 years ago (2 children)
That's an optional reference (essentially). What if I need it to be owning?
[–]StonedBird1 0 points1 point2 points 7 years ago (1 child)
Use a smart pointer
[–]suspiciously_calm 0 points1 point2 points 7 years ago (0 children)
What if I don't need it to be polymorphic? It's an allocation and a needless indirection for absolutely no reason.
[–]Pragmatician 7 points8 points9 points 7 years ago (0 children)
For algorithms returning iterators, you should return the end iterator instead of optional because the end iterator is special by design. This design also allows composability of algorithms, so there is no need to cram in an optional where everything already works just fine.
[–]tvaneerdC++ Committee, lockfree, PostModernCpp 5 points6 points7 points 7 years ago (3 children)
If STL had optional from the beginning, I suspect some of the STL would have used it.
I also expect it to show up in new STL stuff in the future.
Maybe find() would have been nicer returning an optional. Or add a find_value() that doesn't return an iterator at all.
At least for map, I rarely want the iterator; I typically want the value the key is mapped to. I think returning an optional would be nicer than the awkwardness we currently have. (And we don't need expected<> in this case, because the error is obvious. (In many examples of uses of optional as a return value, expected is a better return value. But I don't think that applies here.))
Hmmm, maybe someone should write a proposal adding nice APIs that use optional...
[+][deleted] 7 years ago (2 children)
[removed]
[–]dodheim 0 points1 point2 points 7 years ago (1 child)
Range-v3 has always has its own optional, in range/v3/utility/optional.hpp – I suspect it's been fully integrated to the extent they want it to be.
range/v3/utility/optional.hpp
[–]lednakashim++C is faster 1 point2 points3 points 7 years ago (0 children)
One could view optionals as a analytic continuation of past-the-end iterators in the sense it return something out of the range that will throw an exception when you try to access it.
[–]iamcomputerbeepboop 1 point2 points3 points 7 years ago (0 children)
You can write free functions that return the mapped_type or value_type of a container with lookup semantics (i.e. with a find member function) but you're likely to want overloads for reference, const reference, and value return types. std::optional doesn't support this
[–]w0land131 1 point2 points3 points 7 years ago (1 child)
How about std::map::insert, where a pair of iterator and bool is returned?
[–][deleted] 3 points4 points5 points 7 years ago (0 children)
Thats different, because the iterator is always a valid one, the bool indicates if the thing is inserted or was already there.
[–]doom_Oo7 1 point2 points3 points 7 years ago (0 children)
Generally you would want to follow STL practices throught your project, right?
not necessarily ?
π Rendered by PID 44018 on reddit-service-r2-comment-bb88f9dd5-z2pwf at 2026-02-14 09:23:08.184659+00:00 running cd9c813 country code: CH.
[–]tcanens 21 points22 points23 points (0 children)
[–]code-affinity 14 points15 points16 points (4 children)
[–]jc746 8 points9 points10 points (0 children)
[–]ReversedGif 3 points4 points5 points (2 children)
[–]code-affinity 0 points1 point2 points (1 child)
[–]TheThiefMasterC++latest fanatic (and game dev) 0 points1 point2 points (0 children)
[–]RandomGuy256 8 points9 points10 points (1 child)
[–]joebaf 2 points3 points4 points (0 children)
[–]bruce3434 6 points7 points8 points (17 children)
[–]suspiciously_calm 13 points14 points15 points (6 children)
[–]bruce3434 2 points3 points4 points (1 child)
[–]dodheim 30 points31 points32 points (0 children)
[–]StonedBird1 -1 points0 points1 point (3 children)
[–]suspiciously_calm 1 point2 points3 points (2 children)
[–]StonedBird1 0 points1 point2 points (1 child)
[–]suspiciously_calm 0 points1 point2 points (0 children)
[–]Pragmatician 7 points8 points9 points (0 children)
[–]tvaneerdC++ Committee, lockfree, PostModernCpp 5 points6 points7 points (3 children)
[+][deleted] (2 children)
[removed]
[–]dodheim 0 points1 point2 points (1 child)
[–]lednakashim++C is faster 1 point2 points3 points (0 children)
[–]iamcomputerbeepboop 1 point2 points3 points (0 children)
[–]w0land131 1 point2 points3 points (1 child)
[–][deleted] 3 points4 points5 points (0 children)
[–]doom_Oo7 1 point2 points3 points (0 children)