1 //===----------------------------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 // <tuple> 10 11 // template <class... Types> 12 // template <class U1, class U2> 13 // constexpr explicit(see below) tuple<Types...>::tuple(const pair<U1, U2>&& u); 14 15 // Constraints: 16 // - sizeof...(Types) is 2 and 17 // - is_constructible_v<T0, decltype(get<0>(FWD(u)))> is true and 18 // - is_constructible_v<T1, decltype(get<1>(FWD(u)))> is true. 19 20 // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 21 22 #include <cassert> 23 #include <tuple> 24 #include <utility> 25 26 #include "convert_types.h" 27 28 // test constraints 29 // sizeof...(Types) == 2 30 static_assert(std::is_constructible_v<std::tuple<ConstMove, int>, const std::pair<ConstMove, int>&&>); 31 32 static_assert(!std::is_constructible_v<std::tuple<ConstMove>, const std::pair<ConstMove, int>&&>); 33 34 static_assert(!std::is_constructible_v<std::tuple<ConstMove, int, int>, const std::pair<ConstMove, int>&&>); 35 36 // test constraints 37 // is_constructible_v<T0, decltype(get<0>(FWD(u)))> is true and 38 // is_constructible_v<T1, decltype(get<1>(FWD(u)))> is true. 39 static_assert(std::is_constructible_v<std::tuple<int, int>, const std::pair<int, int>&&>); 40 41 static_assert(!std::is_constructible_v<std::tuple<NoConstructorFromInt, int>, const std::pair<int, int>&&>); 42 43 static_assert(!std::is_constructible_v<std::tuple<int, NoConstructorFromInt>, const std::pair<int, int>&&>); 44 45 static_assert( 46 !std::is_constructible_v< std::tuple<NoConstructorFromInt, NoConstructorFromInt>, const std::pair<int, int>&&>); 47 48 // test: The expression inside explicit is equivalent to: 49 // !is_convertible_v<decltype(get<0>(FWD(u))), T0> || 50 // !is_convertible_v<decltype(get<1>(FWD(u))), T1> 51 static_assert(std::is_convertible_v<const std::pair<ConstMove, ConstMove>&&, 52 std::tuple<ConvertibleFrom<ConstMove>, ConvertibleFrom<ConstMove>>>); 53 54 static_assert(!std::is_convertible_v<const std::pair<ConstMove, ConstMove>&&, 55 std::tuple<ExplicitConstructibleFrom<ConstMove>, ConvertibleFrom<ConstMove>>>); 56 57 static_assert(!std::is_convertible_v<const std::pair<ConstMove, ConstMove>&&, 58 std::tuple<ConvertibleFrom<ConstMove>, ExplicitConstructibleFrom<ConstMove>>>); 59 60 constexpr bool test() { 61 // test implicit conversions. 62 { 63 const std::pair<ConstMove, int> p{1, 2}; 64 std::tuple<ConvertibleFrom<ConstMove>, ConvertibleFrom<int>> t = std::move(p); 65 assert(std::get<0>(t).v.val == 1); 66 assert(std::get<1>(t).v == 2); 67 } 68 69 // test explicit conversions. 70 { 71 const std::pair<ConstMove, int> p{1, 2}; 72 std::tuple<ExplicitConstructibleFrom<ConstMove>, ExplicitConstructibleFrom<int>> t{std::move(p)}; 73 assert(std::get<0>(t).v.val == 1); 74 assert(std::get<1>(t).v == 2); 75 } 76 77 // non const overload should be called 78 { 79 const std::pair<TracedCopyMove, TracedCopyMove> p; 80 std::tuple<ConvertibleFrom<TracedCopyMove>, TracedCopyMove> t = std::move(p); 81 assert(constMoveCtrCalled(std::get<0>(t).v)); 82 assert(constMoveCtrCalled(std::get<1>(t))); 83 } 84 85 return true; 86 } 87 88 int main() { 89 test(); 90 static_assert(test()); 91 92 return 0; 93 } 94