xref: /llvm-project/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/const_move_pair.pass.cpp (revision 83ead2bbc5e14ca1beb776c062ebc36c38e8bb1c)
116719cd0SHui Xie //===----------------------------------------------------------------------===//
216719cd0SHui Xie //
316719cd0SHui Xie // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
416719cd0SHui Xie // See https://llvm.org/LICENSE.txt for license information.
516719cd0SHui Xie // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
616719cd0SHui Xie //
716719cd0SHui Xie //===----------------------------------------------------------------------===//
816719cd0SHui Xie 
916719cd0SHui Xie // <tuple>
1016719cd0SHui Xie 
1116719cd0SHui Xie // template <class... Types>
1216719cd0SHui Xie // template <class U1, class U2>
1316719cd0SHui Xie // constexpr explicit(see below) tuple<Types...>::tuple(const pair<U1, U2>&& u);
1416719cd0SHui Xie 
1516719cd0SHui Xie // Constraints:
1616719cd0SHui Xie // - sizeof...(Types) is 2 and
1716719cd0SHui Xie // - is_constructible_v<T0, decltype(get<0>(FWD(u)))> is true and
1816719cd0SHui Xie // - is_constructible_v<T1, decltype(get<1>(FWD(u)))> is true.
1916719cd0SHui Xie 
2016719cd0SHui Xie // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
2116719cd0SHui Xie 
2216719cd0SHui Xie #include <cassert>
2316719cd0SHui Xie #include <tuple>
2416719cd0SHui Xie #include <utility>
2516719cd0SHui Xie 
26*83ead2bbSHui Xie #include "copy_move_types.h"
2716719cd0SHui Xie 
2816719cd0SHui Xie // test constraints
2916719cd0SHui Xie // sizeof...(Types) == 2
3016719cd0SHui Xie static_assert(std::is_constructible_v<std::tuple<ConstMove, int>, const std::pair<ConstMove, int>&&>);
3116719cd0SHui Xie 
3216719cd0SHui Xie static_assert(!std::is_constructible_v<std::tuple<ConstMove>, const std::pair<ConstMove, int>&&>);
3316719cd0SHui Xie 
3416719cd0SHui Xie static_assert(!std::is_constructible_v<std::tuple<ConstMove, int, int>, const std::pair<ConstMove, int>&&>);
3516719cd0SHui Xie 
3616719cd0SHui Xie // test constraints
3716719cd0SHui Xie // is_constructible_v<T0, decltype(get<0>(FWD(u)))> is true and
3816719cd0SHui Xie // is_constructible_v<T1, decltype(get<1>(FWD(u)))> is true.
3916719cd0SHui Xie static_assert(std::is_constructible_v<std::tuple<int, int>, const std::pair<int, int>&&>);
4016719cd0SHui Xie 
4116719cd0SHui Xie static_assert(!std::is_constructible_v<std::tuple<NoConstructorFromInt, int>, const std::pair<int, int>&&>);
4216719cd0SHui Xie 
4316719cd0SHui Xie static_assert(!std::is_constructible_v<std::tuple<int, NoConstructorFromInt>, const std::pair<int, int>&&>);
4416719cd0SHui Xie 
4516719cd0SHui Xie static_assert(
4616719cd0SHui Xie     !std::is_constructible_v< std::tuple<NoConstructorFromInt, NoConstructorFromInt>, const std::pair<int, int>&&>);
4716719cd0SHui Xie 
4816719cd0SHui Xie // test: The expression inside explicit is equivalent to:
4916719cd0SHui Xie // !is_convertible_v<decltype(get<0>(FWD(u))), T0> ||
5016719cd0SHui Xie // !is_convertible_v<decltype(get<1>(FWD(u))), T1>
5116719cd0SHui Xie static_assert(std::is_convertible_v<const std::pair<ConstMove, ConstMove>&&,
5216719cd0SHui Xie                                     std::tuple<ConvertibleFrom<ConstMove>, ConvertibleFrom<ConstMove>>>);
5316719cd0SHui Xie 
5416719cd0SHui Xie static_assert(!std::is_convertible_v<const std::pair<ConstMove, ConstMove>&&,
5516719cd0SHui Xie                                      std::tuple<ExplicitConstructibleFrom<ConstMove>, ConvertibleFrom<ConstMove>>>);
5616719cd0SHui Xie 
5716719cd0SHui Xie static_assert(!std::is_convertible_v<const std::pair<ConstMove, ConstMove>&&,
5816719cd0SHui Xie                                      std::tuple<ConvertibleFrom<ConstMove>, ExplicitConstructibleFrom<ConstMove>>>);
5916719cd0SHui Xie 
test()6016719cd0SHui Xie constexpr bool test() {
6116719cd0SHui Xie   // test implicit conversions.
6216719cd0SHui Xie   {
6316719cd0SHui Xie     const std::pair<ConstMove, int> p{1, 2};
6416719cd0SHui Xie     std::tuple<ConvertibleFrom<ConstMove>, ConvertibleFrom<int>> t = std::move(p);
6516719cd0SHui Xie     assert(std::get<0>(t).v.val == 1);
6616719cd0SHui Xie     assert(std::get<1>(t).v == 2);
6716719cd0SHui Xie   }
6816719cd0SHui Xie 
6916719cd0SHui Xie   // test explicit conversions.
7016719cd0SHui Xie   {
7116719cd0SHui Xie     const std::pair<ConstMove, int> p{1, 2};
7216719cd0SHui Xie     std::tuple<ExplicitConstructibleFrom<ConstMove>, ExplicitConstructibleFrom<int>> t{std::move(p)};
7316719cd0SHui Xie     assert(std::get<0>(t).v.val == 1);
7416719cd0SHui Xie     assert(std::get<1>(t).v == 2);
7516719cd0SHui Xie   }
7616719cd0SHui Xie 
7716719cd0SHui Xie   // non const overload should be called
7816719cd0SHui Xie   {
7916719cd0SHui Xie     const std::pair<TracedCopyMove, TracedCopyMove> p;
8016719cd0SHui Xie     std::tuple<ConvertibleFrom<TracedCopyMove>, TracedCopyMove> t = std::move(p);
8116719cd0SHui Xie     assert(constMoveCtrCalled(std::get<0>(t).v));
8216719cd0SHui Xie     assert(constMoveCtrCalled(std::get<1>(t)));
8316719cd0SHui Xie   }
8416719cd0SHui Xie 
8516719cd0SHui Xie   return true;
8616719cd0SHui Xie }
8716719cd0SHui Xie 
main(int,char **)88c72f22bfSLouis Dionne int main(int, char**) {
8916719cd0SHui Xie   test();
9016719cd0SHui Xie   static_assert(test());
9116719cd0SHui Xie 
9216719cd0SHui Xie   return 0;
9316719cd0SHui Xie }
94