N3584
2013-03-14
Mike Spertus, Symantec
mike_spertus@symantec.com

Wording for Addressing Tuples by Type

In Portland, LWG accepted the "Addressing tuples by type" portion of n3404, pending wording, which is provided below. Note that the "Functoriality" proposal in that paper was not accepted.

Overview

N3404 proposed allowing tuples to be addressed by type as well as by numerical index.
tuple<string, string, int> t("foo", "bar", 7); int i = get<int>(t); // i == 7 int j = get<2>(t); // Equivalent to the above: j == 7 string s = get<string>(t); // Compile-time error. Ambiguous

Wording

Add the following after §20.4.2.6p7 [tuple.elem]:

template <class T, class... Types>
  T& get(tuple<Types...>& t) noexcept;
Requires: The type T occurs exactly once in Types.... Otherwise, the program is ill-formed.
Returns: A reference to the element of t corresponding to the type T in Types...
template <class T, class... Types>
  T&& get(tuple<Types...>&& t) noexcept;
Effects: Equivalent to return std::forward<T&&>(get<i>(t));
Note: if a T in Types is some reference type X&, the return type is X&, not X&&. However, if the element type is a non-reference type T, the return type is T&&.
template <class T, class... Types>
  T& get(const tuple<Types...>& t) noexcept;
Requires: The type T occurs exactly once in Types.... Otherwise, the program is ill-formed.
Returns: A const reference to the element of t corresponding to the type T in Types...

[ Note: Constness is shallow. If a T in Types is some reference type X&, the return type is X&, not const X&. However, if the element type is non-reference type T, the return type is const T&. This is consistent with how constness is defined to work for member variables of reference type.
— end note
]


[ Example:

const tuple<int, const int, double, double> t(1, 2, 3.4, 5.6);
const int &i1(get<int>(t) // OK. Not ambiguous. i1 == 1
const int &i2(get<const int&gt;(t) // OK. Not ambiguous. i2 == 2
const double &d(get<double>(t) // ERROR. ill-formed

— end example ]

Add the following to the end of §20.3.4 [pair.astuple]:

template <class T, class U>
  T& get(pair<T, U>& p) noexcept;
template <class T, class U>
  const T& get(const pair<T, U>& p) noexcept;
template <class T, class U>
  T&& get(pair<T, U>&& p) noexcept;
Requires: T and U are distinct types. Otherwise, the program is ill-formed.
Returns: get<0>(p);
template <class T, class U>
  T& get(pair<U, T>& p) noexcept;
template <class T, class U>
  const T& get(const pair<U, T>& p) noexcept;
template <class T, class U>
  T&& get(pair<U, T>&& p) noexcept;
Requires: T and U are distinct types. Otherwise, the program is ill-formed.
Returns: get<1>(p);