make_from_tuple.pass.cpp 6.8 KB

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