Traits.h 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764
  1. /*
  2. * Copyright 2011-present Facebook, Inc.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. // @author: Andrei Alexandrescu
  17. #pragma once
  18. #include <functional>
  19. #include <limits>
  20. #include <memory>
  21. #include <type_traits>
  22. #include <folly/Portability.h>
  23. // libc++ doesn't provide this header, nor does msvc
  24. #if __has_include(<bits/c++config.h>)
  25. // This file appears in two locations: inside fbcode and in the
  26. // libstdc++ source code (when embedding fbstring as std::string).
  27. // To aid in this schizophrenic use, two macros are defined in
  28. // c++config.h:
  29. // _LIBSTDCXX_FBSTRING - Set inside libstdc++. This is useful to
  30. // gate use inside fbcode v. libstdc++
  31. #include <bits/c++config.h>
  32. #endif
  33. #define FOLLY_CREATE_HAS_MEMBER_TYPE_TRAITS(classname, type_name) \
  34. template <typename TTheClass_> \
  35. struct classname##__folly_traits_impl__ { \
  36. template <typename UTheClass_> \
  37. static constexpr bool test(typename UTheClass_::type_name*) { \
  38. return true; \
  39. } \
  40. template <typename> \
  41. static constexpr bool test(...) { \
  42. return false; \
  43. } \
  44. }; \
  45. template <typename TTheClass_> \
  46. using classname = typename std::conditional< \
  47. classname##__folly_traits_impl__<TTheClass_>::template test<TTheClass_>( \
  48. nullptr), \
  49. std::true_type, \
  50. std::false_type>::type
  51. #define FOLLY_CREATE_HAS_MEMBER_FN_TRAITS_IMPL(classname, func_name, cv_qual) \
  52. template <typename TTheClass_, typename RTheReturn_, typename... TTheArgs_> \
  53. struct classname##__folly_traits_impl__< \
  54. TTheClass_, \
  55. RTheReturn_(TTheArgs_...) cv_qual> { \
  56. template < \
  57. typename UTheClass_, \
  58. RTheReturn_ (UTheClass_::*)(TTheArgs_...) cv_qual> \
  59. struct sfinae {}; \
  60. template <typename UTheClass_> \
  61. static std::true_type test(sfinae<UTheClass_, &UTheClass_::func_name>*); \
  62. template <typename> \
  63. static std::false_type test(...); \
  64. }
  65. /*
  66. * The FOLLY_CREATE_HAS_MEMBER_FN_TRAITS is used to create traits
  67. * classes that check for the existence of a member function with
  68. * a given name and signature. It currently does not support
  69. * checking for inherited members.
  70. *
  71. * Such classes receive two template parameters: the class to be checked
  72. * and the signature of the member function. A static boolean field
  73. * named `value` (which is also constexpr) tells whether such member
  74. * function exists.
  75. *
  76. * Each traits class created is bound only to the member name, not to
  77. * its signature nor to the type of the class containing it.
  78. *
  79. * Say you need to know if a given class has a member function named
  80. * `test` with the following signature:
  81. *
  82. * int test() const;
  83. *
  84. * You'd need this macro to create a traits class to check for a member
  85. * named `test`, and then use this traits class to check for the signature:
  86. *
  87. * namespace {
  88. *
  89. * FOLLY_CREATE_HAS_MEMBER_FN_TRAITS(has_test_traits, test);
  90. *
  91. * } // unnamed-namespace
  92. *
  93. * void some_func() {
  94. * cout << "Does class Foo have a member int test() const? "
  95. * << boolalpha << has_test_traits<Foo, int() const>::value;
  96. * }
  97. *
  98. * You can use the same traits class to test for a completely different
  99. * signature, on a completely different class, as long as the member name
  100. * is the same:
  101. *
  102. * void some_func() {
  103. * cout << "Does class Foo have a member int test()? "
  104. * << boolalpha << has_test_traits<Foo, int()>::value;
  105. * cout << "Does class Foo have a member int test() const? "
  106. * << boolalpha << has_test_traits<Foo, int() const>::value;
  107. * cout << "Does class Bar have a member double test(const string&, long)? "
  108. * << boolalpha << has_test_traits<Bar, double(const string&, long)>::value;
  109. * }
  110. *
  111. * @author: Marcelo Juchem <marcelo@fb.com>
  112. */
  113. #define FOLLY_CREATE_HAS_MEMBER_FN_TRAITS(classname, func_name) \
  114. template <typename, typename> \
  115. struct classname##__folly_traits_impl__; \
  116. FOLLY_CREATE_HAS_MEMBER_FN_TRAITS_IMPL(classname, func_name, ); \
  117. FOLLY_CREATE_HAS_MEMBER_FN_TRAITS_IMPL(classname, func_name, const); \
  118. FOLLY_CREATE_HAS_MEMBER_FN_TRAITS_IMPL( \
  119. classname, func_name, /* nolint */ volatile); \
  120. FOLLY_CREATE_HAS_MEMBER_FN_TRAITS_IMPL( \
  121. classname, func_name, /* nolint */ volatile const); \
  122. template <typename TTheClass_, typename TTheSignature_> \
  123. using classname = \
  124. decltype(classname##__folly_traits_impl__<TTheClass_, TTheSignature_>:: \
  125. template test<TTheClass_>(nullptr))
  126. namespace folly {
  127. #if __cpp_lib_bool_constant || _MSC_VER
  128. using std::bool_constant;
  129. #else
  130. // mimic: std::bool_constant, C++17
  131. template <bool B>
  132. using bool_constant = std::integral_constant<bool, B>;
  133. #endif
  134. template <std::size_t I>
  135. using index_constant = std::integral_constant<std::size_t, I>;
  136. /***
  137. * _t
  138. *
  139. * Instead of:
  140. *
  141. * using decayed = typename std::decay<T>::type;
  142. *
  143. * With the C++14 standard trait aliases, we could use:
  144. *
  145. * using decayed = std::decay_t<T>;
  146. *
  147. * Without them, we could use:
  148. *
  149. * using decayed = _t<std::decay<T>>;
  150. *
  151. * Also useful for any other library with template types having dependent
  152. * member types named `type`, like the standard trait types.
  153. */
  154. template <typename T>
  155. using _t = typename T::type;
  156. /**
  157. * A type trait to remove all const volatile and reference qualifiers on a
  158. * type T
  159. */
  160. template <typename T>
  161. struct remove_cvref {
  162. using type =
  163. typename std::remove_cv<typename std::remove_reference<T>::type>::type;
  164. };
  165. template <typename T>
  166. using remove_cvref_t = typename remove_cvref<T>::type;
  167. namespace detail {
  168. template <typename Src>
  169. struct like_ {
  170. template <typename Dst>
  171. using apply = Dst;
  172. };
  173. template <typename Src>
  174. struct like_<Src const> {
  175. template <typename Dst>
  176. using apply = Dst const;
  177. };
  178. template <typename Src>
  179. struct like_<Src volatile> {
  180. template <typename Dst>
  181. using apply = Dst volatile;
  182. };
  183. template <typename Src>
  184. struct like_<Src const volatile> {
  185. template <typename Dst>
  186. using apply = Dst const volatile;
  187. };
  188. template <typename Src>
  189. struct like_<Src&> {
  190. template <typename Dst>
  191. using apply = typename like_<Src>::template apply<Dst>&;
  192. };
  193. template <typename Src>
  194. struct like_<Src&&> {
  195. template <typename Dst>
  196. using apply = typename like_<Src>::template apply<Dst>&&;
  197. };
  198. } // namespace detail
  199. // mimic: like_t, p0847r0
  200. template <typename Src, typename Dst>
  201. using like_t = typename detail::like_<Src>::template apply<remove_cvref_t<Dst>>;
  202. // mimic: like, p0847r0
  203. template <typename Src, typename Dst>
  204. struct like {
  205. using type = like_t<Src, Dst>;
  206. };
  207. /**
  208. * type_t
  209. *
  210. * A type alias for the first template type argument. `type_t` is useful for
  211. * controlling class-template and function-template partial specialization.
  212. *
  213. * Example:
  214. *
  215. * template <typename Value>
  216. * class Container {
  217. * public:
  218. * template <typename... Args>
  219. * Container(
  220. * type_t<in_place_t, decltype(Value(std::declval<Args>()...))>,
  221. * Args&&...);
  222. * };
  223. *
  224. * void_t
  225. *
  226. * A type alias for `void`. `void_t` is useful for controling class-template
  227. * and function-template partial specialization.
  228. *
  229. * Example:
  230. *
  231. * // has_value_type<T>::value is true if T has a nested type `value_type`
  232. * template <class T, class = void>
  233. * struct has_value_type
  234. * : std::false_type {};
  235. *
  236. * template <class T>
  237. * struct has_value_type<T, folly::void_t<typename T::value_type>>
  238. * : std::true_type {};
  239. */
  240. /**
  241. * There is a bug in libstdc++, libc++, and MSVC's STL that causes it to
  242. * ignore unused template parameter arguments in template aliases and does not
  243. * cause substitution failures. This defect has been recorded here:
  244. * http://open-std.org/JTC1/SC22/WG21/docs/cwg_defects.html#1558.
  245. *
  246. * This causes the implementation of std::void_t to be buggy, as it is likely
  247. * defined as something like the following:
  248. *
  249. * template <typename...>
  250. * using void_t = void;
  251. *
  252. * This causes the compiler to ignore all the template arguments and does not
  253. * help when one wants to cause substitution failures. Rather declarations
  254. * which have void_t in orthogonal specializations are treated as the same.
  255. * For example, assuming the possible `T` types are only allowed to have
  256. * either the alias `one` or `two` and never both or none:
  257. *
  258. * template <typename T,
  259. * typename std::void_t<std::decay_t<T>::one>* = nullptr>
  260. * void foo(T&&) {}
  261. * template <typename T,
  262. * typename std::void_t<std::decay_t<T>::two>* = nullptr>
  263. * void foo(T&&) {}
  264. *
  265. * The second foo() will be a redefinition because it conflicts with the first
  266. * one; void_t does not cause substitution failures - the template types are
  267. * just ignored.
  268. */
  269. namespace traits_detail {
  270. template <class T, class...>
  271. struct type_t_ {
  272. using type = T;
  273. };
  274. } // namespace traits_detail
  275. template <class T, class... Ts>
  276. using type_t = typename traits_detail::type_t_<T, Ts...>::type;
  277. template <class... Ts>
  278. using void_t = type_t<void, Ts...>;
  279. // Older versions of libstdc++ do not provide std::is_trivially_copyable
  280. #if defined(__clang__) && !defined(_LIBCPP_VERSION)
  281. template <class T>
  282. struct is_trivially_copyable : bool_constant<__is_trivially_copyable(T)> {};
  283. #elif defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 5
  284. template <class T>
  285. struct is_trivially_copyable : std::is_trivial<T> {};
  286. #else
  287. template <class T>
  288. using is_trivially_copyable = std::is_trivially_copyable<T>;
  289. #endif
  290. /**
  291. * IsRelocatable<T>::value describes the ability of moving around
  292. * memory a value of type T by using memcpy (as opposed to the
  293. * conservative approach of calling the copy constructor and then
  294. * destroying the old temporary. Essentially for a relocatable type,
  295. * the following two sequences of code should be semantically
  296. * equivalent:
  297. *
  298. * void move1(T * from, T * to) {
  299. * new(to) T(from);
  300. * (*from).~T();
  301. * }
  302. *
  303. * void move2(T * from, T * to) {
  304. * memcpy(to, from, sizeof(T));
  305. * }
  306. *
  307. * Most C++ types are relocatable; the ones that aren't would include
  308. * internal pointers or (very rarely) would need to update remote
  309. * pointers to pointers tracking them. All C++ primitive types and
  310. * type constructors are relocatable.
  311. *
  312. * This property can be used in a variety of optimizations. Currently
  313. * fbvector uses this property intensively.
  314. *
  315. * The default conservatively assumes the type is not
  316. * relocatable. Several specializations are defined for known
  317. * types. You may want to add your own specializations. Do so in
  318. * namespace folly and make sure you keep the specialization of
  319. * IsRelocatable<SomeStruct> in the same header as SomeStruct.
  320. *
  321. * You may also declare a type to be relocatable by including
  322. * `typedef std::true_type IsRelocatable;`
  323. * in the class header.
  324. *
  325. * It may be unset in a base class by overriding the typedef to false_type.
  326. */
  327. /*
  328. * IsZeroInitializable describes the property that default construction is the
  329. * same as memset(dst, 0, sizeof(T)).
  330. */
  331. namespace traits_detail {
  332. #define FOLLY_HAS_TRUE_XXX(name) \
  333. FOLLY_CREATE_HAS_MEMBER_TYPE_TRAITS(has_##name, name); \
  334. template <class T> \
  335. struct name##_is_true : std::is_same<typename T::name, std::true_type> {}; \
  336. template <class T> \
  337. struct has_true_##name : std::conditional< \
  338. has_##name<T>::value, \
  339. name##_is_true<T>, \
  340. std::false_type>::type {}
  341. FOLLY_HAS_TRUE_XXX(IsRelocatable);
  342. FOLLY_HAS_TRUE_XXX(IsZeroInitializable);
  343. #undef FOLLY_HAS_TRUE_XXX
  344. } // namespace traits_detail
  345. struct Ignore {
  346. Ignore() = default;
  347. template <class T>
  348. constexpr /* implicit */ Ignore(const T&) {}
  349. template <class T>
  350. const Ignore& operator=(T const&) const {
  351. return *this;
  352. }
  353. };
  354. template <class...>
  355. using Ignored = Ignore;
  356. namespace traits_detail_IsEqualityComparable {
  357. Ignore operator==(Ignore, Ignore);
  358. template <class T, class U = T>
  359. struct IsEqualityComparable
  360. : std::is_convertible<
  361. decltype(std::declval<T>() == std::declval<U>()),
  362. bool> {};
  363. } // namespace traits_detail_IsEqualityComparable
  364. /* using override */ using traits_detail_IsEqualityComparable::
  365. IsEqualityComparable;
  366. namespace traits_detail_IsLessThanComparable {
  367. Ignore operator<(Ignore, Ignore);
  368. template <class T, class U = T>
  369. struct IsLessThanComparable
  370. : std::is_convertible<
  371. decltype(std::declval<T>() < std::declval<U>()),
  372. bool> {};
  373. } // namespace traits_detail_IsLessThanComparable
  374. /* using override */ using traits_detail_IsLessThanComparable::
  375. IsLessThanComparable;
  376. namespace traits_detail_IsNothrowSwappable {
  377. #if defined(__cpp_lib_is_swappable) || (_CPPLIB_VER && _HAS_CXX17)
  378. // MSVC 2015+ already implements the C++17 P0185R1 proposal which
  379. // adds std::is_nothrow_swappable, so use it instead if C++17 mode
  380. // is enabled.
  381. template <typename T>
  382. using IsNothrowSwappable = std::is_nothrow_swappable<T>;
  383. #elif _CPPLIB_VER
  384. // MSVC 2015+ defines the base even if C++17 is disabled, and
  385. // MSVC 2015 has issues with our fallback implementation due to
  386. // over-eager evaluation of noexcept.
  387. template <typename T>
  388. using IsNothrowSwappable = std::_Is_nothrow_swappable<T>;
  389. #else
  390. /* using override */ using std::swap;
  391. template <class T>
  392. struct IsNothrowSwappable
  393. : bool_constant<std::is_nothrow_move_constructible<T>::value&& noexcept(
  394. swap(std::declval<T&>(), std::declval<T&>()))> {};
  395. #endif
  396. } // namespace traits_detail_IsNothrowSwappable
  397. /* using override */ using traits_detail_IsNothrowSwappable::IsNothrowSwappable;
  398. template <class T>
  399. struct IsRelocatable : std::conditional<
  400. traits_detail::has_IsRelocatable<T>::value,
  401. traits_detail::has_true_IsRelocatable<T>,
  402. // TODO add this line (and some tests for it) when we
  403. // upgrade to gcc 4.7
  404. // std::is_trivially_move_constructible<T>::value ||
  405. is_trivially_copyable<T>>::type {};
  406. template <class T>
  407. struct IsZeroInitializable
  408. : std::conditional<
  409. traits_detail::has_IsZeroInitializable<T>::value,
  410. traits_detail::has_true_IsZeroInitializable<T>,
  411. bool_constant<!std::is_class<T>::value>>::type {};
  412. template <typename...>
  413. struct Conjunction : std::true_type {};
  414. template <typename T>
  415. struct Conjunction<T> : T {};
  416. template <typename T, typename... TList>
  417. struct Conjunction<T, TList...>
  418. : std::conditional<T::value, Conjunction<TList...>, T>::type {};
  419. template <typename...>
  420. struct Disjunction : std::false_type {};
  421. template <typename T>
  422. struct Disjunction<T> : T {};
  423. template <typename T, typename... TList>
  424. struct Disjunction<T, TList...>
  425. : std::conditional<T::value, T, Disjunction<TList...>>::type {};
  426. template <typename T>
  427. struct Negation : bool_constant<!T::value> {};
  428. template <bool... Bs>
  429. struct Bools {
  430. using valid_type = bool;
  431. static constexpr std::size_t size() {
  432. return sizeof...(Bs);
  433. }
  434. };
  435. // Lighter-weight than Conjunction, but evaluates all sub-conditions eagerly.
  436. template <class... Ts>
  437. struct StrictConjunction
  438. : std::is_same<Bools<Ts::value...>, Bools<(Ts::value || true)...>> {};
  439. template <class... Ts>
  440. struct StrictDisjunction
  441. : Negation<
  442. std::is_same<Bools<Ts::value...>, Bools<(Ts::value && false)...>>> {};
  443. } // namespace folly
  444. /**
  445. * Use this macro ONLY inside namespace folly. When using it with a
  446. * regular type, use it like this:
  447. *
  448. * // Make sure you're at namespace ::folly scope
  449. * template <> FOLLY_ASSUME_RELOCATABLE(MyType)
  450. *
  451. * When using it with a template type, use it like this:
  452. *
  453. * // Make sure you're at namespace ::folly scope
  454. * template <class T1, class T2>
  455. * FOLLY_ASSUME_RELOCATABLE(MyType<T1, T2>)
  456. */
  457. #define FOLLY_ASSUME_RELOCATABLE(...) \
  458. struct IsRelocatable<__VA_ARGS__> : std::true_type {}
  459. /**
  460. * The FOLLY_ASSUME_FBVECTOR_COMPATIBLE* macros below encode the
  461. * assumption that the type is relocatable per IsRelocatable
  462. * above. Many types can be assumed to satisfy this condition, but
  463. * it is the responsibility of the user to state that assumption.
  464. * User-defined classes will not be optimized for use with
  465. * fbvector (see FBVector.h) unless they state that assumption.
  466. *
  467. * Use FOLLY_ASSUME_FBVECTOR_COMPATIBLE with regular types like this:
  468. *
  469. * FOLLY_ASSUME_FBVECTOR_COMPATIBLE(MyType)
  470. *
  471. * The versions FOLLY_ASSUME_FBVECTOR_COMPATIBLE_1, _2, _3, and _4
  472. * allow using the macro for describing templatized classes with 1, 2,
  473. * 3, and 4 template parameters respectively. For template classes
  474. * just use the macro with the appropriate number and pass the name of
  475. * the template to it. Example:
  476. *
  477. * template <class T1, class T2> class MyType { ... };
  478. * ...
  479. * // Make sure you're at global scope
  480. * FOLLY_ASSUME_FBVECTOR_COMPATIBLE_2(MyType)
  481. */
  482. // Use this macro ONLY at global level (no namespace)
  483. #define FOLLY_ASSUME_FBVECTOR_COMPATIBLE(...) \
  484. namespace folly { \
  485. template <> \
  486. FOLLY_ASSUME_RELOCATABLE(__VA_ARGS__); \
  487. }
  488. // Use this macro ONLY at global level (no namespace)
  489. #define FOLLY_ASSUME_FBVECTOR_COMPATIBLE_1(...) \
  490. namespace folly { \
  491. template <class T1> \
  492. FOLLY_ASSUME_RELOCATABLE(__VA_ARGS__<T1>); \
  493. }
  494. // Use this macro ONLY at global level (no namespace)
  495. #define FOLLY_ASSUME_FBVECTOR_COMPATIBLE_2(...) \
  496. namespace folly { \
  497. template <class T1, class T2> \
  498. FOLLY_ASSUME_RELOCATABLE(__VA_ARGS__<T1, T2>); \
  499. }
  500. // Use this macro ONLY at global level (no namespace)
  501. #define FOLLY_ASSUME_FBVECTOR_COMPATIBLE_3(...) \
  502. namespace folly { \
  503. template <class T1, class T2, class T3> \
  504. FOLLY_ASSUME_RELOCATABLE(__VA_ARGS__<T1, T2, T3>); \
  505. }
  506. // Use this macro ONLY at global level (no namespace)
  507. #define FOLLY_ASSUME_FBVECTOR_COMPATIBLE_4(...) \
  508. namespace folly { \
  509. template <class T1, class T2, class T3, class T4> \
  510. FOLLY_ASSUME_RELOCATABLE(__VA_ARGS__<T1, T2, T3, T4>); \
  511. }
  512. /**
  513. * Instantiate FOLLY_ASSUME_FBVECTOR_COMPATIBLE for a few types. It is
  514. * safe to assume that pair is compatible if both of its components
  515. * are. Furthermore, all STL containers can be assumed to comply,
  516. * although that is not guaranteed by the standard.
  517. */
  518. FOLLY_NAMESPACE_STD_BEGIN
  519. template <class T, class U>
  520. struct pair;
  521. #ifndef _GLIBCXX_USE_FB
  522. FOLLY_GLIBCXX_NAMESPACE_CXX11_BEGIN
  523. template <class T, class R, class A>
  524. class basic_string;
  525. FOLLY_GLIBCXX_NAMESPACE_CXX11_END
  526. #else
  527. template <class T, class R, class A, class S>
  528. class basic_string;
  529. #endif
  530. template <class T, class A>
  531. class vector;
  532. template <class T, class A>
  533. class deque;
  534. template <class T, class C, class A>
  535. class set;
  536. template <class K, class V, class C, class A>
  537. class map;
  538. template <class T>
  539. class shared_ptr;
  540. FOLLY_NAMESPACE_STD_END
  541. namespace folly {
  542. // STL commonly-used types
  543. template <class T, class U>
  544. struct IsRelocatable<std::pair<T, U>>
  545. : bool_constant<IsRelocatable<T>::value && IsRelocatable<U>::value> {};
  546. // Is T one of T1, T2, ..., Tn?
  547. template <typename T, typename... Ts>
  548. using IsOneOf = StrictDisjunction<std::is_same<T, Ts>...>;
  549. /*
  550. * Complementary type traits for integral comparisons.
  551. *
  552. * For instance, `if(x < 0)` yields an error in clang for unsigned types
  553. * when -Werror is used due to -Wtautological-compare
  554. *
  555. *
  556. * @author: Marcelo Juchem <marcelo@fb.com>
  557. */
  558. namespace detail {
  559. template <typename T, bool>
  560. struct is_negative_impl {
  561. constexpr static bool check(T x) {
  562. return x < 0;
  563. }
  564. };
  565. template <typename T>
  566. struct is_negative_impl<T, false> {
  567. constexpr static bool check(T) {
  568. return false;
  569. }
  570. };
  571. // folly::to integral specializations can end up generating code
  572. // inside what are really static ifs (not executed because of the templated
  573. // types) that violate -Wsign-compare and/or -Wbool-compare so suppress them
  574. // in order to not prevent all calling code from using it.
  575. FOLLY_PUSH_WARNING
  576. FOLLY_GNU_DISABLE_WARNING("-Wsign-compare")
  577. #if __GNUC_PREREQ(5, 0)
  578. FOLLY_GNU_DISABLE_WARNING("-Wbool-compare")
  579. #endif
  580. FOLLY_MSVC_DISABLE_WARNING(4388) // sign-compare
  581. FOLLY_MSVC_DISABLE_WARNING(4804) // bool-compare
  582. template <typename RHS, RHS rhs, typename LHS>
  583. bool less_than_impl(LHS const lhs) {
  584. // clang-format off
  585. return
  586. rhs > std::numeric_limits<LHS>::max() ? true :
  587. rhs <= std::numeric_limits<LHS>::min() ? false :
  588. lhs < rhs;
  589. // clang-format on
  590. }
  591. template <typename RHS, RHS rhs, typename LHS>
  592. bool greater_than_impl(LHS const lhs) {
  593. // clang-format off
  594. return
  595. rhs > std::numeric_limits<LHS>::max() ? false :
  596. rhs < std::numeric_limits<LHS>::min() ? true :
  597. lhs > rhs;
  598. // clang-format on
  599. }
  600. FOLLY_POP_WARNING
  601. } // namespace detail
  602. // same as `x < 0`
  603. template <typename T>
  604. constexpr bool is_negative(T x) {
  605. return folly::detail::is_negative_impl<T, std::is_signed<T>::value>::check(x);
  606. }
  607. // same as `x <= 0`
  608. template <typename T>
  609. constexpr bool is_non_positive(T x) {
  610. return !x || folly::is_negative(x);
  611. }
  612. // same as `x > 0`
  613. template <typename T>
  614. constexpr bool is_positive(T x) {
  615. return !is_non_positive(x);
  616. }
  617. // same as `x >= 0`
  618. template <typename T>
  619. constexpr bool is_non_negative(T x) {
  620. return !x || is_positive(x);
  621. }
  622. template <typename RHS, RHS rhs, typename LHS>
  623. bool less_than(LHS const lhs) {
  624. return detail::
  625. less_than_impl<RHS, rhs, typename std::remove_reference<LHS>::type>(lhs);
  626. }
  627. template <typename RHS, RHS rhs, typename LHS>
  628. bool greater_than(LHS const lhs) {
  629. return detail::
  630. greater_than_impl<RHS, rhs, typename std::remove_reference<LHS>::type>(
  631. lhs);
  632. }
  633. } // namespace folly
  634. // Assume nothing when compiling with MSVC.
  635. #ifndef _MSC_VER
  636. // gcc-5.0 changed string's implementation in libstdc++ to be non-relocatable
  637. #if !_GLIBCXX_USE_CXX11_ABI
  638. FOLLY_ASSUME_FBVECTOR_COMPATIBLE_3(std::basic_string)
  639. #endif
  640. FOLLY_ASSUME_FBVECTOR_COMPATIBLE_2(std::vector)
  641. FOLLY_ASSUME_FBVECTOR_COMPATIBLE_2(std::deque)
  642. FOLLY_ASSUME_FBVECTOR_COMPATIBLE_2(std::unique_ptr)
  643. FOLLY_ASSUME_FBVECTOR_COMPATIBLE_1(std::shared_ptr)
  644. FOLLY_ASSUME_FBVECTOR_COMPATIBLE_1(std::function)
  645. #endif
  646. /* Some combinations of compilers and C++ libraries make __int128 and
  647. * unsigned __int128 available but do not correctly define their standard type
  648. * traits.
  649. *
  650. * If FOLLY_SUPPLY_MISSING_INT128_TRAITS is defined, we define these traits
  651. * here.
  652. *
  653. * @author: Phil Willoughby <philwill@fb.com>
  654. */
  655. #if FOLLY_SUPPLY_MISSING_INT128_TRAITS
  656. FOLLY_NAMESPACE_STD_BEGIN
  657. template <>
  658. struct is_arithmetic<__int128> : ::std::true_type {};
  659. template <>
  660. struct is_arithmetic<unsigned __int128> : ::std::true_type {};
  661. template <>
  662. struct is_integral<__int128> : ::std::true_type {};
  663. template <>
  664. struct is_integral<unsigned __int128> : ::std::true_type {};
  665. template <>
  666. struct make_unsigned<__int128> {
  667. typedef unsigned __int128 type;
  668. };
  669. template <>
  670. struct make_signed<__int128> {
  671. typedef __int128 type;
  672. };
  673. template <>
  674. struct make_unsigned<unsigned __int128> {
  675. typedef unsigned __int128 type;
  676. };
  677. template <>
  678. struct make_signed<unsigned __int128> {
  679. typedef __int128 type;
  680. };
  681. template <>
  682. struct is_signed<__int128> : ::std::true_type {};
  683. template <>
  684. struct is_unsigned<unsigned __int128> : ::std::true_type {};
  685. FOLLY_NAMESPACE_STD_END
  686. #endif // FOLLY_SUPPLY_MISSING_INT128_TRAITS