C++ Logo


Advanced search

Re: std::get on const rvalue

From: Julien Villemure-Fréchette <julien.villemure_at_[hidden]>
Date: Wed, 07 Dec 2022 14:26:54 -0500
> The background is that some people in the team are arguing that we
should forbid std::move on const objects.

That's not exactly right, its not about calling std::move or not:, there's a very important distinction between calling std::move on an expression and move constructing/move assigning from an object. A precise, more insightful way to express the guideline is:

"If an object is going to be moved from, then it must not be declared const".

Application of this rule is not concerned with the correct uses of std::move itself (there are other guidelines for this). Actually, more often than not, moving from an object should in fact be done without an explicit call to std::move:

1) for returning by value
std:: string func()
    std::string ret;
    // modify/build ret

    // good: return a locally declared complete object by value
    return ret;

    // bad: return with std::move
    // return std::move(ret);
    // see http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#f48-dont-return-stdmovelocal
2) for passing by value
void g(std::unique_ptr<int>&& p);

void h()

In your example, the return type of the `get` function is critical to understand correctly the application of the rule "If an object is going to be moved from, then do not declare it const"; since `get(std::tuple<Types...> const&&)` returns a const rvalue reference, then it does not move construct/move assign anything, it merely forwards the indexed subobject with the same value category and qualifier as the tuple argument; so the rule is not applicable in this situation.

Also, note that the example you pulled is an extremely peculiar one, production code almost never return by rvalue ref (even less const rvalue ref); see http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#f45-dont-return-a-t .
The special treatment of `get(std::tuple<Types...> const&&)` is only a special case of perfect forwarding for the const rvalue ref arguments (which is not likely to occur in runtime code, but may be important (and even necessary) for compile time type computations (ie, template metaprogramming)).

Note: The CppCoreGuidelines do not seem to have an explicit rule that mandates the explanations I give here: this is a result from deductive reasoning with implications that follows from the interactions between the guidelines, and how to interpret them as a hole (not really the hole, but just the subset of rules that relate to function interfaces, return types, move semantics).

Julien V.

-------- Original Message --------
From: Yongwei Wu via Std-Discussion <std-discussion_at_[hidden]>
Sent: December 7, 2022 9:01:22 a.m. EST
To: std-discussion_at_[hidden]
Cc: Yongwei Wu <wuyongwei_at_[hidden]>
Subject: Re: [std-discussion] std::get on const rvalue

On Wed, 7 Dec 2022 at 20:27, Bo Persson via Std-Discussion
<std-discussion_at_[hidden]> wrote:
> On 2022-12-07 at 13:09, Yongwei Wu via Std-Discussion wrote:
> > Thanks for the response.
> >
> > Right, it seems there is no harm in forwarding. But my question is in
> > the other direction: What possible harm could there be in real
> > scenarios, if there were no special treatment for the const rvalue?
> In general, a const lvalue reference allows a conversion to a type that
> can bind to the reference. Perhaps we want to avoid that?

Yup, that is the purpose of `=delete` for const T&& in some templates
:-). But still, I was talking about the cases of std::get, where the
const T&& overload is not deleted.

The background is that some people in the team are arguing that we
should forbid std::move on const objects. That basically also forbids
implementing something like get(const tuple<Types...>&& t). I am
looking for whether there are any valid cases of using this kinds of
Std-Discussion mailing list
-- Julien Villemure
Sent from my Android device with K-9 Mail.

Received on 2022-12-07 19:27:03