make_from_tuple.pass.cpp 7.0 KB

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