This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of CD1 status.

### 775. Tuple indexing should be unsigned?

Section: 22.4.7 [tuple.helper] Status: CD1 Submitter: Alisdair Meredith Opened: 2008-01-16 Last modified: 2016-01-28

Priority: Not Prioritized

View all other issues in [tuple.helper].

View all issues with CD1 status.

Discussion:

The tuple element access API identifies the element in the sequence using signed integers, and then goes on to enforce the requirement that I be >= 0. There is a much easier way to do this - declare I as `unsigned`.

In fact the proposal is to use `std::size_t`, matching the type used in the `tuple_size` API.

A second suggestion is that it is hard to imagine an API that deduces and index at compile time and returns a reference throwing an exception. Add a specific Throws: Nothing paragraph to each element access API.

In addition to `tuple`, update the API applies to `pair` and `array`, and should be updated accordingly.

A third observation is that the return type of the `get` functions for `std::pair` is pseudo-code, but it is not clearly marked as such. There is actually no need for pseudo-code as the return type can be specified precisely with a call to `tuple_element`. This is already done for `std::tuple`, and `std::array` does not have a problem as all elements are of type `T`.

Proposed resolution:

Update header <utility> synopsis in 22.2 [utility]

    // 20.2.3, tuple-like access to pair:
    template <class T> class tuple_size;
    template <intsize_t I, class T> class tuple_element;

    template <class T1, class T2> struct tuple_size<std::pair<T1, T2> >;
    template <class T1, class T2> struct tuple_element<0, std::pair<T1, T2> >;
    template <class T1, class T2> struct tuple_element<1, std::pair<T1, T2> >;

    template<intsize_t I, class T1, class T2>
      Ptypename tuple_element<I, std::pair<T1, T2> >::type & get(std::pair<T1, T2>&);
    template<intsize_t I, class T1, class T2>
      const Ptypename tuple_element<I, std::pair<T1, T2> >::type & get(const std::pair<T1, T2>&);

Update 22.3 [pairs] Pairs

    template<intsize_t I, class T1, class T2>
      Ptypename tuple_element<I, std::pair<T1, T2> >::type & get(pair<T1, T2>&);
    template<intsize_t I, class T1, class T2>
      const Ptypename tuple_element<I, std::pair<T1, T2> >::type & get(const pair<T1, T2>&);

24 Return type: If `I == 0` then `P` is `T1`, if `I == 1` then `P` is `T2`, and otherwise the program is ill-formed.

25 Returns: If `I == 0` returns `p.first`, otherwise if `I == 1` returns `p.second`, and otherwise the program is ill-formed.

Throws: Nothing.

Update header <tuple> synopsis in 22.4 [tuple] with a APIs as below:

    template <intsize_t I, class T> class tuple_element; // undefined
    template <intsize_t I, class... Types> class tuple_element<I, tuple<Types...> >;

    // 20.3.1.4, element access:
    template <intsize_t I, class... Types>
      typename tuple_element<I, tuple<Types...> >::type& get(tuple<Types...>&);
    template <intsize_t I, class ... types>
      typename tuple_element<I, tuple<Types...> >::type const& get(const tuple<Types...>&);

Update 22.4.7 [tuple.helper] Tuple helper classes

    template <intsize_t I, class... Types>
    class tuple_element<I, tuple<Types...> > {
    public:
      typedef TI type;
    };

1 Requires: `0 <= I and I < sizeof...(Types)`. The program is ill-formed if `I` is out of bounds.

2 Type: `TI` is the type of the `I`th element of `Types`, where indexing is zero-based.

Update 22.4.8 [tuple.elem] Element access

    template <intsize_t I, class... types >
    typename tuple_element<I, tuple<Types...> >::type& get(tuple<Types...>& t);

1 Requires: `0 <= I and I < sizeof...(Types)`. The program is ill-formed if `I` is out of bounds.

2 Returns: A reference to the `I`th element of `t`, where indexing is zero-based. Throws: Nothing.

    template <intsize_t I, class... types>
    typename tuple_element<I, tuple<Types...> >::type const& get(const tuple<Types...>& t);

3 Requires: `0 <= I and I < sizeof...(Types)`. The program is ill-formed if `I` is out of bounds.

4 Returns: A const reference to the `I`th element of `t`, where indexing is zero-based.

Throws: Nothing.

Update header <array> synopsis in 22.2 [utility]

    template <class T> class tuple_size; // forward declaration
    template <intsize_t I, class T> class tuple_element; // forward declaration
    template <class T, size_t N>
      struct tuple_size<array<T, N> >;
    template <intsize_t I, class T, size_t N>
      struct tuple_element<I, array<T, N> >;
    template <intsize_t I, class T, size_t N>
      T& get(array<T, N>&);
    template <intsize_t I, class T, size_t N>
      const T& get(const array<T, N>&);

Update 24.3.7.7 [array.tuple] Tuple interface to class template array

    tuple_element<size_t I, array<T, N> >::type

3 Requires: `0 <= I < N.` The program is ill-formed if `I` is out of bounds.

4 Value: The type `T`.

    template <intsize_t I, class T, size_t N> T& get(array<T, N>& a);

5 Requires: `0 <= I < N`. The program is ill-formed if `I` is out of bounds.

Returns: A reference to the `I`th element of `a`, where indexing is zero-based.

Throws: Nothing.

    template <intsize_t I, class T, size_t N> const T& get(const array<T, N>& a);

6 Requires: `0 <= I < N`. The program is ill-formed if `I` is out of bounds.

7 Returns: A const reference to the `I`th element of `a`, where indexing is zero-based.

Throws: Nothing.

[ Bellevue: Note also that the phrase "The program is ill-formed if I is out of bounds" in the requires clauses are probably unnecessary, and could be removed at the editor's discretion. Also std:: qualification for pair is also unnecessary. ]