make_from_tuple.pass.cpp 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  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. // UNSUPPORTED: c++98, c++03, c++11, c++14
  10. // <tuple>
  11. // template <class T, class Tuple> constexpr T make_from_tuple(Tuple&&);
  12. #include <tuple>
  13. #include <array>
  14. #include <utility>
  15. #include <string>
  16. #include <cassert>
  17. #include "test_macros.h"
  18. #include "type_id.h"
  19. // std::array is explicitly allowed to be initialized with A a = { init-list };.
  20. // Disable the missing braces warning for this reason.
  21. #include "disable_missing_braces_warning.h"
  22. template <class Tuple>
  23. struct ConstexprConstructibleFromTuple {
  24. template <class ...Args>
  25. explicit constexpr ConstexprConstructibleFromTuple(Args&&... xargs)
  26. : args{std::forward<Args>(xargs)...} {}
  27. Tuple args;
  28. };
  29. template <class TupleLike>
  30. struct ConstructibleFromTuple;
  31. template <template <class ...> class Tuple, class ...Types>
  32. struct ConstructibleFromTuple<Tuple<Types...>> {
  33. template <class ...Args>
  34. explicit ConstructibleFromTuple(Args&&... xargs)
  35. : args(xargs...),
  36. arg_types(&makeArgumentID<Args&&...>())
  37. {}
  38. Tuple<std::decay_t<Types>...> args;
  39. TypeID const* arg_types;
  40. };
  41. template <class Tp, size_t N>
  42. struct ConstructibleFromTuple<std::array<Tp, N>> {
  43. template <class ...Args>
  44. explicit ConstructibleFromTuple(Args&&... xargs)
  45. : args{xargs...},
  46. arg_types(&makeArgumentID<Args&&...>())
  47. {}
  48. std::array<Tp, N> args;
  49. TypeID const* arg_types;
  50. };
  51. template <class Tuple>
  52. constexpr bool do_constexpr_test(Tuple&& tup) {
  53. using RawTuple = std::decay_t<Tuple>;
  54. using Tp = ConstexprConstructibleFromTuple<RawTuple>;
  55. return std::make_from_tuple<Tp>(std::forward<Tuple>(tup)).args == tup;
  56. }
  57. // Needed by do_forwarding_test() since it compares pairs of different types.
  58. template <class T1, class T2, class U1, class U2>
  59. inline bool operator==(const std::pair<T1, T2>& lhs, const std::pair<U1, U2>& rhs) {
  60. return lhs.first == rhs.first && lhs.second == rhs.second;
  61. }
  62. template <class ...ExpectTypes, class Tuple>
  63. bool do_forwarding_test(Tuple&& tup) {
  64. using RawTuple = std::decay_t<Tuple>;
  65. using Tp = ConstructibleFromTuple<RawTuple>;
  66. const Tp value = std::make_from_tuple<Tp>(std::forward<Tuple>(tup));
  67. return value.args == tup
  68. && value.arg_types == &makeArgumentID<ExpectTypes...>();
  69. }
  70. void test_constexpr_construction() {
  71. {
  72. constexpr std::tuple<> tup;
  73. static_assert(do_constexpr_test(tup), "");
  74. }
  75. {
  76. constexpr std::tuple<int> tup(42);
  77. static_assert(do_constexpr_test(tup), "");
  78. }
  79. {
  80. constexpr std::tuple<int, long, void*> tup(42, 101, nullptr);
  81. static_assert(do_constexpr_test(tup), "");
  82. }
  83. {
  84. constexpr std::pair<int, const char*> p(42, "hello world");
  85. static_assert(do_constexpr_test(p), "");
  86. }
  87. {
  88. using Tuple = std::array<int, 3>;
  89. using ValueTp = ConstexprConstructibleFromTuple<Tuple>;
  90. constexpr Tuple arr = {42, 101, -1};
  91. constexpr ValueTp value = std::make_from_tuple<ValueTp>(arr);
  92. static_assert(value.args[0] == arr[0] && value.args[1] == arr[1]
  93. && value.args[2] == arr[2], "");
  94. }
  95. }
  96. void test_perfect_forwarding() {
  97. {
  98. using Tup = std::tuple<>;
  99. Tup tup;
  100. Tup const& ctup = tup;
  101. assert(do_forwarding_test<>(tup));
  102. assert(do_forwarding_test<>(ctup));
  103. }
  104. {
  105. using Tup = std::tuple<int>;
  106. Tup tup(42);
  107. Tup const& ctup = tup;
  108. assert(do_forwarding_test<int&>(tup));
  109. assert(do_forwarding_test<int const&>(ctup));
  110. assert(do_forwarding_test<int&&>(std::move(tup)));
  111. assert(do_forwarding_test<int const&&>(std::move(ctup)));
  112. }
  113. {
  114. using Tup = std::tuple<int&, const char*, unsigned&&>;
  115. int x = 42;
  116. unsigned y = 101;
  117. Tup tup(x, "hello world", std::move(y));
  118. Tup const& ctup = tup;
  119. assert((do_forwarding_test<int&, const char*&, unsigned&>(tup)));
  120. assert((do_forwarding_test<int&, const char* const&, unsigned &>(ctup)));
  121. assert((do_forwarding_test<int&, const char*&&, unsigned&&>(std::move(tup))));
  122. assert((do_forwarding_test<int&, const char* const&&, unsigned &&>(std::move(ctup))));
  123. }
  124. // test with pair<T, U>
  125. {
  126. using Tup = std::pair<int&, const char*>;
  127. int x = 42;
  128. Tup tup(x, "hello world");
  129. Tup const& ctup = tup;
  130. assert((do_forwarding_test<int&, const char*&>(tup)));
  131. assert((do_forwarding_test<int&, const char* const&>(ctup)));
  132. assert((do_forwarding_test<int&, const char*&&>(std::move(tup))));
  133. assert((do_forwarding_test<int&, const char* const&&>(std::move(ctup))));
  134. }
  135. // test with array<T, I>
  136. {
  137. using Tup = std::array<int, 3>;
  138. Tup tup = {42, 101, -1};
  139. Tup const& ctup = tup;
  140. assert((do_forwarding_test<int&, int&, int&>(tup)));
  141. assert((do_forwarding_test<int const&, int const&, int const&>(ctup)));
  142. assert((do_forwarding_test<int&&, int&&, int&&>(std::move(tup))));
  143. assert((do_forwarding_test<int const&&, int const&&, int const&&>(std::move(ctup))));
  144. }
  145. }
  146. void test_noexcept() {
  147. struct NothrowMoveable {
  148. NothrowMoveable() = default;
  149. NothrowMoveable(NothrowMoveable const&) {}
  150. NothrowMoveable(NothrowMoveable&&) noexcept {}
  151. };
  152. struct TestType {
  153. TestType(int, NothrowMoveable) noexcept {}
  154. TestType(int, int, int) noexcept(false) {}
  155. TestType(long, long, long) noexcept {}
  156. };
  157. {
  158. using Tuple = std::tuple<int, NothrowMoveable>;
  159. Tuple tup; ((void)tup);
  160. Tuple const& ctup = tup; ((void)ctup);
  161. ASSERT_NOT_NOEXCEPT(std::make_from_tuple<TestType>(ctup));
  162. LIBCPP_ASSERT_NOEXCEPT(std::make_from_tuple<TestType>(std::move(tup)));
  163. }
  164. {
  165. using Tuple = std::pair<int, NothrowMoveable>;
  166. Tuple tup; ((void)tup);
  167. Tuple const& ctup = tup; ((void)ctup);
  168. ASSERT_NOT_NOEXCEPT(std::make_from_tuple<TestType>(ctup));
  169. LIBCPP_ASSERT_NOEXCEPT(std::make_from_tuple<TestType>(std::move(tup)));
  170. }
  171. {
  172. using Tuple = std::tuple<int, int, int>;
  173. Tuple tup; ((void)tup);
  174. ASSERT_NOT_NOEXCEPT(std::make_from_tuple<TestType>(tup));
  175. }
  176. {
  177. using Tuple = std::tuple<long, long, long>;
  178. Tuple tup; ((void)tup);
  179. LIBCPP_ASSERT_NOEXCEPT(std::make_from_tuple<TestType>(tup));
  180. }
  181. {
  182. using Tuple = std::array<int, 3>;
  183. Tuple tup; ((void)tup);
  184. ASSERT_NOT_NOEXCEPT(std::make_from_tuple<TestType>(tup));
  185. }
  186. {
  187. using Tuple = std::array<long, 3>;
  188. Tuple tup; ((void)tup);
  189. LIBCPP_ASSERT_NOEXCEPT(std::make_from_tuple<TestType>(tup));
  190. }
  191. }
  192. int main()
  193. {
  194. test_constexpr_construction();
  195. test_perfect_forwarding();
  196. test_noexcept();
  197. }