| 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 | // UNSUPPORTED: c++03 |
| 10 | |
| 11 | // <utility> |
| 12 | |
| 13 | // template <class T1, class T2> struct pair |
| 14 | |
| 15 | // template<class U = T1, class V = T2> pair(U&&, V&&); |
| 16 | |
| 17 | #include <utility> |
| 18 | #include <cassert> |
| 19 | #include <memory> |
| 20 | |
| 21 | #include "archetypes.h" |
| 22 | #include "test_convertible.h" |
| 23 | |
| 24 | #include "test_macros.h" |
| 25 | using namespace ImplicitTypes; // Get implicitly archetypes |
| 26 | |
| 27 | template <class T1, class T1Arg, |
| 28 | bool CanCopy = true, bool CanConvert = CanCopy> |
| 29 | void test_sfinae() { |
| 30 | using P1 = std::pair<T1, int>; |
| 31 | using P2 = std::pair<int, T1>; |
| 32 | using T2 = int const&; |
| 33 | static_assert(std::is_constructible<P1, T1Arg, T2>::value == CanCopy, "" ); |
| 34 | static_assert(test_convertible<P1, T1Arg, T2>() == CanConvert, "" ); |
| 35 | static_assert(std::is_constructible<P2, T2, T1Arg>::value == CanCopy, "" ); |
| 36 | static_assert(test_convertible<P2, T2, T1Arg>() == CanConvert, "" ); |
| 37 | } |
| 38 | |
| 39 | struct ExplicitT { |
| 40 | constexpr explicit ExplicitT(int x) : value(x) {} |
| 41 | int value; |
| 42 | }; |
| 43 | |
| 44 | struct ImplicitT { |
| 45 | constexpr ImplicitT(int x) : value(x) {} |
| 46 | int value; |
| 47 | }; |
| 48 | |
| 49 | int main(int, char**) |
| 50 | { |
| 51 | { |
| 52 | typedef std::pair<std::unique_ptr<int>, short*> P; |
| 53 | P p(std::unique_ptr<int>(new int(3)), nullptr); |
| 54 | assert(*p.first == 3); |
| 55 | assert(p.second == nullptr); |
| 56 | } |
| 57 | { |
| 58 | // Test non-const lvalue and rvalue types |
| 59 | test_sfinae<AllCtors, AllCtors&>(); |
| 60 | test_sfinae<AllCtors, AllCtors&&>(); |
| 61 | test_sfinae<ExplicitTypes::AllCtors, ExplicitTypes::AllCtors&, true, false>(); |
| 62 | test_sfinae<ExplicitTypes::AllCtors, ExplicitTypes::AllCtors&&, true, false>(); |
| 63 | test_sfinae<CopyOnly, CopyOnly&>(); |
| 64 | test_sfinae<CopyOnly, CopyOnly&&>(); |
| 65 | test_sfinae<ExplicitTypes::CopyOnly, ExplicitTypes::CopyOnly&, true, false>(); |
| 66 | test_sfinae<ExplicitTypes::CopyOnly, ExplicitTypes::CopyOnly&&, true, false>(); |
| 67 | test_sfinae<MoveOnly, MoveOnly&, false>(); |
| 68 | test_sfinae<MoveOnly, MoveOnly&&>(); |
| 69 | test_sfinae<ExplicitTypes::MoveOnly, ExplicitTypes::MoveOnly&, false>(); |
| 70 | test_sfinae<ExplicitTypes::MoveOnly, ExplicitTypes::MoveOnly&&, true, false>(); |
| 71 | test_sfinae<NonCopyable, NonCopyable&, false>(); |
| 72 | test_sfinae<NonCopyable, NonCopyable&&, false>(); |
| 73 | test_sfinae<ExplicitTypes::NonCopyable, ExplicitTypes::NonCopyable&, false>(); |
| 74 | test_sfinae<ExplicitTypes::NonCopyable, ExplicitTypes::NonCopyable&&, false>(); |
| 75 | } |
| 76 | { |
| 77 | // Test converting types |
| 78 | test_sfinae<ConvertingType, int&>(); |
| 79 | test_sfinae<ConvertingType, const int&>(); |
| 80 | test_sfinae<ConvertingType, int&&>(); |
| 81 | test_sfinae<ConvertingType, const int&&>(); |
| 82 | test_sfinae<ExplicitTypes::ConvertingType, int&, true, false>(); |
| 83 | test_sfinae<ExplicitTypes::ConvertingType, const int&, true, false>(); |
| 84 | test_sfinae<ExplicitTypes::ConvertingType, int&&, true, false>(); |
| 85 | test_sfinae<ExplicitTypes::ConvertingType, const int&&, true, false>(); |
| 86 | } |
| 87 | #if TEST_STD_VER > 11 |
| 88 | { // explicit constexpr test |
| 89 | constexpr std::pair<ExplicitT, ExplicitT> p(42, 43); |
| 90 | static_assert(p.first.value == 42, "" ); |
| 91 | static_assert(p.second.value == 43, "" ); |
| 92 | } |
| 93 | { // implicit constexpr test |
| 94 | constexpr std::pair<ImplicitT, ImplicitT> p = {42, 43}; |
| 95 | static_assert(p.first.value == 42, "" ); |
| 96 | static_assert(p.second.value == 43, "" ); |
| 97 | } |
| 98 | #endif |
| 99 | |
| 100 | // Test support for http://wg21.link/P1951, default arguments for pair's constructor. |
| 101 | // Basically, this turns copies for brace initialization into moves. |
| 102 | #if TEST_STD_VER > 20 |
| 103 | { |
| 104 | struct TrackInit { |
| 105 | TrackInit() = default; |
| 106 | constexpr TrackInit(TrackInit const& other) : wasMoveInit(other.wasMoveInit), wasCopyInit(true) { } |
| 107 | constexpr TrackInit(TrackInit&& other) : wasMoveInit(true), wasCopyInit(other.wasCopyInit) { } |
| 108 | bool wasMoveInit = false; |
| 109 | bool wasCopyInit = false; |
| 110 | }; |
| 111 | |
| 112 | // Explicit constructor |
| 113 | { |
| 114 | { |
| 115 | std::pair<TrackInit, int> p({}, 3); |
| 116 | assert( p.first.wasMoveInit); |
| 117 | assert(!p.first.wasCopyInit); |
| 118 | } |
| 119 | { |
| 120 | std::pair<int, TrackInit> p(3, {}); |
| 121 | assert( p.second.wasMoveInit); |
| 122 | assert(!p.second.wasCopyInit); |
| 123 | } |
| 124 | } |
| 125 | |
| 126 | // Implicit constructor |
| 127 | { |
| 128 | { |
| 129 | std::pair<TrackInit, int> p = {{}, 3}; |
| 130 | assert( p.first.wasMoveInit); |
| 131 | assert(!p.first.wasCopyInit); |
| 132 | } |
| 133 | { |
| 134 | std::pair<int, TrackInit> p = {3, {}}; |
| 135 | assert( p.second.wasMoveInit); |
| 136 | assert(!p.second.wasCopyInit); |
| 137 | } |
| 138 | } |
| 139 | } |
| 140 | #endif // TEST_STD_VER > 20 |
| 141 | |
| 142 | return 0; |
| 143 | } |
| 144 | |