What is use of the ref-qualifier `const &&`?

后端 未结 4 605
予麋鹿
予麋鹿 2020-12-13 19:06

I\'ve been digging around ref-qualifiers a bit, following on a previous question.

Given the code sample below;

#include 
#include <         


        
相关标签:
4条回答
  • 2020-12-13 19:22

    On the usefulness of const&&... (in general)

    The usefulness of the const&& qualifier on the member method is minimal at best. The object cannot be modified in the same manner as a && method would allow it to be modified; it is const after all (as noted, mutable does change this). So we will not be able to rip out its guts, since the temporary is expiring anyway, as we would in something akin to a normal move.

    In many ways the usefulness of the const&& may be best evaluated in the context of how useful an object of type const T&& is to begin with. How useful is a const T&& function argument? As pointed out in another answer (to this question) here, they are very useful in declaring functions deleted, e.g. in this case

    template <class T> void ref (const T&&) = delete;
    

    to explicitly disallow objects of prvalue and xvalue value category types from being used with the functions, and const T&& does bind to all prvalue and xvalue objects.

    What is the usefulness of const&& method qualifier?

    It is interesting to note that in the proposal C++ library extensions, optional, § 5.3, includes overloads, e.g.

    constexpr T value() const &&;
    

    that are qualified as const&& and are specified to perform the same action as the && alternative.

    The reason I can infer for this case; is that this is for completeness and correctness. If the value() method is called on an rvalue, then it performs the same action independent of it being const or not. The const will need to be dealt with by the contained object being moved or the client code using it. If there is some mutable state with the object being contained, then that state can legitimately be changed.

    There may well still be some merit in this; in no particular order...

    • To declare it = delete to prohibit the method's use on prvalues and xvalues.
    • If the type has mutable state and the qualifier makes sense (possibly in addition to the other qualifiers) in the target environment, consider it.
    • If you are implementing a generic container type, then for completeness and correctness, consider adding it and performing the same action as the && method. Advice here is sort from the standard library (and its extensions).

    What would a "canonical" signature look like for a const&& qualified method?

    Since the method will be performing the same action as the && method, I would advocate that the signature matches the && signature.

    0 讨论(0)
  • 2020-12-13 19:28

    We can find a similar exploration of this issue in the article What are const rvalue references good for? and the one use that stood out is this example form the standard library:

    template <class T> void ref (const T&&) = delete;
    template <class T> void cref (const T&&) = delete;
    

    which disables ref and cref for rvalues altogether. We can find these declarations in the draft C++11 standard section 20.8 Function objects paragraph 2.

    Scott Meyers alludes to this use in Universal References in C++11:

    Even the simple addition of a const qualifier is enough to disable the interpretation of “&&” as a universal reference:

    0 讨论(0)
  • 2020-12-13 19:37

    Suppose we have a type with a mutable state. Then const&& will both allow us to mutate that state, and indicate that such mutation is safe.

    struct bar;
    
    struct foo {
      mutable std::vector<char> state;
      operator bar() const&;
      operator bar() const&&;
    };
    

    const is not absolute.

    Barring mutable state, it is not safe to cast away const in a const&& method in order to extract state, because extracting state in this way from an actual const object is undefined behavior.

    0 讨论(0)
  • 2020-12-13 19:37

    I see two main uses for ref-qualifying a method. One is like you show in your get() && method, where you use it to select a potentially more efficient implementation that is only available when you know the object will no longer be used. But the other is a safety hint to prevent calling certain methods on temporary objects.

    You can use notation like get() const && = delete in such cases, although realistically I would save this approach for modifying methods, especially those that are potentially costly. It doesn't make much sense to mutate and then discard an object without retrieving something, and doubly so if it's expensive to perform the mutation. This construct gives the compiler a way to flag and prevent such usage.

    0 讨论(0)
提交回复
热议问题