News for hackers. Stuff that matters.
Re:Const all the things? by PaulDavisThe1st on Monday January 24, 2022 @11:20AM (#30059651)
for performance-oriented code, the original example, where the argument is stack-allocated in the caller, passed by reference, and used based on the return value, has benefits that can't be replicated in the std::optional<> version.

I like the std::optional<> version and use that pattern some of the time. But if the object being passed/returned to/from do_something() is non-trivial, i don't want the copy overhead.

Re:Const all the things? by kaashif on Monday January 24, 2022 @01:06PM (#30061413)
> for performance-oriented code, the original example, where the argument is stack-allocated in the caller, passed by reference, and used based on the return value, has benefits that can't be replicated in the std::optional<> version.

Can you go into detail? What are the benefits that can't be replicated?

If anything, the std::optional version seems better, since we can avoid an invocation of the SomeType constructor. Otherwise, everything is the same - everything's allocated on the stack, there is no dynamic allocation.

> If an optional<T> contains a value, the value is guaranteed to be allocated as part of the optional object footprint, i.e. no dynamic memory allocation ever takes place. Thus, an optional object models an object, not a pointer, even though operator*() and operator->() are defined.

That's from here: https://en.cppreference.com/w/cpp/utility/optional

Since C++17, RVO is required by the standard too:

> Return value optimization is mandatory and no longer considered as copy elision; see above.

From here: https://en.cppreference.com/w/cpp/language/copy_elision

I admit I'm not really a C++ expert, so maybe I'm missing something.

Re:Const all the things? by PaulDavisThe1st on Monday January 24, 2022 @01:45PM (#30062020)
Yes, in C++17, RVO would fix the issue. Alas, some of us are stuck with project conventions that have not reached "use C++17". Without RVO, there's an extra copy.
Re:Const all the things? by masklinn on Monday January 24, 2022 @03:05PM (#30063219)
RVO is not new in C++17 though, only the standard requiring it in some cases.

Unless your compiler is truly ancient odds are good it RVOs just fine no?

Re:Const all the things? by Kranar on Monday January 24, 2022 @11:56AM (#30060304)
There is no copy involved with the std::optional version.
Re:Const all the things? by cyber_kinetist on Monday January 24, 2022 @12:38PM (#30060984)
The thing is, are we sure?

Probably many C++ aficionados will run to godbolt.org to prove this in a simple testcase, and they will probably be right. But then maybe it’s because you’ve only tested this for primitive or POD types. Maybe this might not be guaranteed for non-POD types with custom constructors? Or maybe this might be okay because of RVO or something? Hmm, let us read the specs again…

The problem is, C++ is a language that is very unintuitive about how your code is going to get mapped to actual hardware (assembly code). For many systems developers, it isn’t enough that the compiler might optimize this smartly; we instead want predictable compiler behavior. So if you want to make sure, and you’re not confident about the gnarly details of the C++ specification, it will be better for you just use out parameters instead of std::optional, if you are in the situation where you really need to squeeze out performance (which happens a lot for low-level systems programming).

Re:Const all the things? by Kranar on Monday January 24, 2022 @12:51PM (#30061191)
Yes we are sure and it has nothing to do with optimizations, RVO, Godbolt or any of the completely irrelevant details you are talking about.

The implementation of std::optional is not permitted by the standard to allocate memory.

Re:Const all the things? by cyber_kinetist on Monday January 24, 2022 @01:48PM (#30062069)
Note that I’m not talking about if std::optional itself allocates more than it needs to at construction (which I know it doesn’t, as cppreference.com says so), but if the compiler might generate an additional copy constructor call if it is value-returned from a function (which I’m worried about since NRVO isn’t in the spec and you can’t rely on it).

It’s more specific to the example code the original commenter posted (and about general out-parameter usage) than the flaws of std::optional itself. Maybe this didn’t get communicated properly from my comment.

Re:Const all the things? by PaulDavisThe1st on Monday January 24, 2022 @01:48PM (#30062062)
For C++17, true. Not so if you're using an earlier compiler and/or language standard. Yes, yes, I know we should all get with the program, but that's alas not how the world operates.
Re:Const all the things? by Kranar on Monday January 24, 2022 @01:57PM (#30062210)
There is no std::optional in earlier language standards. std::optional is a C++17 library feature.
Re:Const all the things? by tsimionescu on Monday January 24, 2022 @02:46PM (#30062922)
Even for C++ 17, this is only guaranteed if you don't name the variable in your function. NRVO is not guaranteed at all. There is even an example downthread where gcc can't do it even at -O3.
Re:Const all the things? by PaulDavisThe1st on Monday January 24, 2022 @02:04PM (#30062298)
boost::optional has existed for many, many years and does not require compiler/language support. AFAIK, the behavior is substantially identical to std::optional.