Created on 2015-03-27.00:00:00 last changed 100 months ago
Proposed resolution:
This wording is relative to N4296.
Change [utility]/2 "Header <utility> synopsis" as depicted:
[…]
template<size_t I, class T1, class T2>
constexpr tuple_element_t<I, pair<T1, T2>>&
get(pair<T1, T2>&) noexcept;
template<size_t I, class T1, class T2>
constexpr tuple_element_t<I, pair<T1, T2>>&&
get(pair<T1, T2>&&) noexcept;
template<size_t I, class T1, class T2>
constexpr const tuple_element_t<I, pair<T1, T2>>&
get(const pair<T1, T2>&) noexcept;
template<size_t I, class T1, class T2>
constexpr const tuple_element_t<I, pair<T1, T2>>&&
get(const 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 const T&& get(const 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;
template <class T, class U>
constexpr const T&& get(const pair<U, T>&& p) noexcept;
[…]
Change [tuple.general]/2 "Header <tuple> synopsis" as depicted:
[…] // 20.4.2.6, element access: template <size_t I, class... Types> constexpr tuple_element_t<I, tuple<Types...>>& get(tuple<Types...>&) noexcept; template <size_t I, class... Types> constexpr tuple_element_t<I, tuple<Types...>>&& get(tuple<Types...>&&) noexcept; template <size_t I, class... Types> constexpr const tuple_element_t<I, tuple<Types...>>& get(const tuple<Types...>&) noexcept; template <size_t I, class... Types> constexpr const tuple_element_t<I, tuple<Types...>>&& 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; template <class T, class... Types> constexpr const T&& get(const tuple<Types...>&& t) noexcept; […]
Change [sequences.general]/2 "Header <array> synopsis" as depicted:
[…] template <size_t I, class T, size_t N> constexpr T& get(array<T, N>&) noexcept; template <size_t I, class T, size_t N> constexpr T&& get(array<T, N>&&) noexcept; template <size_t I, class T, size_t N> constexpr const T& get(const array<T, N>&) noexcept; template <size_t I, class T, size_t N> constexpr const T&& get(const array<T, N>&&) noexcept; […]
Change [pair.astuple] as depicted:
template<size_t I, class T1, class T2> constexpr tuple_element_t<I, pair<T1, T2>>& get(pair<T1, T2>& p) noexcept; template<size_t I, class T1, class T2> constexpr const tuple_element_t<I, pair<T1, T2>>& get(const pair<T1, T2>& p) noexcept;
-3- Returns: If I == 0 returns p.first; if I == 1 returns p.second; otherwise the program is ill-formed.template<size_t I, class T1, class T2> constexpr tuple_element_t<I, pair<T1, T2>>&& get(pair<T1, T2>&& p) noexcept; template<size_t I, class T1, class T2> constexpr const tuple_element_t<I, pair<T1, T2>>&& get(const pair<T1, T2>&& p) noexcept;-4- Returns: If I == 0 returns a reference to
std::forward<T1&&>(p.first); if I == 1 returns a reference tostd::forward<T2&&>(p.second); otherwise the program is ill-formed.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;
-5- Requires: T and U are distinct types. Otherwise, the program is ill-formed.-6- Returns: get<0>(p);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;-7- Requires: T and U are distinct types. Otherwise, the program is ill-formed.
-8- Returns: A reference to p.first.get<0>(std::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;
-9- Requires: T and U are distinct types. Otherwise, the program is ill-formed.-10- Returns: get<1>(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;-11- Requires: T and U are distinct types. Otherwise, the program is ill-formed.
-12- Returns: A reference to p.second.get<1>(std::move(p));
Change [tuple.elem] as depicted:
template <size_t I, class... Types> constexpr tuple_element_t<I, tuple<Types...> >& get(tuple<Types...>& t) noexcept;
-1- Requires: I < sizeof...(Types). The program is ill-formed if I is out of bounds.-2- Returns: A reference to the Ith element of t, where indexing is zero-based.template <size_t I, class... Types> constexpr tuple_element_t<I, tuple<Types...> >&& get(tuple<Types...>&& t) noexcept; // Note A
-3- Effects: Equivalent to return std::forward<typename tuple_element<I, tuple<Types...> >::type&&>(get<I>(t));-4- 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 <size_t I, class... Types> constexpr tuple_element_t<I, tuple<Types...> > const& get(const tuple<Types...>& t) noexcept; // Note B template <size_t I, class... Types> constexpr const tuple_element_t<I, tuple<Types...> >&& get(const tuple<Types...>&& t) noexcept;-5- Requires: I < sizeof...(Types). The program is ill-formed if I is out of bounds.
-6- Returns: Aconstreference to the Ith element of t, where indexing is zero-based. -?- [Note A: 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&&. — end note] -7- [Note B: 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]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; template <class T, class... Types> constexpr const T&& get(const tuple<Types...>&& t) noexcept;-8- Requires: The type T occurs exactly once in Types.... Otherwise, the program is ill-formed.
-9- Returns: A reference to the element of t corresponding to the type T in Types.... […]
Change [array.tuple] as depicted:
template <size_t I, class T, size_t N> constexpr T& get(array<T, N>& a) noexcept;
-3- Requires: I < N. The program is ill-formed if I is out of bounds.-4- Returns: A reference to the Ith element of a, where indexing is zero-based.template <size_t I, class T, size_t N> constexpr T&& get(array<T, N>&& a) noexcept;
-5- Effects: Equivalent to return std::move(get<I>(a));template <size_t I, class T, size_t N> constexpr const T& get(const array<T, N>& a) noexcept; template <size_t I, class T, size_t N> constexpr const T&& get(const array<T, N>&& a) noexcept;-6- Requires: I < N. The program is ill-formed if I is out of bounds.
-7- Returns: Aconstreference to the Ith element of a, where indexing is zero-based.
[ 2015-05, Lenexa ]
TP: for the existing overloads there's no change to the code, just descriptions?
STL: right.
JW: I love it
MC: in favor of moving to Ready and bringing up for vote on Friday
7 in favor, none opposed
const rvalues are weird, but they're part of the type system. Consider the following code:
#include <functional>
#include <string>
#include <tuple>
using namespace std;
string str1() { return "one"; }
const string str2() { return "two"; }
tuple<string> tup3() { return make_tuple("three"); }
const tuple<string> tup4() { return make_tuple("four"); }
int main() {
// cref(str1()); // BAD, properly rejected
// cref(str2()); // BAD, properly rejected
// cref(get<0>(tup3())); // BAD, properly rejected
cref(get<0>(tup4())); // BAD, but improperly accepted!
}
As tuple is a fundamental building block (and the only convenient way to have variadic data members), it should not open a hole in the type system. get() should imitate [expr.ref]'s rules for accessing data members. (This is especially true for pair, where both get<0>() and .first are available.)
While we're in the neighborhood, we can dramatically simplify the wording here. All we need to do is follow [tuple.elem]/9's example of saying "Returns: A reference to STUFF", and allow implementers to figure out how to achieve that with the given return types.| History | |||
|---|---|---|---|
| Date | User | Action | Args |
| 2017-07-30 20:15:43 | admin | set | status: wp -> c++17 |
| 2015-10-27 16:52:45 | admin | set | status: ready -> wp |
| 2015-05-07 23:01:40 | admin | set | messages: + msg7392 |
| 2015-05-07 23:01:40 | admin | set | status: new -> ready |
| 2015-04-03 13:38:55 | admin | set | messages: + msg7315 |
| 2015-03-27 00:00:00 | admin | create | |