Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

rvalue ref-qualifiers for STL containers

Why element access member functions of STL containers, e.g. std::array::operator[] or std::vector::operator[] do not have rvalue ref-qualifier overloads? Of course I can do std::move(generate_vector()[10]), but I'm curious if adding rvalue ref-qualifier overloads was considered when ref-qualifiers were being standardized.

I think std::array<T, N> and std::tuple<T, T, ..., T> are really the same thing, and the "element access function (i.e., std::get)" of the latter is overloaded for all combinations of const vs non-const and lvalue vs rvalue. Why not the former?

Is it a good idea to add rvalue ref-qualified element access member functions (which return rvalue references) to my custom container?

EDIT

To Richard Critten's comment. I think this can be occasionally useful.

For example, you have a function that returns a container constructed inside that function, but you may be interested only to the first element of that container. Yes, that's silly. In that case, it's definitely better to use simpler function that only constructs the first element. But if the function is not yours, you have no such a choice.

Or, there may be more general examples. You have a function that constructs a container, and you wish to process that container to get another result. For example, you may wish to perform std::reduce, or std::unique_copy to that container. (It seems that it is prevented to modify elements during performing std::reduce, but let us just assume we have implemented our own that allows modifications.) In this case, one may use std::make_move_iterator, but why not let the container itself returns move iterators?

EDIT2

In fact I encountered this problem when I'm implementing some "view" classes to a container class. Mutable view (lvalue reference), immutable view (const reference), and movable view (rvalue reference) seem to be all needed, and I have to determine what to return from element access member functions of the movable view class: lvalue or rvalue references? It felt a little bit weird to me, to return rvalue references to elements where the container itself does not expose such interfaces. Which one is correct?

  1. lvalue references.
  2. rvalue references.
  3. Movable view, in general, is not right. Such thing should not be needed that often, and there should be some serious problems in my design.
like image 707
Junekey Jeon Avatar asked Nov 07 '22 10:11

Junekey Jeon


1 Answers

There isn't a particular problem with adding ref-qualifiers to everything that returns references, however that basically doubles the number of members, which will generally have identical implementations apart from wrapping the return in std::move.

class A
{
    int a;

    int& operator[](std::size_t pos) & { return a; }
    int&& operator[](std::size_t pos) && { return std::move(a); }
};

The standard library has declined to provide these overloads, in the same way that it has declined to provide many volatile overloads. In this case, you can just std::move the & value, where you need it.

If you are writing your own containers, then there is no safeness reason to avoid such overloads. It does increase the maintenance burden, so I would advise against it.

like image 183
Caleth Avatar answered Nov 14 '22 21:11

Caleth