TypeTraits.h 36 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262
  1. /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /* This Source Code Form is subject to the terms of the Mozilla Public
  3. * License, v. 2.0. If a copy of the MPL was not distributed with this
  4. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. /* Template-based metaprogramming and type-testing facilities. */
  6. #ifndef mozilla_TypeTraits_h
  7. #define mozilla_TypeTraits_h
  8. #include "mozilla/Types.h"
  9. /*
  10. * These traits are approximate copies of the traits and semantics from C++11's
  11. * <type_traits> header. Don't add traits not in that header! When all
  12. * platforms provide that header, we can convert all users and remove this one.
  13. */
  14. #include <wchar.h>
  15. namespace mozilla {
  16. /* Forward declarations. */
  17. template<typename> struct RemoveCV;
  18. template<typename> struct AddRvalueReference;
  19. /* 20.2.4 Function template declval [declval] */
  20. /**
  21. * DeclVal simplifies the definition of expressions which occur as unevaluated
  22. * operands. It converts T to a reference type, making it possible to use in
  23. * decltype expressions even if T does not have a default constructor, e.g.:
  24. * decltype(DeclVal<TWithNoDefaultConstructor>().foo())
  25. */
  26. template<typename T>
  27. typename AddRvalueReference<T>::Type DeclVal();
  28. /* 20.9.3 Helper classes [meta.help] */
  29. /**
  30. * Helper class used as a base for various type traits, exposed publicly
  31. * because <type_traits> exposes it as well.
  32. */
  33. template<typename T, T Value>
  34. struct IntegralConstant
  35. {
  36. static const T value = Value;
  37. typedef T ValueType;
  38. typedef IntegralConstant<T, Value> Type;
  39. };
  40. /** Convenient aliases. */
  41. typedef IntegralConstant<bool, true> TrueType;
  42. typedef IntegralConstant<bool, false> FalseType;
  43. /* 20.9.4 Unary type traits [meta.unary] */
  44. /* 20.9.4.1 Primary type categories [meta.unary.cat] */
  45. namespace detail {
  46. template<typename T>
  47. struct IsVoidHelper : FalseType {};
  48. template<>
  49. struct IsVoidHelper<void> : TrueType {};
  50. } // namespace detail
  51. /**
  52. * IsVoid determines whether a type is void.
  53. *
  54. * mozilla::IsVoid<int>::value is false;
  55. * mozilla::IsVoid<void>::value is true;
  56. * mozilla::IsVoid<void*>::value is false;
  57. * mozilla::IsVoid<volatile void>::value is true.
  58. */
  59. template<typename T>
  60. struct IsVoid : detail::IsVoidHelper<typename RemoveCV<T>::Type> {};
  61. namespace detail {
  62. template <typename T>
  63. struct IsIntegralHelper : FalseType {};
  64. template<> struct IsIntegralHelper<char> : TrueType {};
  65. template<> struct IsIntegralHelper<signed char> : TrueType {};
  66. template<> struct IsIntegralHelper<unsigned char> : TrueType {};
  67. template<> struct IsIntegralHelper<short> : TrueType {};
  68. template<> struct IsIntegralHelper<unsigned short> : TrueType {};
  69. template<> struct IsIntegralHelper<int> : TrueType {};
  70. template<> struct IsIntegralHelper<unsigned int> : TrueType {};
  71. template<> struct IsIntegralHelper<long> : TrueType {};
  72. template<> struct IsIntegralHelper<unsigned long> : TrueType {};
  73. template<> struct IsIntegralHelper<long long> : TrueType {};
  74. template<> struct IsIntegralHelper<unsigned long long> : TrueType {};
  75. template<> struct IsIntegralHelper<bool> : TrueType {};
  76. template<> struct IsIntegralHelper<wchar_t> : TrueType {};
  77. template<> struct IsIntegralHelper<char16_t> : TrueType {};
  78. } /* namespace detail */
  79. /**
  80. * IsIntegral determines whether a type is an integral type.
  81. *
  82. * mozilla::IsIntegral<int>::value is true;
  83. * mozilla::IsIntegral<unsigned short>::value is true;
  84. * mozilla::IsIntegral<const long>::value is true;
  85. * mozilla::IsIntegral<int*>::value is false;
  86. * mozilla::IsIntegral<double>::value is false;
  87. */
  88. template<typename T>
  89. struct IsIntegral : detail::IsIntegralHelper<typename RemoveCV<T>::Type>
  90. {};
  91. template<typename T, typename U>
  92. struct IsSame;
  93. namespace detail {
  94. template<typename T>
  95. struct IsFloatingPointHelper
  96. : IntegralConstant<bool,
  97. IsSame<T, float>::value ||
  98. IsSame<T, double>::value ||
  99. IsSame<T, long double>::value>
  100. {};
  101. } // namespace detail
  102. /**
  103. * IsFloatingPoint determines whether a type is a floating point type (float,
  104. * double, long double).
  105. *
  106. * mozilla::IsFloatingPoint<int>::value is false;
  107. * mozilla::IsFloatingPoint<const float>::value is true;
  108. * mozilla::IsFloatingPoint<long double>::value is true;
  109. * mozilla::IsFloatingPoint<double*>::value is false.
  110. */
  111. template<typename T>
  112. struct IsFloatingPoint
  113. : detail::IsFloatingPointHelper<typename RemoveCV<T>::Type>
  114. {};
  115. namespace detail {
  116. template<typename T>
  117. struct IsArrayHelper : FalseType {};
  118. template<typename T, decltype(sizeof(1)) N>
  119. struct IsArrayHelper<T[N]> : TrueType {};
  120. template<typename T>
  121. struct IsArrayHelper<T[]> : TrueType {};
  122. } // namespace detail
  123. /**
  124. * IsArray determines whether a type is an array type, of known or unknown
  125. * length.
  126. *
  127. * mozilla::IsArray<int>::value is false;
  128. * mozilla::IsArray<int[]>::value is true;
  129. * mozilla::IsArray<int[5]>::value is true.
  130. */
  131. template<typename T>
  132. struct IsArray : detail::IsArrayHelper<typename RemoveCV<T>::Type>
  133. {};
  134. namespace detail {
  135. template<typename T>
  136. struct IsFunPtr;
  137. template<typename>
  138. struct IsFunPtr
  139. : public FalseType
  140. {};
  141. template<typename Result, typename... ArgTypes>
  142. struct IsFunPtr<Result(*)(ArgTypes...)>
  143. : public TrueType
  144. {};
  145. }; // namespace detail
  146. /**
  147. * IsFunction determines whether a type is a function type. Function pointers
  148. * don't qualify here--only the type of an actual function symbol. We do not
  149. * correctly handle varags function types because of a bug in MSVC.
  150. *
  151. * Given the function:
  152. * void f(int) {}
  153. *
  154. * mozilla::IsFunction<void(int)> is true;
  155. * mozilla::IsFunction<void(*)(int)> is false;
  156. * mozilla::IsFunction<decltype(f)> is true.
  157. */
  158. template<typename T>
  159. struct IsFunction
  160. : public detail::IsFunPtr<typename RemoveCV<T>::Type *>
  161. {};
  162. namespace detail {
  163. template<typename T>
  164. struct IsPointerHelper : FalseType {};
  165. template<typename T>
  166. struct IsPointerHelper<T*> : TrueType {};
  167. } // namespace detail
  168. /**
  169. * IsPointer determines whether a type is a possibly-CV-qualified pointer type
  170. * (but not a pointer-to-member type).
  171. *
  172. * mozilla::IsPointer<struct S*>::value is true;
  173. * mozilla::IsPointer<int*>::value is true;
  174. * mozilla::IsPointer<int**>::value is true;
  175. * mozilla::IsPointer<const int*>::value is true;
  176. * mozilla::IsPointer<int* const>::value is true;
  177. * mozilla::IsPointer<int* volatile>::value is true;
  178. * mozilla::IsPointer<void (*)(void)>::value is true;
  179. * mozilla::IsPointer<int>::value is false;
  180. * mozilla::IsPointer<struct S>::value is false.
  181. * mozilla::IsPointer<int(struct S::*)>::value is false
  182. */
  183. template<typename T>
  184. struct IsPointer : detail::IsPointerHelper<typename RemoveCV<T>::Type>
  185. {};
  186. /**
  187. * IsLvalueReference determines whether a type is an lvalue reference.
  188. *
  189. * mozilla::IsLvalueReference<struct S*>::value is false;
  190. * mozilla::IsLvalueReference<int**>::value is false;
  191. * mozilla::IsLvalueReference<void (*)(void)>::value is false;
  192. * mozilla::IsLvalueReference<int>::value is false;
  193. * mozilla::IsLvalueReference<struct S>::value is false;
  194. * mozilla::IsLvalueReference<struct S*&>::value is true;
  195. * mozilla::IsLvalueReference<struct S&&>::value is false.
  196. */
  197. template<typename T>
  198. struct IsLvalueReference : FalseType {};
  199. template<typename T>
  200. struct IsLvalueReference<T&> : TrueType {};
  201. /**
  202. * IsRvalueReference determines whether a type is an rvalue reference.
  203. *
  204. * mozilla::IsRvalueReference<struct S*>::value is false;
  205. * mozilla::IsRvalueReference<int**>::value is false;
  206. * mozilla::IsRvalueReference<void (*)(void)>::value is false;
  207. * mozilla::IsRvalueReference<int>::value is false;
  208. * mozilla::IsRvalueReference<struct S>::value is false;
  209. * mozilla::IsRvalueReference<struct S*&>::value is false;
  210. * mozilla::IsRvalueReference<struct S&&>::value is true.
  211. */
  212. template<typename T>
  213. struct IsRvalueReference : FalseType {};
  214. template<typename T>
  215. struct IsRvalueReference<T&&> : TrueType {};
  216. namespace detail {
  217. // __is_enum is a supported extension across all of our supported compilers.
  218. template<typename T>
  219. struct IsEnumHelper
  220. : IntegralConstant<bool, __is_enum(T)>
  221. {};
  222. } // namespace detail
  223. /**
  224. * IsEnum determines whether a type is an enum type.
  225. *
  226. * mozilla::IsEnum<enum S>::value is true;
  227. * mozilla::IsEnum<enum S*>::value is false;
  228. * mozilla::IsEnum<int>::value is false;
  229. */
  230. template<typename T>
  231. struct IsEnum
  232. : detail::IsEnumHelper<typename RemoveCV<T>::Type>
  233. {};
  234. namespace detail {
  235. // __is_class is a supported extension across all of our supported compilers:
  236. // http://llvm.org/releases/3.0/docs/ClangReleaseNotes.html
  237. // http://gcc.gnu.org/onlinedocs/gcc-4.4.7/gcc/Type-Traits.html#Type-Traits
  238. // http://msdn.microsoft.com/en-us/library/ms177194%28v=vs.100%29.aspx
  239. template<typename T>
  240. struct IsClassHelper
  241. : IntegralConstant<bool, __is_class(T)>
  242. {};
  243. } // namespace detail
  244. /**
  245. * IsClass determines whether a type is a class type (but not a union).
  246. *
  247. * struct S {};
  248. * union U {};
  249. * mozilla::IsClass<int>::value is false;
  250. * mozilla::IsClass<const S>::value is true;
  251. * mozilla::IsClass<U>::value is false;
  252. */
  253. template<typename T>
  254. struct IsClass
  255. : detail::IsClassHelper<typename RemoveCV<T>::Type>
  256. {};
  257. /* 20.9.4.2 Composite type traits [meta.unary.comp] */
  258. /**
  259. * IsReference determines whether a type is an lvalue or rvalue reference.
  260. *
  261. * mozilla::IsReference<struct S*>::value is false;
  262. * mozilla::IsReference<int**>::value is false;
  263. * mozilla::IsReference<int&>::value is true;
  264. * mozilla::IsReference<void (*)(void)>::value is false;
  265. * mozilla::IsReference<const int&>::value is true;
  266. * mozilla::IsReference<int>::value is false;
  267. * mozilla::IsReference<struct S>::value is false;
  268. * mozilla::IsReference<struct S&>::value is true;
  269. * mozilla::IsReference<struct S*&>::value is true;
  270. * mozilla::IsReference<struct S&&>::value is true.
  271. */
  272. template<typename T>
  273. struct IsReference
  274. : IntegralConstant<bool,
  275. IsLvalueReference<T>::value || IsRvalueReference<T>::value>
  276. {};
  277. /**
  278. * IsArithmetic determines whether a type is arithmetic. A type is arithmetic
  279. * iff it is an integral type or a floating point type.
  280. *
  281. * mozilla::IsArithmetic<int>::value is true;
  282. * mozilla::IsArithmetic<double>::value is true;
  283. * mozilla::IsArithmetic<long double*>::value is false.
  284. */
  285. template<typename T>
  286. struct IsArithmetic
  287. : IntegralConstant<bool, IsIntegral<T>::value || IsFloatingPoint<T>::value>
  288. {};
  289. namespace detail {
  290. template<typename T>
  291. struct IsMemberPointerHelper : FalseType {};
  292. template<typename T, typename U>
  293. struct IsMemberPointerHelper<T U::*> : TrueType {};
  294. } // namespace detail
  295. /**
  296. * IsMemberPointer determines whether a type is pointer to non-static member
  297. * object or a pointer to non-static member function.
  298. *
  299. * mozilla::IsMemberPointer<int(cls::*)>::value is true
  300. * mozilla::IsMemberPointer<int*>::value is false
  301. */
  302. template<typename T>
  303. struct IsMemberPointer
  304. : detail::IsMemberPointerHelper<typename RemoveCV<T>::Type>
  305. {};
  306. /**
  307. * IsScalar determines whether a type is a scalar type.
  308. *
  309. * mozilla::IsScalar<int>::value is true
  310. * mozilla::IsScalar<int*>::value is true
  311. * mozilla::IsScalar<cls>::value is false
  312. */
  313. template<typename T>
  314. struct IsScalar
  315. : IntegralConstant<bool, IsArithmetic<T>::value || IsEnum<T>::value ||
  316. IsPointer<T>::value || IsMemberPointer<T>::value>
  317. {};
  318. /* 20.9.4.3 Type properties [meta.unary.prop] */
  319. /**
  320. * IsConst determines whether a type is const or not.
  321. *
  322. * mozilla::IsConst<int>::value is false;
  323. * mozilla::IsConst<void* const>::value is true;
  324. * mozilla::IsConst<const char*>::value is false.
  325. */
  326. template<typename T>
  327. struct IsConst : FalseType {};
  328. template<typename T>
  329. struct IsConst<const T> : TrueType {};
  330. /**
  331. * IsVolatile determines whether a type is volatile or not.
  332. *
  333. * mozilla::IsVolatile<int>::value is false;
  334. * mozilla::IsVolatile<void* volatile>::value is true;
  335. * mozilla::IsVolatile<volatile char*>::value is false.
  336. */
  337. template<typename T>
  338. struct IsVolatile : FalseType {};
  339. template<typename T>
  340. struct IsVolatile<volatile T> : TrueType {};
  341. /**
  342. * Traits class for identifying POD types. Until C++11 there's no automatic
  343. * way to detect PODs, so for the moment this is done manually. Users may
  344. * define specializations of this class that inherit from mozilla::TrueType and
  345. * mozilla::FalseType (or equivalently mozilla::IntegralConstant<bool, true or
  346. * false>, or conveniently from mozilla::IsPod for composite types) as needed to
  347. * ensure correct IsPod behavior.
  348. */
  349. template<typename T>
  350. struct IsPod : public FalseType {};
  351. template<> struct IsPod<char> : TrueType {};
  352. template<> struct IsPod<signed char> : TrueType {};
  353. template<> struct IsPod<unsigned char> : TrueType {};
  354. template<> struct IsPod<short> : TrueType {};
  355. template<> struct IsPod<unsigned short> : TrueType {};
  356. template<> struct IsPod<int> : TrueType {};
  357. template<> struct IsPod<unsigned int> : TrueType {};
  358. template<> struct IsPod<long> : TrueType {};
  359. template<> struct IsPod<unsigned long> : TrueType {};
  360. template<> struct IsPod<long long> : TrueType {};
  361. template<> struct IsPod<unsigned long long> : TrueType {};
  362. template<> struct IsPod<bool> : TrueType {};
  363. template<> struct IsPod<float> : TrueType {};
  364. template<> struct IsPod<double> : TrueType {};
  365. template<> struct IsPod<wchar_t> : TrueType {};
  366. template<> struct IsPod<char16_t> : TrueType {};
  367. template<typename T> struct IsPod<T*> : TrueType {};
  368. namespace detail {
  369. // __is_empty is a supported extension across all of our supported compilers:
  370. // http://llvm.org/releases/3.0/docs/ClangReleaseNotes.html
  371. // http://gcc.gnu.org/onlinedocs/gcc-4.4.7/gcc/Type-Traits.html#Type-Traits
  372. // http://msdn.microsoft.com/en-us/library/ms177194%28v=vs.100%29.aspx
  373. template<typename T>
  374. struct IsEmptyHelper
  375. : IntegralConstant<bool, IsClass<T>::value && __is_empty(T)>
  376. {};
  377. } // namespace detail
  378. /**
  379. * IsEmpty determines whether a type is a class (but not a union) that is empty.
  380. *
  381. * A class is empty iff it and all its base classes have no non-static data
  382. * members (except bit-fields of length 0) and no virtual member functions, and
  383. * no base class is empty or a virtual base class.
  384. *
  385. * Intuitively, empty classes don't have any data that has to be stored in
  386. * instances of those classes. (The size of the class must still be non-zero,
  387. * because distinct array elements of any type must have different addresses.
  388. * However, if the Empty Base Optimization is implemented by the compiler [most
  389. * compilers implement it, and in certain cases C++11 requires it], the size of
  390. * a class inheriting from an empty |Base| class need not be inflated by
  391. * |sizeof(Base)|.) And intuitively, non-empty classes have data members and/or
  392. * vtable pointers that must be stored in each instance for proper behavior.
  393. *
  394. * static_assert(!mozilla::IsEmpty<int>::value, "not a class => not empty");
  395. * union U1 { int x; };
  396. * static_assert(!mozilla::IsEmpty<U1>::value, "not a class => not empty");
  397. * struct E1 {};
  398. * struct E2 { int : 0 };
  399. * struct E3 : E1 {};
  400. * struct E4 : E2 {};
  401. * static_assert(mozilla::IsEmpty<E1>::value &&
  402. * mozilla::IsEmpty<E2>::value &&
  403. * mozilla::IsEmpty<E3>::value &&
  404. * mozilla::IsEmpty<E4>::value,
  405. * "all empty");
  406. * union U2 { E1 e1; };
  407. * static_assert(!mozilla::IsEmpty<U2>::value, "not a class => not empty");
  408. * struct NE1 { int x; };
  409. * struct NE2 : virtual E1 {};
  410. * struct NE3 : E2 { virtual ~NE3() {} };
  411. * struct NE4 { virtual void f() {} };
  412. * static_assert(!mozilla::IsEmpty<NE1>::value &&
  413. * !mozilla::IsEmpty<NE2>::value &&
  414. * !mozilla::IsEmpty<NE3>::value &&
  415. * !mozilla::IsEmpty<NE4>::value,
  416. * "all empty");
  417. */
  418. template<typename T>
  419. struct IsEmpty : detail::IsEmptyHelper<typename RemoveCV<T>::Type>
  420. {};
  421. namespace detail {
  422. template<typename T,
  423. bool = IsFloatingPoint<T>::value,
  424. bool = IsIntegral<T>::value,
  425. typename NoCV = typename RemoveCV<T>::Type>
  426. struct IsSignedHelper;
  427. // Floating point is signed.
  428. template<typename T, typename NoCV>
  429. struct IsSignedHelper<T, true, false, NoCV> : TrueType {};
  430. // Integral is conditionally signed.
  431. template<typename T, typename NoCV>
  432. struct IsSignedHelper<T, false, true, NoCV>
  433. : IntegralConstant<bool, bool(NoCV(-1) < NoCV(1))>
  434. {};
  435. // Non-floating point, non-integral is not signed.
  436. template<typename T, typename NoCV>
  437. struct IsSignedHelper<T, false, false, NoCV> : FalseType {};
  438. } // namespace detail
  439. /**
  440. * IsSigned determines whether a type is a signed arithmetic type. |char| is
  441. * considered a signed type if it has the same representation as |signed char|.
  442. *
  443. * mozilla::IsSigned<int>::value is true;
  444. * mozilla::IsSigned<const unsigned int>::value is false;
  445. * mozilla::IsSigned<unsigned char>::value is false;
  446. * mozilla::IsSigned<float>::value is true.
  447. */
  448. template<typename T>
  449. struct IsSigned : detail::IsSignedHelper<T> {};
  450. namespace detail {
  451. template<typename T,
  452. bool = IsFloatingPoint<T>::value,
  453. bool = IsIntegral<T>::value,
  454. typename NoCV = typename RemoveCV<T>::Type>
  455. struct IsUnsignedHelper;
  456. // Floating point is not unsigned.
  457. template<typename T, typename NoCV>
  458. struct IsUnsignedHelper<T, true, false, NoCV> : FalseType {};
  459. // Integral is conditionally unsigned.
  460. template<typename T, typename NoCV>
  461. struct IsUnsignedHelper<T, false, true, NoCV>
  462. : IntegralConstant<bool,
  463. (IsSame<NoCV, bool>::value || bool(NoCV(1) < NoCV(-1)))>
  464. {};
  465. // Non-floating point, non-integral is not unsigned.
  466. template<typename T, typename NoCV>
  467. struct IsUnsignedHelper<T, false, false, NoCV> : FalseType {};
  468. } // namespace detail
  469. /**
  470. * IsUnsigned determines whether a type is an unsigned arithmetic type.
  471. *
  472. * mozilla::IsUnsigned<int>::value is false;
  473. * mozilla::IsUnsigned<const unsigned int>::value is true;
  474. * mozilla::IsUnsigned<unsigned char>::value is true;
  475. * mozilla::IsUnsigned<float>::value is false.
  476. */
  477. template<typename T>
  478. struct IsUnsigned : detail::IsUnsignedHelper<T> {};
  479. namespace detail {
  480. struct DoIsDestructibleImpl
  481. {
  482. template<typename T, typename = decltype(DeclVal<T&>().~T())>
  483. static TrueType test(int);
  484. template<typename T>
  485. static FalseType test(...);
  486. };
  487. template<typename T>
  488. struct IsDestructibleImpl : public DoIsDestructibleImpl
  489. {
  490. typedef decltype(test<T>(0)) Type;
  491. };
  492. } // namespace detail
  493. template<typename T>
  494. struct IsDestructible : public detail::IsDestructibleImpl<T>::Type {};
  495. /* 20.9.5 Type property queries [meta.unary.prop.query] */
  496. /* 20.9.6 Relationships between types [meta.rel] */
  497. /**
  498. * IsSame tests whether two types are the same type.
  499. *
  500. * mozilla::IsSame<int, int>::value is true;
  501. * mozilla::IsSame<int*, int*>::value is true;
  502. * mozilla::IsSame<int, unsigned int>::value is false;
  503. * mozilla::IsSame<void, void>::value is true;
  504. * mozilla::IsSame<const int, int>::value is false;
  505. * mozilla::IsSame<struct S, struct S>::value is true.
  506. */
  507. template<typename T, typename U>
  508. struct IsSame : FalseType {};
  509. template<typename T>
  510. struct IsSame<T, T> : TrueType {};
  511. namespace detail {
  512. #if defined(__GNUC__) || defined(__clang__) || defined(_MSC_VER)
  513. template<class Base, class Derived>
  514. struct BaseOfTester : IntegralConstant<bool, __is_base_of(Base, Derived)> {};
  515. #else
  516. // The trickery used to implement IsBaseOf here makes it possible to use it for
  517. // the cases of private and multiple inheritance. This code was inspired by the
  518. // sample code here:
  519. //
  520. // http://stackoverflow.com/questions/2910979/how-is-base-of-works
  521. template<class Base, class Derived>
  522. struct BaseOfHelper
  523. {
  524. public:
  525. operator Base*() const;
  526. operator Derived*();
  527. };
  528. template<class Base, class Derived>
  529. struct BaseOfTester
  530. {
  531. private:
  532. template<class T>
  533. static char test(Derived*, T);
  534. static int test(Base*, int);
  535. public:
  536. static const bool value =
  537. sizeof(test(BaseOfHelper<Base, Derived>(), int())) == sizeof(char);
  538. };
  539. template<class Base, class Derived>
  540. struct BaseOfTester<Base, const Derived>
  541. {
  542. private:
  543. template<class T>
  544. static char test(Derived*, T);
  545. static int test(Base*, int);
  546. public:
  547. static const bool value =
  548. sizeof(test(BaseOfHelper<Base, Derived>(), int())) == sizeof(char);
  549. };
  550. template<class Base, class Derived>
  551. struct BaseOfTester<Base&, Derived&> : FalseType {};
  552. template<class Type>
  553. struct BaseOfTester<Type, Type> : TrueType {};
  554. template<class Type>
  555. struct BaseOfTester<Type, const Type> : TrueType {};
  556. #endif
  557. } /* namespace detail */
  558. /*
  559. * IsBaseOf allows to know whether a given class is derived from another.
  560. *
  561. * Consider the following class definitions:
  562. *
  563. * class A {};
  564. * class B : public A {};
  565. * class C {};
  566. *
  567. * mozilla::IsBaseOf<A, B>::value is true;
  568. * mozilla::IsBaseOf<A, C>::value is false;
  569. */
  570. template<class Base, class Derived>
  571. struct IsBaseOf
  572. : IntegralConstant<bool, detail::BaseOfTester<Base, Derived>::value>
  573. {};
  574. namespace detail {
  575. template<typename From, typename To>
  576. struct ConvertibleTester
  577. {
  578. private:
  579. template<typename To1>
  580. static char test_helper(To1);
  581. template<typename From1, typename To1>
  582. static decltype(test_helper<To1>(DeclVal<From1>())) test(int);
  583. template<typename From1, typename To1>
  584. static int test(...);
  585. public:
  586. static const bool value =
  587. sizeof(test<From, To>(0)) == sizeof(char);
  588. };
  589. } // namespace detail
  590. /**
  591. * IsConvertible determines whether a value of type From will implicitly convert
  592. * to a value of type To. For example:
  593. *
  594. * struct A {};
  595. * struct B : public A {};
  596. * struct C {};
  597. *
  598. * mozilla::IsConvertible<A, A>::value is true;
  599. * mozilla::IsConvertible<A*, A*>::value is true;
  600. * mozilla::IsConvertible<B, A>::value is true;
  601. * mozilla::IsConvertible<B*, A*>::value is true;
  602. * mozilla::IsConvertible<C, A>::value is false;
  603. * mozilla::IsConvertible<A, C>::value is false;
  604. * mozilla::IsConvertible<A*, C*>::value is false;
  605. * mozilla::IsConvertible<C*, A*>::value is false.
  606. *
  607. * For obscure reasons, you can't use IsConvertible when the types being tested
  608. * are related through private inheritance, and you'll get a compile error if
  609. * you try. Just don't do it!
  610. *
  611. * Note - we need special handling for void, which ConvertibleTester doesn't
  612. * handle. The void handling here doesn't handle const/volatile void correctly,
  613. * which could be easily fixed if the need arises.
  614. */
  615. template<typename From, typename To>
  616. struct IsConvertible
  617. : IntegralConstant<bool, detail::ConvertibleTester<From, To>::value>
  618. {};
  619. template<typename B>
  620. struct IsConvertible<void, B>
  621. : IntegralConstant<bool, IsVoid<B>::value>
  622. {};
  623. template<typename A>
  624. struct IsConvertible<A, void>
  625. : IntegralConstant<bool, IsVoid<A>::value>
  626. {};
  627. template<>
  628. struct IsConvertible<void, void>
  629. : TrueType
  630. {};
  631. /* 20.9.7 Transformations between types [meta.trans] */
  632. /* 20.9.7.1 Const-volatile modifications [meta.trans.cv] */
  633. /**
  634. * RemoveConst removes top-level const qualifications on a type.
  635. *
  636. * mozilla::RemoveConst<int>::Type is int;
  637. * mozilla::RemoveConst<const int>::Type is int;
  638. * mozilla::RemoveConst<const int*>::Type is const int*;
  639. * mozilla::RemoveConst<int* const>::Type is int*.
  640. */
  641. template<typename T>
  642. struct RemoveConst
  643. {
  644. typedef T Type;
  645. };
  646. template<typename T>
  647. struct RemoveConst<const T>
  648. {
  649. typedef T Type;
  650. };
  651. /**
  652. * RemoveVolatile removes top-level volatile qualifications on a type.
  653. *
  654. * mozilla::RemoveVolatile<int>::Type is int;
  655. * mozilla::RemoveVolatile<volatile int>::Type is int;
  656. * mozilla::RemoveVolatile<volatile int*>::Type is volatile int*;
  657. * mozilla::RemoveVolatile<int* volatile>::Type is int*.
  658. */
  659. template<typename T>
  660. struct RemoveVolatile
  661. {
  662. typedef T Type;
  663. };
  664. template<typename T>
  665. struct RemoveVolatile<volatile T>
  666. {
  667. typedef T Type;
  668. };
  669. /**
  670. * RemoveCV removes top-level const and volatile qualifications on a type.
  671. *
  672. * mozilla::RemoveCV<int>::Type is int;
  673. * mozilla::RemoveCV<const int>::Type is int;
  674. * mozilla::RemoveCV<volatile int>::Type is int;
  675. * mozilla::RemoveCV<int* const volatile>::Type is int*.
  676. */
  677. template<typename T>
  678. struct RemoveCV
  679. {
  680. typedef typename RemoveConst<typename RemoveVolatile<T>::Type>::Type Type;
  681. };
  682. /* 20.9.7.2 Reference modifications [meta.trans.ref] */
  683. /**
  684. * Converts reference types to the underlying types.
  685. *
  686. * mozilla::RemoveReference<T>::Type is T;
  687. * mozilla::RemoveReference<T&>::Type is T;
  688. * mozilla::RemoveReference<T&&>::Type is T;
  689. */
  690. template<typename T>
  691. struct RemoveReference
  692. {
  693. typedef T Type;
  694. };
  695. template<typename T>
  696. struct RemoveReference<T&>
  697. {
  698. typedef T Type;
  699. };
  700. template<typename T>
  701. struct RemoveReference<T&&>
  702. {
  703. typedef T Type;
  704. };
  705. template<bool Condition, typename A, typename B>
  706. struct Conditional;
  707. namespace detail {
  708. enum Voidness { TIsVoid, TIsNotVoid };
  709. template<typename T, Voidness V = IsVoid<T>::value ? TIsVoid : TIsNotVoid>
  710. struct AddLvalueReferenceHelper;
  711. template<typename T>
  712. struct AddLvalueReferenceHelper<T, TIsVoid>
  713. {
  714. typedef void Type;
  715. };
  716. template<typename T>
  717. struct AddLvalueReferenceHelper<T, TIsNotVoid>
  718. {
  719. typedef T& Type;
  720. };
  721. } // namespace detail
  722. /**
  723. * AddLvalueReference adds an lvalue & reference to T if one isn't already
  724. * present. (Note: adding an lvalue reference to an rvalue && reference in
  725. * essence replaces the && with a &&, per C+11 reference collapsing rules. For
  726. * example, int&& would become int&.)
  727. *
  728. * The final computed type will only *not* be an lvalue reference if T is void.
  729. *
  730. * mozilla::AddLvalueReference<int>::Type is int&;
  731. * mozilla::AddLvalueRference<volatile int&>::Type is volatile int&;
  732. * mozilla::AddLvalueReference<void*>::Type is void*&;
  733. * mozilla::AddLvalueReference<void>::Type is void;
  734. * mozilla::AddLvalueReference<struct S&&>::Type is struct S&.
  735. */
  736. template<typename T>
  737. struct AddLvalueReference
  738. : detail::AddLvalueReferenceHelper<T>
  739. {};
  740. namespace detail {
  741. template<typename T, Voidness V = IsVoid<T>::value ? TIsVoid : TIsNotVoid>
  742. struct AddRvalueReferenceHelper;
  743. template<typename T>
  744. struct AddRvalueReferenceHelper<T, TIsVoid>
  745. {
  746. typedef void Type;
  747. };
  748. template<typename T>
  749. struct AddRvalueReferenceHelper<T, TIsNotVoid>
  750. {
  751. typedef T&& Type;
  752. };
  753. } // namespace detail
  754. /**
  755. * AddRvalueReference adds an rvalue && reference to T if one isn't already
  756. * present. (Note: adding an rvalue reference to an lvalue & reference in
  757. * essence keeps the &, per C+11 reference collapsing rules. For example,
  758. * int& would remain int&.)
  759. *
  760. * The final computed type will only *not* be a reference if T is void.
  761. *
  762. * mozilla::AddRvalueReference<int>::Type is int&&;
  763. * mozilla::AddRvalueRference<volatile int&>::Type is volatile int&;
  764. * mozilla::AddRvalueRference<const int&&>::Type is const int&&;
  765. * mozilla::AddRvalueReference<void*>::Type is void*&&;
  766. * mozilla::AddRvalueReference<void>::Type is void;
  767. * mozilla::AddRvalueReference<struct S&>::Type is struct S&.
  768. */
  769. template<typename T>
  770. struct AddRvalueReference
  771. : detail::AddRvalueReferenceHelper<T>
  772. {};
  773. /* 20.9.7.3 Sign modifications [meta.trans.sign] */
  774. template<bool B, typename T = void>
  775. struct EnableIf;
  776. namespace detail {
  777. template<bool MakeConst, typename T>
  778. struct WithC : Conditional<MakeConst, const T, T>
  779. {};
  780. template<bool MakeVolatile, typename T>
  781. struct WithV : Conditional<MakeVolatile, volatile T, T>
  782. {};
  783. template<bool MakeConst, bool MakeVolatile, typename T>
  784. struct WithCV : WithC<MakeConst, typename WithV<MakeVolatile, T>::Type>
  785. {};
  786. template<typename T>
  787. struct CorrespondingSigned;
  788. template<>
  789. struct CorrespondingSigned<char> { typedef signed char Type; };
  790. template<>
  791. struct CorrespondingSigned<unsigned char> { typedef signed char Type; };
  792. template<>
  793. struct CorrespondingSigned<unsigned short> { typedef short Type; };
  794. template<>
  795. struct CorrespondingSigned<unsigned int> { typedef int Type; };
  796. template<>
  797. struct CorrespondingSigned<unsigned long> { typedef long Type; };
  798. template<>
  799. struct CorrespondingSigned<unsigned long long> { typedef long long Type; };
  800. template<typename T,
  801. typename CVRemoved = typename RemoveCV<T>::Type,
  802. bool IsSignedIntegerType = IsSigned<CVRemoved>::value &&
  803. !IsSame<char, CVRemoved>::value>
  804. struct MakeSigned;
  805. template<typename T, typename CVRemoved>
  806. struct MakeSigned<T, CVRemoved, true>
  807. {
  808. typedef T Type;
  809. };
  810. template<typename T, typename CVRemoved>
  811. struct MakeSigned<T, CVRemoved, false>
  812. : WithCV<IsConst<T>::value, IsVolatile<T>::value,
  813. typename CorrespondingSigned<CVRemoved>::Type>
  814. {};
  815. } // namespace detail
  816. /**
  817. * MakeSigned produces the corresponding signed integer type for a given
  818. * integral type T, with the const/volatile qualifiers of T. T must be a
  819. * possibly-const/volatile-qualified integral type that isn't bool.
  820. *
  821. * If T is already a signed integer type (not including char!), then T is
  822. * produced.
  823. *
  824. * Otherwise, if T is an unsigned integer type, the signed variety of T, with
  825. * T's const/volatile qualifiers, is produced.
  826. *
  827. * Otherwise, the integral type of the same size as T, with the lowest rank,
  828. * with T's const/volatile qualifiers, is produced. (This basically only acts
  829. * to produce signed char when T = char.)
  830. *
  831. * mozilla::MakeSigned<unsigned long>::Type is signed long;
  832. * mozilla::MakeSigned<volatile int>::Type is volatile int;
  833. * mozilla::MakeSigned<const unsigned short>::Type is const signed short;
  834. * mozilla::MakeSigned<const char>::Type is const signed char;
  835. * mozilla::MakeSigned<bool> is an error;
  836. * mozilla::MakeSigned<void*> is an error.
  837. */
  838. template<typename T>
  839. struct MakeSigned
  840. : EnableIf<IsIntegral<T>::value &&
  841. !IsSame<bool, typename RemoveCV<T>::Type>::value,
  842. typename detail::MakeSigned<T>
  843. >::Type
  844. {};
  845. namespace detail {
  846. template<typename T>
  847. struct CorrespondingUnsigned;
  848. template<>
  849. struct CorrespondingUnsigned<char> { typedef unsigned char Type; };
  850. template<>
  851. struct CorrespondingUnsigned<signed char> { typedef unsigned char Type; };
  852. template<>
  853. struct CorrespondingUnsigned<short> { typedef unsigned short Type; };
  854. template<>
  855. struct CorrespondingUnsigned<int> { typedef unsigned int Type; };
  856. template<>
  857. struct CorrespondingUnsigned<long> { typedef unsigned long Type; };
  858. template<>
  859. struct CorrespondingUnsigned<long long> { typedef unsigned long long Type; };
  860. template<typename T,
  861. typename CVRemoved = typename RemoveCV<T>::Type,
  862. bool IsUnsignedIntegerType = IsUnsigned<CVRemoved>::value &&
  863. !IsSame<char, CVRemoved>::value>
  864. struct MakeUnsigned;
  865. template<typename T, typename CVRemoved>
  866. struct MakeUnsigned<T, CVRemoved, true>
  867. {
  868. typedef T Type;
  869. };
  870. template<typename T, typename CVRemoved>
  871. struct MakeUnsigned<T, CVRemoved, false>
  872. : WithCV<IsConst<T>::value, IsVolatile<T>::value,
  873. typename CorrespondingUnsigned<CVRemoved>::Type>
  874. {};
  875. } // namespace detail
  876. /**
  877. * MakeUnsigned produces the corresponding unsigned integer type for a given
  878. * integral type T, with the const/volatile qualifiers of T. T must be a
  879. * possibly-const/volatile-qualified integral type that isn't bool.
  880. *
  881. * If T is already an unsigned integer type (not including char!), then T is
  882. * produced.
  883. *
  884. * Otherwise, if T is an signed integer type, the unsigned variety of T, with
  885. * T's const/volatile qualifiers, is produced.
  886. *
  887. * Otherwise, the unsigned integral type of the same size as T, with the lowest
  888. * rank, with T's const/volatile qualifiers, is produced. (This basically only
  889. * acts to produce unsigned char when T = char.)
  890. *
  891. * mozilla::MakeUnsigned<signed long>::Type is unsigned long;
  892. * mozilla::MakeUnsigned<volatile unsigned int>::Type is volatile unsigned int;
  893. * mozilla::MakeUnsigned<const signed short>::Type is const unsigned short;
  894. * mozilla::MakeUnsigned<const char>::Type is const unsigned char;
  895. * mozilla::MakeUnsigned<bool> is an error;
  896. * mozilla::MakeUnsigned<void*> is an error.
  897. */
  898. template<typename T>
  899. struct MakeUnsigned
  900. : EnableIf<IsIntegral<T>::value &&
  901. !IsSame<bool, typename RemoveCV<T>::Type>::value,
  902. typename detail::MakeUnsigned<T>
  903. >::Type
  904. {};
  905. /* 20.9.7.4 Array modifications [meta.trans.arr] */
  906. /**
  907. * RemoveExtent produces either the type of the elements of the array T, or T
  908. * itself.
  909. *
  910. * mozilla::RemoveExtent<int>::Type is int;
  911. * mozilla::RemoveExtent<const int[]>::Type is const int;
  912. * mozilla::RemoveExtent<volatile int[5]>::Type is volatile int;
  913. * mozilla::RemoveExtent<long[][17]>::Type is long[17].
  914. */
  915. template<typename T>
  916. struct RemoveExtent
  917. {
  918. typedef T Type;
  919. };
  920. template<typename T>
  921. struct RemoveExtent<T[]>
  922. {
  923. typedef T Type;
  924. };
  925. template<typename T, decltype(sizeof(1)) N>
  926. struct RemoveExtent<T[N]>
  927. {
  928. typedef T Type;
  929. };
  930. /* 20.9.7.5 Pointer modifications [meta.trans.ptr] */
  931. namespace detail {
  932. template<typename T, typename CVRemoved>
  933. struct RemovePointerHelper
  934. {
  935. typedef T Type;
  936. };
  937. template<typename T, typename Pointee>
  938. struct RemovePointerHelper<T, Pointee*>
  939. {
  940. typedef Pointee Type;
  941. };
  942. } // namespace detail
  943. /**
  944. * Produces the pointed-to type if a pointer is provided, else returns the input
  945. * type. Note that this does not dereference pointer-to-member pointers.
  946. *
  947. * struct S { bool m; void f(); };
  948. * mozilla::RemovePointer<int>::Type is int;
  949. * mozilla::RemovePointer<int*>::Type is int;
  950. * mozilla::RemovePointer<int* const>::Type is int;
  951. * mozilla::RemovePointer<int* volatile>::Type is int;
  952. * mozilla::RemovePointer<const long*>::Type is const long;
  953. * mozilla::RemovePointer<void* const>::Type is void;
  954. * mozilla::RemovePointer<void (S::*)()>::Type is void (S::*)();
  955. * mozilla::RemovePointer<void (*)()>::Type is void();
  956. * mozilla::RemovePointer<bool S::*>::Type is bool S::*.
  957. */
  958. template<typename T>
  959. struct RemovePointer
  960. : detail::RemovePointerHelper<T, typename RemoveCV<T>::Type>
  961. {};
  962. /**
  963. * Converts T& to T*. Otherwise returns T* given T. Note that C++17 wants
  964. * std::add_pointer to work differently for function types. We don't implement
  965. * that behavior here.
  966. *
  967. * mozilla::AddPointer<int> is int*;
  968. * mozilla::AddPointer<int*> is int**;
  969. * mozilla::AddPointer<int&> is int*;
  970. * mozilla::AddPointer<int* const> is int** const.
  971. */
  972. template<typename T>
  973. struct AddPointer
  974. {
  975. typedef typename RemoveReference<T>::Type* Type;
  976. };
  977. /* 20.9.7.6 Other transformations [meta.trans.other] */
  978. /**
  979. * EnableIf is a struct containing a typedef of T if and only if B is true.
  980. *
  981. * mozilla::EnableIf<true, int>::Type is int;
  982. * mozilla::EnableIf<false, int>::Type is a compile-time error.
  983. *
  984. * Use this template to implement SFINAE-style (Substitution Failure Is not An
  985. * Error) requirements. For example, you might use it to impose a restriction
  986. * on a template parameter:
  987. *
  988. * template<typename T>
  989. * class PodVector // vector optimized to store POD (memcpy-able) types
  990. * {
  991. * EnableIf<IsPod<T>::value, T>::Type* vector;
  992. * size_t length;
  993. * ...
  994. * };
  995. */
  996. template<bool B, typename T>
  997. struct EnableIf
  998. {};
  999. template<typename T>
  1000. struct EnableIf<true, T>
  1001. {
  1002. typedef T Type;
  1003. };
  1004. /**
  1005. * Conditional selects a class between two, depending on a given boolean value.
  1006. *
  1007. * mozilla::Conditional<true, A, B>::Type is A;
  1008. * mozilla::Conditional<false, A, B>::Type is B;
  1009. */
  1010. template<bool Condition, typename A, typename B>
  1011. struct Conditional
  1012. {
  1013. typedef A Type;
  1014. };
  1015. template<class A, class B>
  1016. struct Conditional<false, A, B>
  1017. {
  1018. typedef B Type;
  1019. };
  1020. namespace detail {
  1021. template<typename U,
  1022. bool IsArray = IsArray<U>::value,
  1023. bool IsFunction = IsFunction<U>::value>
  1024. struct DecaySelector;
  1025. template<typename U>
  1026. struct DecaySelector<U, false, false>
  1027. {
  1028. typedef typename RemoveCV<U>::Type Type;
  1029. };
  1030. template<typename U>
  1031. struct DecaySelector<U, true, false>
  1032. {
  1033. typedef typename RemoveExtent<U>::Type* Type;
  1034. };
  1035. template<typename U>
  1036. struct DecaySelector<U, false, true>
  1037. {
  1038. typedef typename AddPointer<U>::Type Type;
  1039. };
  1040. }; // namespace detail
  1041. /**
  1042. * Strips const/volatile off a type and decays it from an lvalue to an
  1043. * rvalue. So function types are converted to function pointers, arrays to
  1044. * pointers, and references are removed.
  1045. *
  1046. * mozilla::Decay<int>::Type is int
  1047. * mozilla::Decay<int&>::Type is int
  1048. * mozilla::Decay<int&&>::Type is int
  1049. * mozilla::Decay<const int&>::Type is int
  1050. * mozilla::Decay<int[2]>::Type is int*
  1051. * mozilla::Decay<int(int)>::Type is int(*)(int)
  1052. */
  1053. template<typename T>
  1054. class Decay
  1055. : public detail::DecaySelector<typename RemoveReference<T>::Type>
  1056. {
  1057. };
  1058. } /* namespace mozilla */
  1059. #endif /* mozilla_TypeTraits_h */