N3670
Revision of: N3584
2013-04-19
Mike Spertus, Symantec
mike_spertus@symantec.com

Wording for Addressing Tuples by Type: Revision 2

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

Modify §20.2p2 [utility] as follows:

template<size_t I, class T1, class T2>
  constexpr typename tuple_element<I, std::pair<T1, T2> >::type& get(std::pair<T1, T2>&) noexcept;
template<size_t I, class T1, class T2>
  constexpr typename tuple_element<I, std::pair<T1, T2> >::type&& get(std::pair<T1, T2>&&) noexcept;
template<size_t I, class T1, class T2>
  constexpr const typename tuple_element<I, std::pair<T1, T2> >::type&
    get(const std::pair<T1, T2>&) noexcept;
template <class T, class U>
  constexpr T& get(pair<T, U>& p) noexcept;
template <class T, class U>
  constexpr const T& get(const pair<T, U>& p) noexcept;
template <class T, class U>
  constexpr T&& get(pair<T, U>&& p) noexcept;
template <class T, class U>
  constexpr T& get(pair<U, T>& p) noexcept;
template <class T, class U>
  constexpr const T& get(const pair<U, T>& p) noexcept;
template <class T, class U>
  constexpr T&& get(pair<U, T>&& p) noexcept;
// 20.3.5, pair piecewise construction

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

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

Modify §20.4.1p2 [tuple.general] as follows:

// 20.4.2.6, element access:
template <size_t I, class... Types>
  constexpr typename tuple_element<I, tuple<Types...> >::type& get(tuple&lt;Types...>&) noexcept;
template <size_t I, class... types>
  constexpr typename tuple_element<I, tuple<Types...> >::type&& get(tuple&lt;Types...>&&) noexcept;
template <size_t I, class... types>
  constexpr typename tuple_element<I, tuple<Types...> >::type const& get(const tuple<Types...>&) noexcept;
template <class T, class... Types>
  constexpr T& get(tuple<Types...>& t) noexcept;
template <class T, class... Types>
  constexpr T&& get(tuple<Types...>&& t) noexcept;
template <class T, class... Types>
  constexpr const T& get(const tuple<Types...>& t) noexcept;
// 20.4.2.7, relational operators:

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

template <class T, class... Types>
  constexpr T& get(tuple<Types...>& t) noexcept;
template <class T, class... Types>
  constexpr T&& get(tuple<Types...>&& t) noexcept;
template <class T, class... Types>
  constexpr const T& get(const 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....
[ 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>(t);  // OK. Not ambiguous. i2 == 2 
  const double &d = get<double>(t);  // ERROR. ill-formed
— end example ]