From 601afb30ec6ea4171acd812290e79ac49bdd19c5 Mon Sep 17 00:00:00 2001 From: Howard Hinnant <hhinnant@apple.com> Date: Wed, 17 Nov 2010 19:52:17 +0000 Subject: [PATCH] LWG 1191 llvm-svn: 119545 --- libcxx/include/__tuple | 12 +++++++ libcxx/include/array | 13 +++++++ libcxx/include/tuple | 12 +++++++ libcxx/include/utility | 36 +++++++++++++++++++ .../array/array.tuple/get_rv.pass.cpp | 29 +++++++++++++++ .../tuple.tuple/tuple.elem/get_rv.pass.cpp | 30 ++++++++++++++++ .../pairs/pair.astuple/get_rv.pass.cpp | 32 +++++++++++++++++ 7 files changed, 164 insertions(+) create mode 100644 libcxx/test/containers/sequences/array/array.tuple/get_rv.pass.cpp create mode 100644 libcxx/test/utilities/tuple/tuple.tuple/tuple.elem/get_rv.pass.cpp create mode 100644 libcxx/test/utilities/utility/pairs/pair.astuple/get_rv.pass.cpp diff --git a/libcxx/include/__tuple b/libcxx/include/__tuple index a2d4e02f3196..22134a2058ae 100644 --- a/libcxx/include/__tuple +++ b/libcxx/include/__tuple @@ -83,6 +83,10 @@ template <size_t _Ip, class ..._Tp> const typename tuple_element<_Ip, tuple<_Tp...>>::type& get(const tuple<_Tp...>&); +template <size_t _Ip, class ..._Tp> +typename tuple_element<_Ip, tuple<_Tp...>>::type&& +get(tuple<_Tp...>&&); + template <size_t _Ip, class _T1, class _T2> typename tuple_element<_Ip, pair<_T1, _T2> >::type& get(pair<_T1, _T2>&); @@ -91,6 +95,10 @@ template <size_t _Ip, class _T1, class _T2> const typename tuple_element<_Ip, pair<_T1, _T2> >::type& get(const pair<_T1, _T2>&); +template <size_t _Ip, class _T1, class _T2> +typename tuple_element<_Ip, pair<_T1, _T2> >::type&& +get(pair<_T1, _T2>&&); + template <size_t _Ip, class _Tp, size_t _Size> _Tp& get(array<_Tp, _Size>&); @@ -99,6 +107,10 @@ template <size_t _Ip, class _Tp, size_t _Size> const _Tp& get(const array<_Tp, _Size>&); +template <size_t _Ip, class _Tp, size_t _Size> +_Tp&& +get(array<_Tp, _Size>&&); + // __make_tuple_indices template <size_t...> struct __tuple_indices {}; diff --git a/libcxx/include/array b/libcxx/include/array index 2c3d89cde9d5..3801262297f8 100644 --- a/libcxx/include/array +++ b/libcxx/include/array @@ -94,6 +94,7 @@ template <class T, size_t N> struct tuple_size<array<T, N>>; template <int I, class T, size_t N> struct tuple_element<I, array<T, N>>; template <int I, class T, size_t N> T& get(array<T, N>&); template <int I, class T, size_t N> const T& get(const array<T, N>&); +template <int I, class T, size_t N> T&& get(array<T, N>&&); } // std @@ -295,6 +296,18 @@ get(const array<_Tp, _Size>& __a) return __a[_Ip]; } +#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES + +template <size_t _Ip, class _Tp, size_t _Size> +_LIBCPP_INLINE_VISIBILITY inline +_Tp&& +get(array<_Tp, _Size>&& __a) +{ + return _STD::move(__a[_Ip]); +} + +#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES + _LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP_ARRAY diff --git a/libcxx/include/tuple b/libcxx/include/tuple index e134bdff5a60..27c16ed51fb1 100644 --- a/libcxx/include/tuple +++ b/libcxx/include/tuple @@ -88,6 +88,7 @@ template <intsize_t I, class... T> class tuple_element<I, tuple<T...>>; // 20.4.1.5, element access: template <intsize_t I, class... T> typename tuple_element<I, tuple<T...>>::type& get(tuple<T...>&); template <intsize_t I, class... T> typename tuple_element<I, tuple<T...>>::type const& get(const tuple<T...>&); +template <intsize_t I, class... T> typename tuple_element<I, tuple<T...>>::type&& get(tuple<T...>&&); // 20.4.1.6, relational operators: template<class... T, class... U> bool operator==(const tuple<T...>&, const tuple<U...>&); @@ -430,6 +431,8 @@ class _LIBCPP_VISIBLE tuple typename tuple_element<_Jp, tuple<_Up...>>::type& get(tuple<_Up...>&); template <size_t _Jp, class ..._Up> friend const typename tuple_element<_Jp, tuple<_Up...>>::type& get(const tuple<_Up...>&); + template <size_t _Jp, class ..._Up> friend + typename tuple_element<_Jp, tuple<_Up...>>::type&& get(tuple<_Up...>&&); public: _LIBCPP_INLINE_VISIBILITY @@ -583,6 +586,15 @@ get(const tuple<_Tp...>& __t) return static_cast<const __tuple_leaf<_Ip, type>&>(__t.base_).get(); } +template <size_t _Ip, class ..._Tp> +inline _LIBCPP_INLINE_VISIBILITY +typename tuple_element<_Ip, tuple<_Tp...>>::type&& +get(tuple<_Tp...>&& __t) +{ + typedef typename tuple_element<_Ip, tuple<_Tp...>>::type type; + return static_cast<__tuple_leaf<_Ip, type>&&>(__t.base_).get(); +} + // tie template <class ..._Tp> diff --git a/libcxx/include/utility b/libcxx/include/utility index 1faca45719f4..f4c94bea94f9 100644 --- a/libcxx/include/utility +++ b/libcxx/include/utility @@ -100,6 +100,10 @@ template<size_t I, class T1, class T2> const typename const tuple_element<I, std::pair<T1, T2> >::type& get(const std::pair<T1, T2>&); +template<size_t I, class T1, class T2> + typename tuple_element<I, std::pair<T1, T2> >::type&& + get(std::pair<T1, T2>&&); + } // std */ @@ -425,6 +429,16 @@ struct __get_pair<0> _LIBCPP_INLINE_VISIBILITY const _T1& get(const pair<_T1, _T2>& __p) {return __p.first;} + +#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES + + template <class _T1, class _T2> + static + _LIBCPP_INLINE_VISIBILITY + _T1&& + get(pair<_T1, _T2>&& __p) {return _STD::forward<_T1>(__p.first);} + +#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES }; template <> @@ -441,6 +455,16 @@ struct __get_pair<1> _LIBCPP_INLINE_VISIBILITY const _T2& get(const pair<_T1, _T2>& __p) {return __p.second;} + +#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES + + template <class _T1, class _T2> + static + _LIBCPP_INLINE_VISIBILITY + _T2&& + get(pair<_T1, _T2>&& __p) {return _STD::forward<_T2>(__p.second);} + +#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES }; template <size_t _Ip, class _T1, class _T2> @@ -459,6 +483,18 @@ get(const pair<_T1, _T2>& __p) return __get_pair<_Ip>::get(__p); } +#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES + +template <size_t _Ip, class _T1, class _T2> +_LIBCPP_INLINE_VISIBILITY inline +typename tuple_element<_Ip, pair<_T1, _T2> >::type&& +get(pair<_T1, _T2>&& __p) +{ + return __get_pair<_Ip>::get(_STD::move(__p)); +} + +#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES + #endif // _LIBCPP_HAS_NO_VARIADICS _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/test/containers/sequences/array/array.tuple/get_rv.pass.cpp b/libcxx/test/containers/sequences/array/array.tuple/get_rv.pass.cpp new file mode 100644 index 000000000000..869c1ec9c2dc --- /dev/null +++ b/libcxx/test/containers/sequences/array/array.tuple/get_rv.pass.cpp @@ -0,0 +1,29 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// <array> + +// template <size_t I, class T, size_t N> T&& get(array<T, N>&& a); + +#include <array> +#include <memory> +#include <cassert> + +int main() +{ +#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES + { + typedef std::unique_ptr<double> T; + typedef std::array<T, 1> C; + C c = {std::unique_ptr<double>(new double(3.5))}; + T t = std::get<0>(std::move(c)); + assert(*t == 3.5); + } +#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES +} diff --git a/libcxx/test/utilities/tuple/tuple.tuple/tuple.elem/get_rv.pass.cpp b/libcxx/test/utilities/tuple/tuple.tuple/tuple.elem/get_rv.pass.cpp new file mode 100644 index 000000000000..5a97710c2e32 --- /dev/null +++ b/libcxx/test/utilities/tuple/tuple.tuple/tuple.elem/get_rv.pass.cpp @@ -0,0 +1,30 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// <tuple> + +// template <class... Types> class tuple; + +// template <size_t I, class... Types> +// typename tuple_element<I, tuple<Types...> >::type&& +// get(tuple<Types...>&& t); + +#include <tuple> +#include <memory> +#include <cassert> + +int main() +{ + { + typedef std::tuple<std::unique_ptr<int> > T; + T t(std::unique_ptr<int>(new int(3))); + std::unique_ptr<int> p = std::get<0>(std::move(t)); + assert(*p == 3); + } +} diff --git a/libcxx/test/utilities/utility/pairs/pair.astuple/get_rv.pass.cpp b/libcxx/test/utilities/utility/pairs/pair.astuple/get_rv.pass.cpp new file mode 100644 index 000000000000..aa5ca530913c --- /dev/null +++ b/libcxx/test/utilities/utility/pairs/pair.astuple/get_rv.pass.cpp @@ -0,0 +1,32 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// <utility> + +// template <class T1, class T2> struct pair + +// template<size_t I, class T1, class T2> +// typename tuple_element<I, std::pair<T1, T2> >::type&& +// get(pair<T1, T2>&&); + +#include <utility> +#include <memory> +#include <cassert> + +int main() +{ +#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES + { + typedef std::pair<std::unique_ptr<int>, short> P; + P p(std::unique_ptr<int>(new int(3)), 4); + std::unique_ptr<int> ptr = std::get<0>(std::move(p)); + assert(*ptr == 3); + } +#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES +}