1 //===----------------------------------------------------------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is dual licensed under the MIT and the University of Illinois Open 6 // Source Licenses. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 // <tuple> 11 12 // template <class... Types> class tuple; 13 14 // template <class... UTypes> 15 // explicit tuple(UTypes&&... u); 16 17 // UNSUPPORTED: c++98, c++03 18 19 #include <tuple> 20 #include <cassert> 21 #include <type_traits> 22 #include <string> 23 #include <system_error> 24 25 #include "test_macros.h" 26 #include "test_convertible.hpp" 27 #include "MoveOnly.h" 28 29 #if defined(_LIBCPP_ENABLE_TUPLE_IMPLICIT_REDUCED_ARITY_EXTENSION) 30 #error This macro should not be defined by default 31 #endif 32 33 struct NoDefault { NoDefault() = delete; }; 34 35 36 // Make sure the _Up... constructor SFINAEs out when the types that 37 // are not explicitly initialized are not all default constructible. 38 // Otherwise, std::is_constructible would return true but instantiating 39 // the constructor would fail. 40 void test_default_constructible_extension_sfinae() 41 { 42 typedef MoveOnly MO; 43 typedef NoDefault ND; 44 { 45 typedef std::tuple<MO, ND> Tuple; 46 static_assert(!std::is_constructible<Tuple, MO>::value, ""); 47 static_assert(std::is_constructible<Tuple, MO, ND>::value, ""); 48 static_assert(test_convertible<Tuple, MO, ND>(), ""); 49 } 50 { 51 typedef std::tuple<MO, MO, ND> Tuple; 52 static_assert(!std::is_constructible<Tuple, MO, MO>::value, ""); 53 static_assert(std::is_constructible<Tuple, MO, MO, ND>::value, ""); 54 static_assert(test_convertible<Tuple, MO, MO, ND>(), ""); 55 } 56 { 57 // Same idea as above but with a nested tuple type. 58 typedef std::tuple<MO, ND> Tuple; 59 typedef std::tuple<MO, Tuple, MO, MO> NestedTuple; 60 61 static_assert(!std::is_constructible< 62 NestedTuple, MO, MO, MO, MO>::value, ""); 63 static_assert(std::is_constructible< 64 NestedTuple, MO, Tuple, MO, MO>::value, ""); 65 } 66 } 67 68 using ExplicitTup = std::tuple<std::string, int, std::error_code>; 69 ExplicitTup doc_example() { 70 return ExplicitTup{"hello world", 42}; // explicit constructor called. OK. 71 } 72 73 // Test that the example given in UsingLibcxx.rst actually works. 74 void test_example_from_docs() { 75 auto tup = doc_example(); 76 assert(std::get<0>(tup) == "hello world"); 77 assert(std::get<1>(tup) == 42); 78 assert(std::get<2>(tup) == std::error_code{}); 79 } 80 81 int main() 82 { 83 { 84 using E = MoveOnly; 85 using Tup = std::tuple<E, E, E>; 86 // Test that the reduced arity initialization extension is only 87 // allowed on the explicit constructor. 88 static_assert(test_convertible<Tup, E, E, E>(), ""); 89 90 Tup t(E(0), E(1)); 91 static_assert(std::is_constructible<Tup, E, E>::value, ""); 92 static_assert(!test_convertible<Tup, E, E>(), ""); 93 assert(std::get<0>(t) == 0); 94 assert(std::get<1>(t) == 1); 95 assert(std::get<2>(t) == MoveOnly()); 96 97 Tup t2(E(0)); 98 static_assert(std::is_constructible<Tup, E>::value, ""); 99 static_assert(!test_convertible<Tup, E>(), ""); 100 assert(std::get<0>(t) == 0); 101 assert(std::get<1>(t) == E()); 102 assert(std::get<2>(t) == E()); 103 } 104 // Check that SFINAE is properly applied with the default reduced arity 105 // constructor extensions. 106 test_default_constructible_extension_sfinae(); 107 test_example_from_docs(); 108 } 109