Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why doesn't std::array's operator[] retain the value category of the array?

I'd have expected that if an std::array is an rvalue, then calling operator[] returns an rvalue as well. But it doesn't seem to be the case (cppreference), there are no value-category overloads.

For example, std::optional respects the value category (cppreference). Why don't we have the same overloads in std::array, like this?

const T &&operator[](size_type pos) const &&
const T &operator[](size_type pos) const &
T &&operator[](size_type pos) &&
T &operator[](size_type pos) &

(of course, this question is not just about operator[], but all the other accessor functions)


Here's is an example which shows that in this regard, std::array is not a drop-in replacement for old-style arrays. With old-style arrays, the result of the index operator is an rvalue reference, but with std::array, it is not:

#include <array>
#include <utility>
#include <type_traits>
#include <cstdio>

int main() {
    int old_way[1];
    std::array<int, 1> new_way;

    printf("old_way, is_rvalue_reference: %d\n", std::is_rvalue_reference_v<decltype(std::move(old_way)[0])>);
    printf("new_way, is_rvalue_reference: %d\n", std::is_rvalue_reference_v<decltype(std::move(new_way)[0])>);
}

This program prints:

old_way, is_rvalue_reference: 1
new_way, is_rvalue_reference: 0
like image 782
geza Avatar asked Oct 16 '25 19:10

geza


1 Answers

It behaves consistently with other (sequence) containers. The (sequence) container concept requires the type to have member typedefs reference and const_reference which shall be returned by operator[] depending on const-qualification. But there is no equivalent distinction made for lvalue and rvalue references to elements.

Containers have existed before C++11 when the reference qualifiers for member functions were introduced. So they were not able to forward value category originally. And because of a lack of move semantics it wouldn't have been very helpful at that time either.

Also, std::array was originally part of TR1 and derived from boost::array, both before C++11. At the time the necessary syntax didn't exist yet either.

like image 173
user17732522 Avatar answered Oct 18 '25 11:10

user17732522