diff --git a/include/tuple b/include/tuple index 0df315e2a..d8a36e6e9 100644 --- a/include/tuple +++ b/include/tuple @@ -94,6 +94,13 @@ template typename tuple_element>::type&& get(tuple&&) noexcept; +template + constexpr T1& get(tuple&) noexcept; // C++14 +template + constexpr T1 const& get(const tuple&) noexcept; // C++14 +template + constexpr T1&& get(tuple&&) noexcept; // C++14 + // 20.4.1.6, relational operators: template bool operator==(const tuple&, const tuple&); template bool operator<(const tuple&, const tuple&); @@ -783,6 +790,64 @@ get(tuple<_Tp...>&& __t) _NOEXCEPT static_cast<__tuple_leaf<_Ip, type>&&>(__t.base_).get()); } +#if _LIBCPP_STD_VER > 11 +// get by type +template +struct __find_exactly_one_t_helper; + +// -- find exactly one +template +struct __find_exactly_one_t_checker { + static constexpr size_t value = _Idx; +// Check the rest of the list to make sure there's only one + static_assert ( __find_exactly_one_t_helper<_T1, 0, _Args...>::value == -1, "type can only occur once in type list" ); + }; + + +template +struct __find_exactly_one_t_helper <_T1, _Idx> { + static constexpr size_t value = -1; + }; + +template +struct __find_exactly_one_t_helper <_T1, _Idx, _Head, _Args...> { + static constexpr size_t value = + std::conditional< + std::is_same<_T1, _Head>::value, + __find_exactly_one_t_checker<_T1, _Idx,   _Args...>, + __find_exactly_one_t_helper <_T1, _Idx+1, _Args...> + >::type::value; + }; + +template +struct __find_exactly_one_t { + static constexpr size_t value = __find_exactly_one_t_helper<_T1, 0, _Args...>::value; + static_assert ( value != -1, "type not found in type list" ); + }; + +template +inline _LIBCPP_INLINE_VISIBILITY +constexpr _T1& get(tuple<_Args...>& __tup) noexcept +{ + return _VSTD::get<__find_exactly_one_t<_T1, _Args...>::value>(__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>(__tup); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +constexpr _T1&& get(tuple<_Args...>&& __tup) noexcept +{ + return _VSTD::get<__find_exactly_one_t<_T1, _Args...>::value>(_VSTD::move>(__tup)); +} + +#endif + // tie template diff --git a/include/utility b/include/utility index bea463bbd..3e4b401f2 100644 --- a/include/utility +++ b/include/utility @@ -117,6 +117,15 @@ template typename tuple_element >::type&& get(std::pair&&) noexcept; +template + constexpr T1& get(std::pair&) noexcept; // C++14 + +template + constexpr T1 const& get(std::pair const &) noexcept; // C++14 + +template + constexpr T1&& get(std::pair&&) noexcept; // C++14 + // C++14 template @@ -601,6 +610,51 @@ get(pair<_T1, _T2>&& __p) _NOEXCEPT #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES +#if _LIBCPP_STD_VER > 11 +template +_LIBCPP_INLINE_VISIBILITY inline +constexpr _T1 & get(pair<_T1, _T2>& __p) _NOEXCEPT +{ + return __get_pair<0>::get(__p); +} + +template +_LIBCPP_INLINE_VISIBILITY inline +constexpr _T1 const & get(pair<_T1, _T2> const& __p) _NOEXCEPT +{ + return __get_pair<0>::get(__p); +} + +template +_LIBCPP_INLINE_VISIBILITY inline +constexpr _T1 && get(pair<_T1, _T2>&& __p) _NOEXCEPT +{ + return __get_pair<0>::get(_VSTD::move(__p)); +} + +template +_LIBCPP_INLINE_VISIBILITY inline +constexpr _T1 & get(pair<_T2, _T1>& __p) _NOEXCEPT +{ + return __get_pair<1>::get(__p); +} + +template +_LIBCPP_INLINE_VISIBILITY inline +constexpr _T1 const & get(pair<_T2, _T1> const& __p) _NOEXCEPT +{ + return __get_pair<1>::get(__p); +} + +template +_LIBCPP_INLINE_VISIBILITY inline +constexpr _T1 && get(pair<_T2, _T1>&& __p) _NOEXCEPT +{ + return __get_pair<1>::get(_VSTD::move(__p)); +} + +#endif + #if _LIBCPP_STD_VER > 11 template diff --git a/test/utilities/tuple/tuple.tuple/tuple.elem/tuple.by.type.pass.cpp b/test/utilities/tuple/tuple.tuple/tuple.elem/tuple.by.type.pass.cpp new file mode 100644 index 000000000..1835a9f52 --- /dev/null +++ b/test/utilities/tuple/tuple.tuple/tuple.elem/tuple.by.type.pass.cpp @@ -0,0 +1,52 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +#include +#include +#include + +#include + +int main() +{ +#if _LIBCPP_STD_VER > 11 + typedef std::complex cf; + { + auto t1 = std::tuple { 42, "Hi", { 1,2 }}; + assert ( std::get(t1) == 42 ); // find at the beginning + assert ( std::get(t1) == "Hi" ); // find in the middle + assert ( std::get(t1).real() == 1 ); // find at the end + assert ( std::get(t1).imag() == 2 ); + } + + { + auto t2 = std::tuple { 42, "Hi", 23, { 1,2 }}; +// get would fail! + assert ( std::get(t2) == "Hi" ); + assert (( std::get(t2) == cf{ 1,2 } )); + } + + { + const std::tuple p5 { 1, 2, 3.4, 5.6 }; + const int &i1 = std::get(p5); + const int &i2 = std::get(p5); + assert ( i1 == 1 ); + assert ( i2 == 2 ); + } + + { + typedef std::unique_ptr upint; + std::tuple t(upint(new int(4))); + upint p = std::get(std::move(t)); // get rvalue + assert(*p == 4); + assert(std::get<0>(t) == nullptr); // has been moved from + } + +#endif +} diff --git a/test/utilities/tuple/tuple.tuple/tuple.elem/tuple.by.type1.fail.cpp b/test/utilities/tuple/tuple.tuple/tuple.elem/tuple.by.type1.fail.cpp new file mode 100644 index 000000000..094f80905 --- /dev/null +++ b/test/utilities/tuple/tuple.tuple/tuple.elem/tuple.by.type1.fail.cpp @@ -0,0 +1,25 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +#include +#include +#include + +#include + +int main() +{ +#if _LIBCPP_STD_VER > 11 + typedef std::complex cf; + auto t1 = std::make_tuple ( 42, "Hi" ); + assert ( std::get(t1) == cf {1,2} ); // no such type +#else +#error +#endif +} diff --git a/test/utilities/tuple/tuple.tuple/tuple.elem/tuple.by.type2.fail.cpp b/test/utilities/tuple/tuple.tuple/tuple.elem/tuple.by.type2.fail.cpp new file mode 100644 index 000000000..0b2fac04c --- /dev/null +++ b/test/utilities/tuple/tuple.tuple/tuple.elem/tuple.by.type2.fail.cpp @@ -0,0 +1,25 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +#include +#include +#include + +#include + +int main() +{ +#if _LIBCPP_STD_VER > 11 + typedef std::complex cf; + auto t1 = std::make_tuple ( 42, 21, "Hi", { 1,2 } ); + assert ( std::get(t1) == 42 ); // two ints here +#else +#error +#endif +} diff --git a/test/utilities/tuple/tuple.tuple/tuple.elem/tuple.by.type3.fail.cpp b/test/utilities/tuple/tuple.tuple/tuple.elem/tuple.by.type3.fail.cpp new file mode 100644 index 000000000..f1881717b --- /dev/null +++ b/test/utilities/tuple/tuple.tuple/tuple.elem/tuple.by.type3.fail.cpp @@ -0,0 +1,25 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +#include +#include +#include + +#include + +int main() +{ +#if _LIBCPP_STD_VER > 11 + typedef std::complex cf; + auto t1 = std::make_tuple ( 42, 21, "Hi", { 1,2 } ); + assert ( std::get(t1) == 42 ); // two ints here (one at the end) +#else +#error +#endif +} diff --git a/test/utilities/tuple/tuple.tuple/tuple.elem/tuple.by.type4.fail.cpp b/test/utilities/tuple/tuple.tuple/tuple.elem/tuple.by.type4.fail.cpp new file mode 100644 index 000000000..e78c4f107 --- /dev/null +++ b/test/utilities/tuple/tuple.tuple/tuple.elem/tuple.by.type4.fail.cpp @@ -0,0 +1,25 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +#include +#include +#include + +#include + +int main() +{ +#if _LIBCPP_STD_VER > 11 + typedef std::unique_ptr upint; + std::tuple t(upint(new int(4))); + upint p = std::get(t); +#else +#error +#endif +} diff --git a/test/utilities/utility/pairs/pair.astuple/pairs.by.type.pass.cpp b/test/utilities/utility/pairs/pair.astuple/pairs.by.type.pass.cpp new file mode 100644 index 000000000..176d58330 --- /dev/null +++ b/test/utilities/utility/pairs/pair.astuple/pairs.by.type.pass.cpp @@ -0,0 +1,44 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +#include +#include +#include + +#include + +int main() +{ +#if _LIBCPP_STD_VER > 11 + typedef std::complex cf; + { + auto t1 = std::make_pair ( 42, { 1,2 } ); + assert ( std::get(t1) == 42 ); + assert ( std::get(t1).real() == 1 ); + assert ( std::get(t1).imag() == 2 ); + } + + { + const std::pair p1 { 1, 2 }; + const int &i1 = std::get(p1); + const int &i2 = std::get(p1); + assert ( i1 == 1 ); + assert ( i2 == 2 ); + } + + { + typedef std::unique_ptr upint; + std::pair t(upint(new int(4)), 42); + upint p = std::get<0>(std::move(t)); // get rvalue + assert(*p == 4); + assert(std::get<0>(t) == nullptr); // has been moved from + } + +#endif +} diff --git a/test/utilities/utility/pairs/pair.astuple/pairs.by.type1.fail.cpp b/test/utilities/utility/pairs/pair.astuple/pairs.by.type1.fail.cpp new file mode 100644 index 000000000..1c01ed74d --- /dev/null +++ b/test/utilities/utility/pairs/pair.astuple/pairs.by.type1.fail.cpp @@ -0,0 +1,24 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +#include +#include + +#include + +int main() +{ +#if _LIBCPP_STD_VER > 11 + typedef std::complex cf; + auto t1 = std::make_pair ( 42, 3.4 ); + assert ( std::get(t1) == cf {1,2} ); // no such type +#else +#error +#endif +} diff --git a/test/utilities/utility/pairs/pair.astuple/pairs.by.type2.fail.cpp b/test/utilities/utility/pairs/pair.astuple/pairs.by.type2.fail.cpp new file mode 100644 index 000000000..f9e3942d7 --- /dev/null +++ b/test/utilities/utility/pairs/pair.astuple/pairs.by.type2.fail.cpp @@ -0,0 +1,24 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +#include +#include + +#include + +int main() +{ +#if _LIBCPP_STD_VER > 11 + typedef std::complex cf; + auto t1 = std::make_pair ( 42, 43 ); + assert ( std::get(t1) == 42 ); // two ints +#else +#error +#endif +} diff --git a/test/utilities/utility/pairs/pair.astuple/pairs.by.type3.fail.cpp b/test/utilities/utility/pairs/pair.astuple/pairs.by.type3.fail.cpp new file mode 100644 index 000000000..8bf35c7b3 --- /dev/null +++ b/test/utilities/utility/pairs/pair.astuple/pairs.by.type3.fail.cpp @@ -0,0 +1,24 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +#include +#include + +#include + +int main() +{ +#if _LIBCPP_STD_VER > 11 + typedef std::unique_ptr upint; + std::pair t(upint(new int(4)), 23); + upint p = std::get(t); +#else +#error +#endif +}