Index: include/__tuple =================================================================== --- include/__tuple +++ include/__tuple @@ -86,6 +86,11 @@ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 typename tuple_element<_Ip, tuple<_Tp...> >::type&& get(tuple<_Tp...>&&) _NOEXCEPT; + +template +_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 +const typename tuple_element<_Ip, tuple<_Tp...> >::type&& +get(const tuple<_Tp...>&&) _NOEXCEPT; #endif // pair specializations @@ -109,6 +114,11 @@ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 typename tuple_element<_Ip, pair<_T1, _T2> >::type&& get(pair<_T1, _T2>&&) _NOEXCEPT; + +template +_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 +const typename tuple_element<_Ip, pair<_T1, _T2> >::type&& +get(const pair<_T1, _T2>&&) _NOEXCEPT; #endif // array specializations @@ -132,6 +142,11 @@ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 _Tp&& get(array<_Tp, _Size>&&) _NOEXCEPT; + +template +_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 +const _Tp&& +get(const array<_Tp, _Size>&&) _NOEXCEPT; #endif #if !defined(_LIBCPP_HAS_NO_VARIADICS) Index: include/array =================================================================== --- include/array +++ include/array @@ -95,6 +95,7 @@ template T& get(array&) noexcept; // constexpr in C++14 template const T& get(const array&) noexcept; // constexpr in C++14 template T&& get(array&&) noexcept; // constexpr in C++14 +template const T&& get(const array&&) noexcept; // constexpr in C++14 } // std @@ -324,6 +325,15 @@ return _VSTD::move(__a.__elems_[_Ip]); } +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 +const _Tp&& +get(const array<_Tp, _Size>&& __a) _NOEXCEPT +{ + static_assert(_Ip < _Size, "Index out of bounds in std::get<> (const std::array &&)"); + return _VSTD::move(__a.__elems_[_Ip]); +} + #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES _LIBCPP_END_NAMESPACE_STD Index: include/tuple =================================================================== --- include/tuple +++ include/tuple @@ -95,6 +95,9 @@ template typename tuple_element>::type&& get(tuple&&) noexcept; // constexpr in C++14 +template + const typename tuple_element>::type&& + get(const tuple&&) noexcept; // constexpr in C++14 template constexpr T1& get(tuple&) noexcept; // C++14 @@ -102,6 +105,8 @@ constexpr const T1& get(const tuple&) noexcept; // C++14 template constexpr T1&& get(tuple&&) noexcept; // C++14 +template + constexpr const T1&& get(const tuple&&) noexcept; // C++14 // 20.4.1.6, relational operators: template bool operator==(const tuple&, const tuple&); // constexpr in C++14 @@ -507,6 +512,8 @@ const typename tuple_element<_Jp, tuple<_Up...> >::type& get(const tuple<_Up...>&) _NOEXCEPT; template friend _LIBCPP_CONSTEXPR_AFTER_CXX11 typename tuple_element<_Jp, tuple<_Up...> >::type&& get(tuple<_Up...>&&) _NOEXCEPT; + template friend _LIBCPP_CONSTEXPR_AFTER_CXX11 + const typename tuple_element<_Jp, tuple<_Up...> >::type&& get(const tuple<_Up...>&&) _NOEXCEPT; public: template &&>(__t.base_).get()); } +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 +const typename tuple_element<_Ip, tuple<_Tp...> >::type&& +get(const tuple<_Tp...>&& __t) _NOEXCEPT +{ + typedef typename tuple_element<_Ip, tuple<_Tp...> >::type type; + return static_cast( + static_cast&&>(__t.base_).get()); +} + #if _LIBCPP_STD_VER > 11 // get by type template @@ -822,6 +839,13 @@ return _VSTD::get<__find_exactly_one_t<_T1, _Args...>::value>(_VSTD::move(__tup)); } +template +inline _LIBCPP_INLINE_VISIBILITY +constexpr _T1 const&& get(tuple<_Args...> const&& __tup) noexcept +{ + return _VSTD::get<__find_exactly_one_t<_T1, _Args...>::value>(_VSTD::move(__tup)); +} + #endif // tie Index: include/utility =================================================================== --- include/utility +++ include/utility @@ -120,6 +120,10 @@ typename tuple_element >::type&& get(pair&&) noexcept; // constexpr in C++14 +template + const typename tuple_element >::type&& + get(const pair&&) noexcept; // constexpr in C++14 + template constexpr T1& get(pair&) noexcept; // C++14 @@ -129,6 +133,9 @@ template constexpr T1&& get(pair&&) noexcept; // C++14 +template + constexpr const T1&& get(const pair&&) noexcept; // C++14 + // C++14 template @@ -560,6 +567,12 @@ _T1&& get(pair<_T1, _T2>&& __p) _NOEXCEPT {return _VSTD::forward<_T1>(__p.first);} + template + static + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 + const _T1&& + get(const pair<_T1, _T2>&& __p) _NOEXCEPT {return _VSTD::forward(__p.first);} + #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES }; @@ -586,6 +599,12 @@ _T2&& get(pair<_T1, _T2>&& __p) _NOEXCEPT {return _VSTD::forward<_T2>(__p.second);} + template + static + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 + const _T2&& + get(const pair<_T1, _T2>&& __p) _NOEXCEPT {return _VSTD::forward(__p.second);} + #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES }; @@ -615,6 +634,14 @@ return __get_pair<_Ip>::get(_VSTD::move(__p)); } +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 +const typename tuple_element<_Ip, pair<_T1, _T2> >::type&& +get(const pair<_T1, _T2>&& __p) _NOEXCEPT +{ + return __get_pair<_Ip>::get(_VSTD::move(__p)); +} + #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES #if _LIBCPP_STD_VER > 11 @@ -641,6 +668,13 @@ template inline _LIBCPP_INLINE_VISIBILITY +constexpr _T1 const && get(pair<_T1, _T2> const&& __p) _NOEXCEPT +{ + return __get_pair<0>::get(_VSTD::move(__p)); +} + +template +inline _LIBCPP_INLINE_VISIBILITY constexpr _T1 & get(pair<_T2, _T1>& __p) _NOEXCEPT { return __get_pair<1>::get(__p); @@ -660,6 +694,13 @@ return __get_pair<1>::get(_VSTD::move(__p)); } +template +inline _LIBCPP_INLINE_VISIBILITY +constexpr _T1 const && get(pair<_T2, _T1> const&& __p) _NOEXCEPT +{ + return __get_pair<1>::get(_VSTD::move(__p)); +} + #endif #if _LIBCPP_STD_VER > 11 Index: test/std/containers/sequences/array/array.tuple/get_const_rv.pass.cpp =================================================================== --- /dev/null +++ test/std/containers/sequences/array/array.tuple/get_const_rv.pass.cpp @@ -0,0 +1,35 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// + +// template const T&& get(const array&& a); + +// UNSUPPORTED: c++98, c++03 + +#include +#include +#include +#include + +// std::array is explicitly allowed to be initialized with A a = { init-list };. +// Disable the missing braces warning for this reason. +#include "disable_missing_braces_warning.h" + +int main() +{ + + { + typedef std::unique_ptr T; + typedef std::array C; + const C c = {std::unique_ptr(new double(3.5))}; + const T&& t = std::get<0>(std::move(c)); + assert(*t == 3.5); + } +} Index: test/std/utilities/tuple/tuple.tuple/tuple.elem/get_const_rv.fail.cpp =================================================================== --- /dev/null +++ test/std/utilities/tuple/tuple.tuple/tuple.elem/get_const_rv.fail.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. +// +//===----------------------------------------------------------------------===// + +// + +// template class tuple; + +// template +// const typename tuple_element >::type&& +// get(const tuple&& t); + +// UNSUPPORTED: c++98, c++03 + +#include + +template void cref(T const&) {}; +template void cref(T const&&) = delete; + +std::tuple const tup4() { return std::make_tuple(4); } + +int main() +{ + { + cref(std::get<0>(tup4())); + } +} Index: test/std/utilities/tuple/tuple.tuple/tuple.elem/get_const_rv.pass.cpp =================================================================== --- /dev/null +++ test/std/utilities/tuple/tuple.tuple/tuple.elem/get_const_rv.pass.cpp @@ -0,0 +1,43 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// + +// template class tuple; + +// template +// const typename tuple_element >::type&& +// get(const tuple&& t); + +// UNSUPPORTED: c++98, c++03 + +#include +#include +#include +#include + +struct Empty {}; + +int main() +{ + { + typedef std::tuple T; + const T t(3); + int const&& i = std::get<0>(std::move(t)); + assert(i == 3); + } + { + typedef std::tuple T; + const T t("high", 5); + std::string const&& s = std::get<0>(std::move(t)); + int const&& i = std::get<1>(std::move(t)); + assert(s == "high"); + assert(i == 5); + } +} Index: test/std/utilities/tuple/tuple.tuple/tuple.elem/tuple.by.type.pass.cpp =================================================================== --- test/std/utilities/tuple/tuple.tuple/tuple.elem/tuple.by.type.pass.cpp +++ test/std/utilities/tuple/tuple.tuple/tuple.elem/tuple.by.type.pass.cpp @@ -56,5 +56,13 @@ assert(std::get<0>(t) == nullptr); // has been moved from } + { + typedef std::unique_ptr upint; + const std::tuple t(upint(new int(4))); + const upint&& p = std::get(std::move(t)); // get const rvalue + assert(*p == 4); + assert(std::get<0>(t) != nullptr); + } + #endif } Index: test/std/utilities/utility/pairs/pair.astuple/get_const_rv.pass.cpp =================================================================== --- /dev/null +++ test/std/utilities/utility/pairs/pair.astuple/get_const_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. +// +//===----------------------------------------------------------------------===// + +// + +// template struct pair + +// template +// const typename tuple_element >::type&& +// get(const pair&&); + +#include +#include +#include + +int main() +{ +#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES + { + typedef std::pair, short> P; + const P p(std::unique_ptr(new int(3)), 4); + const std::unique_ptr&& ptr = std::get<0>(std::move(p)); + assert(*ptr == 3); + } +#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES +} Index: test/std/utilities/utility/pairs/pair.astuple/pairs.by.type.pass.cpp =================================================================== --- test/std/utilities/utility/pairs/pair.astuple/pairs.by.type.pass.cpp +++ test/std/utilities/utility/pairs/pair.astuple/pairs.by.type.pass.cpp @@ -40,5 +40,13 @@ assert(std::get<0>(t) == nullptr); // has been moved from } + { + typedef std::unique_ptr upint; + const std::pair t(upint(new int(4)), 42); + const upint&& p = std::get<0>(std::move(t)); // get const rvalue + assert(*p == 4); + assert(std::get<0>(t) != nullptr); + } + #endif }