lib.hpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537
  1. // MPark.Variant
  2. //
  3. // Copyright Michael Park, 2015-2017
  4. //
  5. // Distributed under the Boost Software License, Version 1.0.
  6. // (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
  7. #ifndef MPARK_LIB_HPP
  8. #define MPARK_LIB_HPP
  9. #include <memory>
  10. #include <functional>
  11. #include <type_traits>
  12. #include <utility>
  13. #include "config.hpp"
  14. #define MPARK_RETURN(...) \
  15. noexcept(noexcept(__VA_ARGS__)) -> decltype(__VA_ARGS__) { return __VA_ARGS__; }
  16. namespace mpark {
  17. namespace lib {
  18. template <typename T>
  19. struct identity { using type = T; };
  20. inline namespace cpp14 {
  21. template <typename T, std::size_t N>
  22. struct array {
  23. constexpr const T &operator[](std::size_t index) const {
  24. return data[index];
  25. }
  26. T data[N == 0 ? 1 : N];
  27. };
  28. template <typename T>
  29. using add_pointer_t = typename std::add_pointer<T>::type;
  30. template <typename... Ts>
  31. using common_type_t = typename std::common_type<Ts...>::type;
  32. template <typename T>
  33. using decay_t = typename std::decay<T>::type;
  34. template <bool B, typename T = void>
  35. using enable_if_t = typename std::enable_if<B, T>::type;
  36. template <typename T>
  37. using remove_const_t = typename std::remove_const<T>::type;
  38. template <typename T>
  39. using remove_reference_t = typename std::remove_reference<T>::type;
  40. template <typename T>
  41. inline constexpr T &&forward(remove_reference_t<T> &t) noexcept {
  42. return static_cast<T &&>(t);
  43. }
  44. template <typename T>
  45. inline constexpr T &&forward(remove_reference_t<T> &&t) noexcept {
  46. static_assert(!std::is_lvalue_reference<T>::value,
  47. "can not forward an rvalue as an lvalue");
  48. return static_cast<T &&>(t);
  49. }
  50. template <typename T>
  51. inline constexpr remove_reference_t<T> &&move(T &&t) noexcept {
  52. return static_cast<remove_reference_t<T> &&>(t);
  53. }
  54. #ifdef MPARK_INTEGER_SEQUENCE
  55. using std::integer_sequence;
  56. using std::index_sequence;
  57. using std::make_index_sequence;
  58. using std::index_sequence_for;
  59. #else
  60. template <typename T, T... Is>
  61. struct integer_sequence {
  62. using value_type = T;
  63. static constexpr std::size_t size() noexcept { return sizeof...(Is); }
  64. };
  65. template <std::size_t... Is>
  66. using index_sequence = integer_sequence<std::size_t, Is...>;
  67. template <typename Lhs, typename Rhs>
  68. struct make_index_sequence_concat;
  69. template <std::size_t... Lhs, std::size_t... Rhs>
  70. struct make_index_sequence_concat<index_sequence<Lhs...>,
  71. index_sequence<Rhs...>>
  72. : identity<index_sequence<Lhs..., (sizeof...(Lhs) + Rhs)...>> {};
  73. template <std::size_t N>
  74. struct make_index_sequence_impl;
  75. template <std::size_t N>
  76. using make_index_sequence = typename make_index_sequence_impl<N>::type;
  77. template <std::size_t N>
  78. struct make_index_sequence_impl
  79. : make_index_sequence_concat<make_index_sequence<N / 2>,
  80. make_index_sequence<N - (N / 2)>> {};
  81. template <>
  82. struct make_index_sequence_impl<0> : identity<index_sequence<>> {};
  83. template <>
  84. struct make_index_sequence_impl<1> : identity<index_sequence<0>> {};
  85. template <typename... Ts>
  86. using index_sequence_for = make_index_sequence<sizeof...(Ts)>;
  87. #endif
  88. // <functional>
  89. #ifdef MPARK_TRANSPARENT_OPERATORS
  90. using equal_to = std::equal_to<>;
  91. #else
  92. struct equal_to {
  93. template <typename Lhs, typename Rhs>
  94. inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const
  95. MPARK_RETURN(lib::forward<Lhs>(lhs) == lib::forward<Rhs>(rhs))
  96. };
  97. #endif
  98. #ifdef MPARK_TRANSPARENT_OPERATORS
  99. using not_equal_to = std::not_equal_to<>;
  100. #else
  101. struct not_equal_to {
  102. template <typename Lhs, typename Rhs>
  103. inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const
  104. MPARK_RETURN(lib::forward<Lhs>(lhs) != lib::forward<Rhs>(rhs))
  105. };
  106. #endif
  107. #ifdef MPARK_TRANSPARENT_OPERATORS
  108. using less = std::less<>;
  109. #else
  110. struct less {
  111. template <typename Lhs, typename Rhs>
  112. inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const
  113. MPARK_RETURN(lib::forward<Lhs>(lhs) < lib::forward<Rhs>(rhs))
  114. };
  115. #endif
  116. #ifdef MPARK_TRANSPARENT_OPERATORS
  117. using greater = std::greater<>;
  118. #else
  119. struct greater {
  120. template <typename Lhs, typename Rhs>
  121. inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const
  122. MPARK_RETURN(lib::forward<Lhs>(lhs) > lib::forward<Rhs>(rhs))
  123. };
  124. #endif
  125. #ifdef MPARK_TRANSPARENT_OPERATORS
  126. using less_equal = std::less_equal<>;
  127. #else
  128. struct less_equal {
  129. template <typename Lhs, typename Rhs>
  130. inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const
  131. MPARK_RETURN(lib::forward<Lhs>(lhs) <= lib::forward<Rhs>(rhs))
  132. };
  133. #endif
  134. #ifdef MPARK_TRANSPARENT_OPERATORS
  135. using greater_equal = std::greater_equal<>;
  136. #else
  137. struct greater_equal {
  138. template <typename Lhs, typename Rhs>
  139. inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const
  140. MPARK_RETURN(lib::forward<Lhs>(lhs) >= lib::forward<Rhs>(rhs))
  141. };
  142. #endif
  143. } // namespace cpp14
  144. inline namespace cpp17 {
  145. // <type_traits>
  146. template <bool B>
  147. using bool_constant = std::integral_constant<bool, B>;
  148. template <typename...>
  149. struct voider : identity<void> {};
  150. template <typename... Ts>
  151. using void_t = typename voider<Ts...>::type;
  152. namespace detail {
  153. namespace swappable {
  154. using std::swap;
  155. template <typename T>
  156. struct is_swappable {
  157. private:
  158. template <typename U,
  159. typename = decltype(swap(std::declval<U &>(),
  160. std::declval<U &>()))>
  161. inline static std::true_type test(int);
  162. template <typename U>
  163. inline static std::false_type test(...);
  164. public:
  165. static constexpr bool value = decltype(test<T>(0))::value;
  166. };
  167. template <bool IsSwappable, typename T>
  168. struct is_nothrow_swappable {
  169. static constexpr bool value =
  170. noexcept(swap(std::declval<T &>(), std::declval<T &>()));
  171. };
  172. template <typename T>
  173. struct is_nothrow_swappable<false, T> : std::false_type {};
  174. } // namespace swappable
  175. } // namespace detail
  176. using detail::swappable::is_swappable;
  177. template <typename T>
  178. using is_nothrow_swappable =
  179. detail::swappable::is_nothrow_swappable<is_swappable<T>::value, T>;
  180. // <functional>
  181. namespace detail {
  182. template <typename T>
  183. struct is_reference_wrapper : std::false_type {};
  184. template <typename T>
  185. struct is_reference_wrapper<std::reference_wrapper<T>>
  186. : std::true_type {};
  187. template <bool, int>
  188. struct Invoke;
  189. template <>
  190. struct Invoke<true /* pmf */, 0 /* is_base_of */> {
  191. template <typename R, typename T, typename Arg, typename... Args>
  192. inline static constexpr auto invoke(R T::*pmf, Arg &&arg, Args &&... args)
  193. MPARK_RETURN((lib::forward<Arg>(arg).*pmf)(lib::forward<Args>(args)...))
  194. };
  195. template <>
  196. struct Invoke<true /* pmf */, 1 /* is_reference_wrapper */> {
  197. template <typename R, typename T, typename Arg, typename... Args>
  198. inline static constexpr auto invoke(R T::*pmf, Arg &&arg, Args &&... args)
  199. MPARK_RETURN((lib::forward<Arg>(arg).get().*pmf)(lib::forward<Args>(args)...))
  200. };
  201. template <>
  202. struct Invoke<true /* pmf */, 2 /* otherwise */> {
  203. template <typename R, typename T, typename Arg, typename... Args>
  204. inline static constexpr auto invoke(R T::*pmf, Arg &&arg, Args &&... args)
  205. MPARK_RETURN(((*lib::forward<Arg>(arg)).*pmf)(lib::forward<Args>(args)...))
  206. };
  207. template <>
  208. struct Invoke<false /* pmo */, 0 /* is_base_of */> {
  209. template <typename R, typename T, typename Arg>
  210. inline static constexpr auto invoke(R T::*pmo, Arg &&arg)
  211. MPARK_RETURN(lib::forward<Arg>(arg).*pmo)
  212. };
  213. template <>
  214. struct Invoke<false /* pmo */, 1 /* is_reference_wrapper */> {
  215. template <typename R, typename T, typename Arg>
  216. inline static constexpr auto invoke(R T::*pmo, Arg &&arg)
  217. MPARK_RETURN(lib::forward<Arg>(arg).get().*pmo)
  218. };
  219. template <>
  220. struct Invoke<false /* pmo */, 2 /* otherwise */> {
  221. template <typename R, typename T, typename Arg>
  222. inline static constexpr auto invoke(R T::*pmo, Arg &&arg)
  223. MPARK_RETURN((*lib::forward<Arg>(arg)).*pmo)
  224. };
  225. template <typename R, typename T, typename Arg, typename... Args>
  226. inline constexpr auto invoke(R T::*f, Arg &&arg, Args &&... args)
  227. MPARK_RETURN(
  228. Invoke<std::is_function<R>::value,
  229. (std::is_base_of<T, lib::decay_t<Arg>>::value
  230. ? 0
  231. : is_reference_wrapper<lib::decay_t<Arg>>::value
  232. ? 1
  233. : 2)>::invoke(f,
  234. lib::forward<Arg>(arg),
  235. lib::forward<Args>(args)...))
  236. #ifdef _MSC_VER
  237. #pragma warning(push)
  238. #pragma warning(disable : 4100)
  239. #endif
  240. template <typename F, typename... Args>
  241. inline constexpr auto invoke(F &&f, Args &&... args)
  242. MPARK_RETURN(lib::forward<F>(f)(lib::forward<Args>(args)...))
  243. #ifdef _MSC_VER
  244. #pragma warning(pop)
  245. #endif
  246. } // namespace detail
  247. template <typename F, typename... Args>
  248. inline constexpr auto invoke(F &&f, Args &&... args)
  249. MPARK_RETURN(detail::invoke(lib::forward<F>(f),
  250. lib::forward<Args>(args)...))
  251. namespace detail {
  252. template <typename Void, typename, typename...>
  253. struct invoke_result {};
  254. template <typename F, typename... Args>
  255. struct invoke_result<void_t<decltype(lib::invoke(
  256. std::declval<F>(), std::declval<Args>()...))>,
  257. F,
  258. Args...>
  259. : identity<decltype(
  260. lib::invoke(std::declval<F>(), std::declval<Args>()...))> {};
  261. } // namespace detail
  262. template <typename F, typename... Args>
  263. using invoke_result = detail::invoke_result<void, F, Args...>;
  264. template <typename F, typename... Args>
  265. using invoke_result_t = typename invoke_result<F, Args...>::type;
  266. namespace detail {
  267. template <typename Void, typename, typename...>
  268. struct is_invocable : std::false_type {};
  269. template <typename F, typename... Args>
  270. struct is_invocable<void_t<invoke_result_t<F, Args...>>, F, Args...>
  271. : std::true_type {};
  272. template <typename Void, typename, typename, typename...>
  273. struct is_invocable_r : std::false_type {};
  274. template <typename R, typename F, typename... Args>
  275. struct is_invocable_r<void_t<invoke_result_t<F, Args...>>,
  276. R,
  277. F,
  278. Args...>
  279. : std::is_convertible<invoke_result_t<F, Args...>, R> {};
  280. } // namespace detail
  281. template <typename F, typename... Args>
  282. using is_invocable = detail::is_invocable<void, F, Args...>;
  283. template <typename R, typename F, typename... Args>
  284. using is_invocable_r = detail::is_invocable_r<void, R, F, Args...>;
  285. namespace detail {
  286. template <bool Invocable, typename F, typename... Args>
  287. struct is_nothrow_invocable {
  288. static constexpr bool value =
  289. noexcept(lib::invoke(std::declval<F>(), std::declval<Args>()...));
  290. };
  291. template <typename F, typename... Args>
  292. struct is_nothrow_invocable<false, F, Args...> : std::false_type {};
  293. template <bool Invocable, typename R, typename F, typename... Args>
  294. struct is_nothrow_invocable_r {
  295. private:
  296. inline static R impl() {
  297. return lib::invoke(std::declval<F>(), std::declval<Args>()...);
  298. }
  299. public:
  300. static constexpr bool value = noexcept(impl());
  301. };
  302. template <typename R, typename F, typename... Args>
  303. struct is_nothrow_invocable_r<false, R, F, Args...> : std::false_type {};
  304. } // namespace detail
  305. template <typename F, typename... Args>
  306. using is_nothrow_invocable = detail::
  307. is_nothrow_invocable<is_invocable<F, Args...>::value, F, Args...>;
  308. template <typename R, typename F, typename... Args>
  309. using is_nothrow_invocable_r =
  310. detail::is_nothrow_invocable_r<is_invocable_r<R, F, Args...>::value,
  311. R,
  312. F,
  313. Args...>;
  314. // <memory>
  315. #ifdef MPARK_BUILTIN_ADDRESSOF
  316. template <typename T>
  317. inline constexpr T *addressof(T &arg) noexcept {
  318. return __builtin_addressof(arg);
  319. }
  320. #else
  321. namespace detail {
  322. namespace has_addressof_impl {
  323. struct fail;
  324. template <typename T>
  325. inline fail operator&(T &&);
  326. template <typename T>
  327. inline static constexpr bool impl() {
  328. return (std::is_class<T>::value || std::is_union<T>::value) &&
  329. !std::is_same<decltype(&std::declval<T &>()), fail>::value;
  330. }
  331. } // namespace has_addressof_impl
  332. template <typename T>
  333. using has_addressof = bool_constant<has_addressof_impl::impl<T>()>;
  334. template <typename T>
  335. inline constexpr T *addressof(T &arg, std::true_type) noexcept {
  336. return std::addressof(arg);
  337. }
  338. template <typename T>
  339. inline constexpr T *addressof(T &arg, std::false_type) noexcept {
  340. return &arg;
  341. }
  342. } // namespace detail
  343. template <typename T>
  344. inline constexpr T *addressof(T &arg) noexcept {
  345. return detail::addressof(arg, detail::has_addressof<T>{});
  346. }
  347. #endif
  348. template <typename T>
  349. inline constexpr T *addressof(const T &&) = delete;
  350. } // namespace cpp17
  351. template <typename T>
  352. struct remove_all_extents : identity<T> {};
  353. template <typename T, std::size_t N>
  354. struct remove_all_extents<array<T, N>> : remove_all_extents<T> {};
  355. template <typename T>
  356. using remove_all_extents_t = typename remove_all_extents<T>::type;
  357. template <std::size_t N>
  358. using size_constant = std::integral_constant<std::size_t, N>;
  359. template <std::size_t I, typename T>
  360. struct indexed_type : size_constant<I> { using type = T; };
  361. template <bool... Bs>
  362. using all = std::is_same<integer_sequence<bool, true, Bs...>,
  363. integer_sequence<bool, Bs..., true>>;
  364. #ifdef MPARK_TYPE_PACK_ELEMENT
  365. template <std::size_t I, typename... Ts>
  366. using type_pack_element_t = __type_pack_element<I, Ts...>;
  367. #else
  368. template <std::size_t I, typename... Ts>
  369. struct type_pack_element_impl {
  370. private:
  371. template <typename>
  372. struct set;
  373. template <std::size_t... Is>
  374. struct set<index_sequence<Is...>> : indexed_type<Is, Ts>... {};
  375. template <typename T>
  376. inline static std::enable_if<true, T> impl(indexed_type<I, T>);
  377. inline static std::enable_if<false> impl(...);
  378. public:
  379. using type = decltype(impl(set<index_sequence_for<Ts...>>{}));
  380. };
  381. template <std::size_t I, typename... Ts>
  382. using type_pack_element = typename type_pack_element_impl<I, Ts...>::type;
  383. template <std::size_t I, typename... Ts>
  384. using type_pack_element_t = typename type_pack_element<I, Ts...>::type;
  385. #endif
  386. #ifdef MPARK_TRIVIALITY_TYPE_TRAITS
  387. using std::is_trivially_copy_constructible;
  388. using std::is_trivially_move_constructible;
  389. using std::is_trivially_copy_assignable;
  390. using std::is_trivially_move_assignable;
  391. #else
  392. template <typename T>
  393. struct is_trivially_copy_constructible
  394. : bool_constant<
  395. std::is_copy_constructible<T>::value && __has_trivial_copy(T)> {};
  396. template <typename T>
  397. struct is_trivially_move_constructible : bool_constant<__is_trivial(T)> {};
  398. template <typename T>
  399. struct is_trivially_copy_assignable
  400. : bool_constant<
  401. std::is_copy_assignable<T>::value && __has_trivial_assign(T)> {};
  402. template <typename T>
  403. struct is_trivially_move_assignable : bool_constant<__is_trivial(T)> {};
  404. #endif
  405. template <typename T, bool>
  406. struct dependent_type : T {};
  407. template <typename Is, std::size_t J>
  408. struct push_back;
  409. template <typename Is, std::size_t J>
  410. using push_back_t = typename push_back<Is, J>::type;
  411. template <std::size_t... Is, std::size_t J>
  412. struct push_back<index_sequence<Is...>, J> {
  413. using type = index_sequence<Is..., J>;
  414. };
  415. } // namespace lib
  416. } // namespace mpark
  417. #undef MPARK_RETURN
  418. #endif // MPARK_LIB_HPP