1

STL containers have two overloads for operator[], one const and one non-const and two corresponding typedef.

template<class T>
struct vector{
      T* data_;
      using value_type = T;
      using reference = T&;
      using const_reference = T const&;
      reference operator[](int idx){return *(data_ + idx);}
      const_reference operator[](int idx) const{return *(data_ + idx);}
};

In C++11, wouldn't for consistency make sense to have a r-value reference return as well?

template<class T>
struct vector{
      T* data_;
      using value_type = T;
      using reference = T&;
      using const_reference = T const&;
      using move_reference = T&&;
      reference operator[](int idx) &{return *(data_ + idx);}
      const_reference operator[](int idx) const&{return *(data_ + idx);}
      move_reference operator[](int idx) &&{return *(data_ + idx);}
};

For that matter, this actually generalizes to iterator -> const_iterator -> move_iterator, which looks like an explosion of types and overloads for a simple container.

One could move from elements in a container:

void f(vector<ExpensiveType>&& v){
     ExpensiveType et = std::move(v)[0]; // v[0] is might moved here
}

I know that I could do et = std::move(v[0]) in this example, but std::move(v)[0] is more generic because one can let the container handle the move in a more specific way (via the operator[]&&).

Has something like this been discussed or implemented in some container-like class?


@Praetorian suggests to return a value from the rvalue-ref qualified overload.

value_type operator[](int idx) &&{return std::move??(*(data_ + idx));}
xskxzr
  • 12,442
  • 12
  • 37
  • 77
alfC
  • 14,261
  • 4
  • 67
  • 118
  • Why would you want to return an rvalue reference instead of returning by value from the rvalue reference qualified overload? That's just asking for trouble. Consider `ExpensiveType&& et = std::vector{...}[0];`, you have a dangling reference with your example. – Praetorian Aug 16 '18 at 04:29
  • @Praetorian Where is the dangling reference? In my code or in your comment? Even if so, an rvalue-ref qualified overload would be necessary. Actually, from your counter example, I can build a better example. `ExpT et = vector{a, b, c}[0]`. The only way to minimize copies (of `a`) is to have a rvalue-ref overload to `operator[]`. Do you agree? – alfC Aug 16 '18 at 04:42
  • It's in my example, you avoid it by initializing a value type instead of a reference type. Since there's no expectation that the object on which an rvalue ref qualified member function has been invoked will outlive the end of that expression, I would say you should default to returning by value from such overloads. (and you do need `move` in the return statement) – Praetorian Aug 16 '18 at 04:56

0 Answers0