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> class tuple; 12 13 // UNSUPPORTED: c++03 14 15 #include <tuple> 16 #include <utility> 17 #include <cassert> 18 19 #include "test_macros.h" 20 21 template <class ConstructFrom> 22 struct ConstructibleFromT { 23 ConstructibleFromT() = default; 24 ConstructibleFromT(ConstructFrom v) : value(v) {} 25 ConstructFrom value; 26 }; 27 28 template <class AssertOn> 29 struct CtorAssertsT { 30 bool defaulted; 31 CtorAssertsT() : defaulted(true) {} 32 template <class T> 33 constexpr CtorAssertsT(T) : defaulted(false) { 34 static_assert(!std::is_same<T, AssertOn>::value, ""); 35 } 36 }; 37 38 template <class AllowT, class AssertT> 39 struct AllowAssertT { 40 AllowAssertT() = default; 41 AllowAssertT(AllowT) {} 42 template <class U> 43 constexpr AllowAssertT(U) { 44 static_assert(!std::is_same<U, AssertT>::value, ""); 45 } 46 }; 47 48 // Construct a tuple<T1, T2> from pair<int, int> where T1 and T2 49 // are not constructible from ints but T1 is constructible from std::pair. 50 // This considers the following constructors: 51 // (1) tuple(TupleLike) -> checks is_constructible<Tn, int> 52 // (2) tuple(UTypes...) -> checks is_constructible<T1, pair<int, int>> 53 // and is_default_constructible<T2> 54 // The point of this test is to ensure that the consideration of (1) 55 // short circuits before evaluating is_constructible<T2, int>, which 56 // will cause a static assertion. 57 void test_tuple_like_lazy_sfinae() { 58 #if defined(_LIBCPP_VERSION) 59 // This test requires libc++'s reduced arity initialization. 60 using T1 = ConstructibleFromT<std::pair<int, int>>; 61 using T2 = CtorAssertsT<int>; 62 std::pair<int, int> p(42, 100); 63 std::tuple<T1, T2> t(p); 64 assert(std::get<0>(t).value == p); 65 assert(std::get<1>(t).defaulted); 66 #endif 67 } 68 69 70 struct NonConstCopyable { 71 NonConstCopyable() = default; 72 explicit NonConstCopyable(int v) : value(v) {} 73 NonConstCopyable(NonConstCopyable&) = default; 74 NonConstCopyable(NonConstCopyable const&) = delete; 75 int value; 76 }; 77 78 template <class T> 79 struct BlowsUpOnConstCopy { 80 BlowsUpOnConstCopy() = default; 81 constexpr BlowsUpOnConstCopy(BlowsUpOnConstCopy const&) { 82 static_assert(!std::is_same<T, T>::value, ""); 83 } 84 BlowsUpOnConstCopy(BlowsUpOnConstCopy&) = default; 85 }; 86 87 // Test the following constructors: 88 // (1) tuple(Types const&...) 89 // (2) tuple(UTypes&&...) 90 // Test that (1) short circuits before evaluating the copy constructor of the 91 // second argument. Constructor (2) should be selected. 92 void test_const_Types_lazy_sfinae() 93 { 94 NonConstCopyable v(42); 95 BlowsUpOnConstCopy<int> b; 96 std::tuple<NonConstCopyable, BlowsUpOnConstCopy<int>> t(v, b); 97 assert(std::get<0>(t).value == 42); 98 } 99 100 int main(int, char**) { 101 test_tuple_like_lazy_sfinae(); 102 test_const_Types_lazy_sfinae(); 103 104 return 0; 105 } 106