functional.cpp 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. // Range v3 library
  2. //
  3. // Copyright Eric Niebler 2014-present
  4. // Copyright Casey Carter 2015
  5. //
  6. // Use, modification and distribution is subject to the
  7. // Boost Software License, Version 1.0. (See accompanying
  8. // file LICENSE_1_0.txt or copy at
  9. // http://www.boost.org/LICENSE_1_0.txt)
  10. //
  11. // Project home: https://github.com/ericniebler/range-v3
  12. #include <memory>
  13. #include <range/v3/functional/invoke.hpp>
  14. #include <range/v3/functional/not_fn.hpp>
  15. #include <range/v3/view/filter.hpp>
  16. #include "../simple_test.hpp"
  17. #include "../test_utils.hpp"
  18. CPP_assert(ranges::constructible_from<ranges::reference_wrapper<int>, int&>);
  19. CPP_assert(!ranges::constructible_from<ranges::reference_wrapper<int>, int&&>);
  20. CPP_assert(!ranges::constructible_from<ranges::reference_wrapper<int &&>, int&>);
  21. CPP_assert(ranges::constructible_from<ranges::reference_wrapper<int &&>, int&&>);
  22. namespace
  23. {
  24. struct Integer
  25. {
  26. int i;
  27. operator int() const { return i; }
  28. bool odd() const { return (i % 2) != 0; }
  29. };
  30. enum class kind { lvalue, const_lvalue, rvalue, const_rvalue };
  31. std::ostream &operator<<(std::ostream &os, kind k)
  32. {
  33. const char* message = nullptr;
  34. switch (k) {
  35. case kind::lvalue:
  36. message = "lvalue";
  37. break;
  38. case kind::const_lvalue:
  39. message = "const_lvalue";
  40. break;
  41. case kind::rvalue:
  42. message = "rvalue";
  43. break;
  44. case kind::const_rvalue:
  45. message = "const_rvalue";
  46. break;
  47. }
  48. return os << message;
  49. }
  50. kind last_call;
  51. template<kind DisableKind>
  52. struct fn
  53. {
  54. bool operator()() &
  55. {
  56. last_call = kind::lvalue;
  57. return DisableKind != kind::lvalue;
  58. }
  59. bool operator()() const &
  60. {
  61. last_call = kind::const_lvalue;
  62. return DisableKind != kind::const_lvalue;
  63. }
  64. bool operator()() &&
  65. {
  66. last_call = kind::rvalue;
  67. return DisableKind != kind::rvalue;
  68. }
  69. bool operator()() const &&
  70. {
  71. last_call = kind::const_rvalue;
  72. return DisableKind != kind::const_rvalue;
  73. }
  74. };
  75. constexpr struct {
  76. template<typename T>
  77. constexpr T&& operator()(T&& arg) const noexcept {
  78. return (T&&)arg;
  79. }
  80. } h = {};
  81. struct A {
  82. int i = 13;
  83. constexpr int f() const noexcept { return 42; }
  84. constexpr /*c++14*/ int g(int j) { return 2 * j; }
  85. };
  86. constexpr int f() noexcept { return 13; }
  87. constexpr int g(int i) { return 2 * i + 1; }
  88. void test_invoke()
  89. {
  90. CHECK(ranges::invoke(f) == 13);
  91. // CHECK(noexcept(ranges::invoke(f) == 13));
  92. CHECK(ranges::invoke(g, 2) == 5);
  93. CHECK(ranges::invoke(h, 42) == 42);
  94. CHECK(noexcept(ranges::invoke(h, 42) == 42));
  95. {
  96. int i = 13;
  97. CHECK(&ranges::invoke(h, i) == &i);
  98. CHECK(noexcept(&ranges::invoke(h, i) == &i));
  99. }
  100. CHECK(ranges::invoke(&A::f, A{}) == 42);
  101. // CHECK(noexcept(ranges::invoke(&A::f, A{}) == 42));
  102. CHECK(ranges::invoke(&A::g, A{}, 2) == 4);
  103. {
  104. A a;
  105. const auto& ca = a;
  106. CHECK(ranges::invoke(&A::f, a) == 42);
  107. // CHECK(noexcept(ranges::invoke(&A::f, a) == 42));
  108. CHECK(ranges::invoke(&A::f, ca) == 42);
  109. // CHECK(noexcept(ranges::invoke(&A::f, ca) == 42));
  110. CHECK(ranges::invoke(&A::g, a, 2) == 4);
  111. }
  112. {
  113. A a;
  114. const auto& ca = a;
  115. CHECK(ranges::invoke(&A::f, &a) == 42);
  116. // CHECK(noexcept(ranges::invoke(&A::f, &a) == 42));
  117. CHECK(ranges::invoke(&A::f, &ca) == 42);
  118. // CHECK(noexcept(ranges::invoke(&A::f, &ca) == 42));
  119. CHECK(ranges::invoke(&A::g, &a, 2) == 4);
  120. }
  121. {
  122. std::unique_ptr<A> up(new A);
  123. CHECK(ranges::invoke(&A::f, up) == 42);
  124. CHECK(ranges::invoke(&A::g, up, 2) == 4);
  125. }
  126. {
  127. auto sp = std::make_shared<A>();
  128. CHECK(ranges::invoke(&A::f, sp) == 42);
  129. // CHECK(noexcept(ranges::invoke(&A::f, sp) == 42));
  130. CHECK(ranges::invoke(&A::g, sp, 2) == 4);
  131. }
  132. CHECK(ranges::invoke(&A::i, A{}) == 13);
  133. // CHECK(noexcept(ranges::invoke(&A::i, A{}) == 13));
  134. { int&& tmp = ranges::invoke(&A::i, A{}); (void)tmp; }
  135. {
  136. A a;
  137. const auto& ca = a;
  138. CHECK(ranges::invoke(&A::i, a) == 13);
  139. // CHECK(noexcept(ranges::invoke(&A::i, a) == 13));
  140. CHECK(ranges::invoke(&A::i, ca) == 13);
  141. // CHECK(noexcept(ranges::invoke(&A::i, ca) == 13));
  142. CHECK(ranges::invoke(&A::i, &a) == 13);
  143. // CHECK(noexcept(ranges::invoke(&A::i, &a) == 13));
  144. CHECK(ranges::invoke(&A::i, &ca) == 13);
  145. // CHECK(noexcept(ranges::invoke(&A::i, &ca) == 13));
  146. ranges::invoke(&A::i, a) = 0;
  147. CHECK(a.i == 0);
  148. ranges::invoke(&A::i, &a) = 1;
  149. CHECK(a.i == 1);
  150. CPP_assert(ranges::same_as<decltype(ranges::invoke(&A::i, ca)), const int&>);
  151. CPP_assert(ranges::same_as<decltype(ranges::invoke(&A::i, &ca)), const int&>);
  152. }
  153. {
  154. std::unique_ptr<A> up(new A);
  155. CHECK(ranges::invoke(&A::i, up) == 13);
  156. ranges::invoke(&A::i, up) = 0;
  157. CHECK(up->i == 0);
  158. }
  159. {
  160. auto sp = std::make_shared<A>();
  161. CHECK(ranges::invoke(&A::i, sp) == 13);
  162. ranges::invoke(&A::i, sp) = 0;
  163. CHECK(sp->i == 0);
  164. }
  165. // {
  166. // struct B { int i = 42; constexpr int f() const { return i; } };
  167. // constexpr B b;
  168. // static_assert(b.i == 42, "");
  169. // static_assert(b.f() == 42, "");
  170. // static_assert(ranges::invoke_detail::impl(&B::i, b) == 42, "");
  171. // static_assert(ranges::invoke_detail::impl(&B::i, &b) == 42, "");
  172. // static_assert(ranges::invoke_detail::impl(&B::i, B{}) == 42, "");
  173. // static_assert(ranges::invoke_detail::impl(&B::f, b) == 42, "");
  174. // static_assert(ranges::invoke_detail::impl(&B::f, &b) == 42, "");
  175. // static_assert(ranges::invoke_detail::impl(&B::f, B{}) == 42, "");
  176. // }
  177. }
  178. } // unnamed namespace
  179. int main()
  180. {
  181. {
  182. // Check that not_fn works with callables
  183. Integer some_ints[] = {{0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}};
  184. ::check_equal(some_ints | ranges::views::filter(ranges::not_fn(&Integer::odd)),
  185. {0,2,4,6});
  186. }
  187. // Check that not_fn forwards value category
  188. {
  189. constexpr auto k = kind::lvalue;
  190. using F = fn<k>;
  191. auto f = ranges::not_fn(F{});
  192. CHECK(f() == true);
  193. CHECK(last_call == k);
  194. }
  195. {
  196. constexpr auto k = kind::const_lvalue;
  197. using F = fn<k>;
  198. auto const f = ranges::not_fn(F{});
  199. CHECK(f() == true);
  200. CHECK(last_call == k);
  201. }
  202. {
  203. constexpr auto k = kind::rvalue;
  204. using F = fn<k>;
  205. auto f = ranges::not_fn(F{});
  206. CHECK(std::move(f)() == true); // xvalue
  207. CHECK(last_call == k);
  208. CHECK(decltype(f){}() == true); // prvalue
  209. CHECK(last_call == k);
  210. }
  211. #ifdef _WIN32
  212. {
  213. // Ensure that invocable accepts pointers to functions with non-default calling conventions.
  214. CPP_assert(ranges::invocable<void(__cdecl*)()>);
  215. CPP_assert(ranges::invocable<void(__stdcall*)()>);
  216. CPP_assert(ranges::invocable<void(__fastcall*)()>);
  217. CPP_assert(ranges::invocable<void(__thiscall*)()>);
  218. #ifndef __MINGW32__
  219. CPP_assert(ranges::invocable<void(__vectorcall*)()>);
  220. #endif
  221. }
  222. #endif // _WIN32
  223. test_invoke();
  224. return ::test_result();
  225. }