Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is array::operator[] actually noexcept?

Per cppref, the overloads are not currently noexcept specified. But I think they are actually noexcept, right? Since

  1. No bounds checking is performed. So no out_of_range exception like array::at.
  2. If input is beyond bounds, low-level segfault or access violation happens, which is beyond C++ exception scope (I guess).
like image 552
Lingxi Avatar asked Dec 17 '22 18:12

Lingxi


2 Answers

The reason that operator[] is not marked as noexcept is that it has a "narrow contract", i.e, the index value is required to be in the range 0 ... N-1. If the value passed is not in that range, the behavior is not defined, and (who knows?) the function might throw.

The standard is pretty consistent about not marking things with "narrow contracts" as noexcept. This is informally known as "the Lakos rule".

Note that library IMPLEMENTERS have the freedom to add noexcept where the standard does not specify it, if they choose. I'll think about adding that to libc++.

[Later: It turns out that libc++ does this already for string and string_view, but not vector, array or deque]

[Sill later: libc++ now marks operator[] as noexcept for vector/array and deque.]

like image 147
Marshall Clow Avatar answered Dec 31 '22 14:12

Marshall Clow


The standard states w.r.t to operator [] for std::array:

26.3.7 Class template array [array]

26.3.7.1 Class template array overview [array.overview]

namespace std {
template <class T, size_t N>
struct array {
...  

// element access:
constexpr reference operator[](size_type n);
constexpr const_reference operator[](size_type n) const;

As we can see they are not noexcept.

Whereas members like data() are clearly marked noexcept

constexpr T * data() noexcept;
constexpr const T * data() const noexcept;
like image 23
P.W Avatar answered Dec 31 '22 14:12

P.W