std::optional::value()
has the following two overloads
constexpr T& value() &;
constexpr const T & value() const &;
constexpr T&& value() &&;
constexpr const T&& value() const &&;
What is the point of returning a const rvalue reference?
The only reason I can think of is to enable the compiler to help catch undefined behavior in (really really weird) cases like the following
auto r = std::cref(const_cast<const std::optional<int>&&>(
std::optional<int>{}).value());
Where if the std::optional::value()
had returned a const T&
then the above code would compile and would lead to undefined behavior when the r
reference_wrapper
was used later.
Is there any other corner case in mind with the above returning a const T&&
?
Rvalue references is a small technical extension to the C++ language. Rvalue references allow programmers to avoid logically unnecessary copying and to provide perfect forwarding functions. They are primarily meant to aid in the design of higer performance and more robust libraries.
Typically rvalues are temporary objects that exist on the stack as the result of a function call or other operation. Returning a value from a function will turn that value into an rvalue. Once you call return on an object, the name of the object does not exist anymore (it goes out of scope), so it becomes an rvalue.
So an rvalue can be used both with rvalue overloads and a const lvalue reference.
Sure. You have a const optional<T>
in struct. You return an rvalue instance and access the optional member.
Because of how you constructed it, you can guarantee the optional is engaged in this case. So you call value()
. The type T
contains mutable
state that can be efficiently be reused/stolen. The T const&&
overload gives the consuming function permission to steal that state.
struct mutable_type {
mutable std::vector<char> cache;
};
struct test_type {
const std::optional<mutable_type> bob;
};
test_type factory( int x ) {
if (x==0) return {};
return {mutable_type({{1,2,x}})};
}
auto moved_into = factory(3).bob.value().cache;
This, I believe, moves the vector
within bob
, which is a const
rvalue in this context. It relies on value()
returning a const&&
in a const&&
context.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With