Optional.h 35 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262
  1. // Copyright (C) 2011 - 2012 Andrzej Krzemienski.
  2. //
  3. // Use, modification, and distribution is subject to the Boost Software
  4. // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  5. // http://www.boost.org/LICENSE_1_0.txt)
  6. //
  7. // The idea and interface is based on Boost.Optional library
  8. // authored by Fernando Luis Cacciola Carballal
  9. //
  10. // From https://github.com/akrzemi1/Optional
  11. //
  12. // C10
  13. // - Move file to `c10` namespace.
  14. // - Remove macro use in line 478 because the nvcc device compiler cannot handle
  15. // it.
  16. // - Revise constructor logic so that it is 1) consistent with c++ 17 standard
  17. // documented here in (8):
  18. // https://en.cppreference.com/w/cpp/utility/optional/optional, and 2) able to
  19. // support initialization of optionals from convertible type U.
  20. // - Remove the constructors for `optional(const T&)` and `optional(T&&)`, as
  21. // they can be handled by the template<U=T> case with the default template
  22. // argument.
  23. // - Move `constexpr struct in_place_t {} in_place{}` to `c10/util/in_place.h`
  24. // so that it can also be used in `c10/util/variant.h`.
  25. // - Remove special cases for pre-c++14 compilers to make code simpler.
  26. #ifndef C10_UTIL_OPTIONAL_H_
  27. #define C10_UTIL_OPTIONAL_H_
  28. #include <c10/macros/Macros.h>
  29. #include <c10/util/ArrayRef.h>
  30. #include <c10/util/in_place.h>
  31. #include <cassert>
  32. #include <functional>
  33. #include <initializer_list>
  34. #include <stdexcept>
  35. #include <string>
  36. #include <type_traits>
  37. #include <utility>
  38. #include <c10/util/C++17.h>
  39. #include <c10/util/Metaprogramming.h>
  40. C10_CLANG_DIAGNOSTIC_PUSH()
  41. #if C10_CLANG_HAS_WARNING("-Wstring-conversion")
  42. C10_CLANG_DIAGNOSTIC_IGNORE("-Wstring-conversion")
  43. #endif
  44. #if C10_CLANG_HAS_WARNING("-Wshorten-64-to-32")
  45. C10_CLANG_DIAGNOSTIC_IGNORE("-Wshorten-64-to-32")
  46. #endif
  47. #if C10_CLANG_HAS_WARNING("-Wimplicit-float-conversion")
  48. C10_CLANG_DIAGNOSTIC_IGNORE("-Wimplicit-float-conversion")
  49. #endif
  50. #if C10_CLANG_HAS_WARNING("-Wimplicit-int-conversion")
  51. C10_CLANG_DIAGNOSTIC_IGNORE("-Wimplicit-int-conversion")
  52. #endif
  53. #define TR2_OPTIONAL_REQUIRES(...) \
  54. typename std::enable_if<__VA_ARGS__::value, bool>::type = false
  55. namespace c10 {
  56. // 20.5.4, optional for object types
  57. template <class T>
  58. class optional;
  59. // 20.5.5, optional for lvalue reference types
  60. template <class T>
  61. class optional<T&>;
  62. // workaround: std utility functions aren't constexpr yet
  63. template <class T>
  64. inline constexpr T&& constexpr_forward(
  65. typename std::remove_reference<T>::type& t) noexcept {
  66. return static_cast<T&&>(t);
  67. }
  68. template <class T>
  69. inline constexpr T&& constexpr_forward(
  70. typename std::remove_reference<T>::type&& t) noexcept {
  71. static_assert(!std::is_lvalue_reference<T>::value, "!!");
  72. return static_cast<T&&>(t);
  73. }
  74. template <class T>
  75. inline constexpr typename std::remove_reference<T>::type&& constexpr_move(
  76. T&& t) noexcept {
  77. return static_cast<typename std::remove_reference<T>::type&&>(t);
  78. }
  79. #if defined NDEBUG
  80. #define TR2_OPTIONAL_ASSERTED_EXPRESSION(CHECK, EXPR) (EXPR)
  81. #else
  82. #define TR2_OPTIONAL_ASSERTED_EXPRESSION(CHECK, EXPR) \
  83. ((CHECK) ? (EXPR) : ([] { assert(!#CHECK); }(), (EXPR)))
  84. #endif
  85. #if defined(__CUDA_ARCH__)
  86. #define TR2_OPTIONAL_HOST_CONSTEXPR
  87. #else
  88. #define TR2_OPTIONAL_HOST_CONSTEXPR constexpr
  89. #endif
  90. // Sphinx chokes on static_addressof, so exclude it from Doxygen
  91. // generation. See https://github.com/sphinx-doc/sphinx/issues/7944
  92. // \cond
  93. namespace detail_ {
  94. // VS doesn't handle constexpr well, so we need to skip these stuff.
  95. #if (defined _MSC_VER)
  96. template <typename T>
  97. T* static_addressof(T& ref) {
  98. return std::addressof(ref);
  99. }
  100. #else
  101. // static_addressof: a constexpr version of addressof
  102. template <typename T>
  103. struct has_overloaded_addressof {
  104. template <class X>
  105. constexpr static bool has_overload(...) {
  106. return false;
  107. }
  108. template <class X, size_t S = sizeof(std::declval<X&>().operator&())>
  109. constexpr static bool has_overload(bool) {
  110. return true;
  111. }
  112. constexpr static bool value = has_overload<T>(true);
  113. };
  114. template <typename T, TR2_OPTIONAL_REQUIRES(!has_overloaded_addressof<T>)>
  115. constexpr T* static_addressof(T& ref) {
  116. return &ref;
  117. }
  118. template <typename T, TR2_OPTIONAL_REQUIRES(has_overloaded_addressof<T>)>
  119. T* static_addressof(T& ref) {
  120. return std::addressof(ref);
  121. }
  122. #endif
  123. // the call to convert<A>(b) has return type A and converts b to type A iff b
  124. // decltype(b) is implicitly convertible to A
  125. template <class U>
  126. constexpr U convert(U v) {
  127. return v;
  128. }
  129. } // namespace detail_
  130. // \endcond
  131. constexpr struct trivial_init_t {
  132. } trivial_init{};
  133. // 20.5.7, Disengaged state indicator
  134. struct nullopt_t {
  135. constexpr explicit nullopt_t(int) {}
  136. };
  137. constexpr nullopt_t nullopt{0};
  138. // 20.5.8, class bad_optional_access
  139. class bad_optional_access : public std::logic_error {
  140. public:
  141. explicit bad_optional_access(const std::string& what_arg)
  142. : logic_error{what_arg} {}
  143. explicit bad_optional_access(const char* what_arg) : logic_error{what_arg} {}
  144. };
  145. template <class T>
  146. union storage_t {
  147. unsigned char dummy_{};
  148. T value_;
  149. #if __cplusplus >= 202002L
  150. constexpr
  151. #endif
  152. storage_t(trivial_init_t) noexcept {
  153. new (&dummy_) unsigned char;
  154. }
  155. template <class... Args>
  156. constexpr storage_t(Args&&... args)
  157. : value_(constexpr_forward<Args>(args)...) {}
  158. ~storage_t() {}
  159. };
  160. template <class T>
  161. union constexpr_storage_t {
  162. unsigned char dummy_;
  163. T value_;
  164. #if __cplusplus >= 202002L
  165. // C++20 lifted the requirement to initialize a union member in order to be
  166. // constexpr.
  167. constexpr constexpr_storage_t(trivial_init_t) noexcept {
  168. new (&dummy_) unsigned char;
  169. }
  170. #else
  171. constexpr constexpr_storage_t(trivial_init_t) noexcept : dummy_() {}
  172. #endif
  173. template <class... Args>
  174. constexpr constexpr_storage_t(Args&&... args)
  175. : value_(constexpr_forward<Args>(args)...) {}
  176. ~constexpr_storage_t() = default;
  177. };
  178. template <class T>
  179. struct optional_base {
  180. bool init_;
  181. storage_t<T> storage_;
  182. constexpr optional_base() noexcept : init_(false), storage_(trivial_init){};
  183. explicit constexpr optional_base(const optional_base<T>& v)
  184. : init_(v.init_), storage_(trivial_init) {
  185. if (init_) {
  186. ::new (dataptr()) T(v.storage_.value_);
  187. }
  188. }
  189. explicit constexpr optional_base(const T& v) : init_(true), storage_(v) {}
  190. explicit constexpr optional_base(optional_base<T>&& v) noexcept(
  191. std::is_nothrow_move_constructible<T>::value)
  192. : init_(v.init_), storage_(trivial_init) {
  193. if (init_) {
  194. ::new (dataptr()) T(std::move(v.storage_.value_));
  195. }
  196. }
  197. explicit constexpr optional_base(T&& v)
  198. : init_(true), storage_(constexpr_move(v)) {}
  199. template <class... Args>
  200. explicit optional_base(in_place_t, Args&&... args)
  201. : init_(true), storage_(constexpr_forward<Args>(args)...) {}
  202. template <
  203. class U,
  204. class... Args,
  205. TR2_OPTIONAL_REQUIRES(std::is_constructible<T, std::initializer_list<U>>)>
  206. explicit optional_base(
  207. in_place_t,
  208. std::initializer_list<U> il,
  209. Args&&... args)
  210. : init_(true), storage_(il, std::forward<Args>(args)...) {}
  211. optional_base& operator=(const optional_base& rhs) {
  212. if (init_ && !rhs.init_) {
  213. clear();
  214. } else if (!init_ && rhs.init_) {
  215. init_ = true;
  216. ::new (dataptr()) T(rhs.storage_.value_);
  217. } else if (init_ && rhs.init_) {
  218. storage_.value_ = rhs.storage_.value_;
  219. }
  220. return *this;
  221. }
  222. optional_base& operator=(optional_base&& rhs) noexcept(
  223. std::is_nothrow_move_assignable<T>::value&&
  224. std::is_nothrow_move_constructible<T>::value) {
  225. if (init_ && !rhs.init_) {
  226. clear();
  227. } else if (!init_ && rhs.init_) {
  228. init_ = true;
  229. ::new (dataptr()) T(std::move(rhs.storage_.value_));
  230. } else if (init_ && rhs.init_) {
  231. storage_.value_ = std::move(rhs.storage_.value_);
  232. }
  233. return *this;
  234. }
  235. ~optional_base() {
  236. if (init_)
  237. storage_.value_.T::~T();
  238. }
  239. constexpr bool initialized() const noexcept {
  240. return init_;
  241. }
  242. void setInitialized(bool init) noexcept {
  243. init_ = init;
  244. }
  245. private:
  246. typename std::remove_const<T>::type* dataptr() {
  247. return std::addressof(storage_.value_);
  248. }
  249. constexpr const T* dataptr() const {
  250. return detail_::static_addressof(storage_.value_);
  251. }
  252. void clear() noexcept {
  253. if (init_) {
  254. dataptr()->~T();
  255. }
  256. init_ = false;
  257. }
  258. };
  259. template <class T>
  260. struct constexpr_optional_base {
  261. bool init_;
  262. constexpr_storage_t<T> storage_;
  263. constexpr constexpr_optional_base() noexcept
  264. : init_(false), storage_(trivial_init){};
  265. explicit constexpr constexpr_optional_base(
  266. const constexpr_optional_base<T>& v)
  267. : init_(v.init_), storage_(trivial_init) {
  268. if (init_) {
  269. ::new (dataptr()) T(v.storage_.value_);
  270. }
  271. }
  272. explicit constexpr constexpr_optional_base(
  273. constexpr_optional_base<T>&&
  274. v) noexcept(std::is_nothrow_move_constructible<T>::value)
  275. : init_(v.init_), storage_(trivial_init) {
  276. if (init_) {
  277. ::new (dataptr()) T(std::move(v.storage_.value_));
  278. }
  279. }
  280. explicit constexpr constexpr_optional_base(const T& v)
  281. : init_(true), storage_(v) {}
  282. explicit constexpr constexpr_optional_base(T&& v)
  283. : init_(true), storage_(constexpr_move(v)) {}
  284. template <class... Args>
  285. explicit constexpr constexpr_optional_base(in_place_t, Args&&... args)
  286. : init_(true), storage_(constexpr_forward<Args>(args)...) {}
  287. template <
  288. class U,
  289. class... Args,
  290. TR2_OPTIONAL_REQUIRES(std::is_constructible<T, std::initializer_list<U>>)>
  291. constexpr explicit constexpr_optional_base(
  292. in_place_t,
  293. std::initializer_list<U> il,
  294. Args&&... args)
  295. : init_(true), storage_(il, std::forward<Args>(args)...) {}
  296. ~constexpr_optional_base() = default;
  297. constexpr_optional_base& operator=(const constexpr_optional_base& rhs) {
  298. if (init_ && !rhs.init_) {
  299. clear();
  300. } else if (!init_ && rhs.init_) {
  301. init_ = true;
  302. ::new (dataptr()) T(rhs.storage_.value_);
  303. } else if (init_ && rhs.init_) {
  304. storage_.value_ = rhs.storage_.value_;
  305. }
  306. return *this;
  307. }
  308. constexpr_optional_base& operator=(constexpr_optional_base&& rhs) noexcept(
  309. std::is_nothrow_move_assignable<T>::value&&
  310. std::is_nothrow_move_constructible<T>::value) {
  311. if (init_ && !rhs.init_) {
  312. clear();
  313. } else if (!init_ && rhs.init_) {
  314. init_ = true;
  315. ::new (dataptr()) T(std::move(rhs.storage_.value_));
  316. } else if (init_ && rhs.init_) {
  317. storage_.value_ = std::move(rhs.storage_.value_);
  318. }
  319. return *this;
  320. }
  321. constexpr bool initialized() const noexcept {
  322. return init_;
  323. }
  324. void setInitialized(bool init) noexcept {
  325. init_ = init;
  326. }
  327. private:
  328. typename std::remove_const<T>::type* dataptr() {
  329. return std::addressof(storage_.value_);
  330. }
  331. constexpr const T* dataptr() const {
  332. return detail_::static_addressof(storage_.value_);
  333. }
  334. void clear() noexcept {
  335. init_ = false;
  336. }
  337. };
  338. // HACK: Optimization for trivially copyable types. The mainline
  339. // implementation fails to have trivial copy/move operations in these
  340. // cases, and we care about them, so just implement that directly.
  341. template <class T>
  342. struct trivially_copyable_optimization_optional_base {
  343. bool init_;
  344. constexpr_storage_t<T> storage_;
  345. constexpr trivially_copyable_optimization_optional_base() noexcept
  346. : init_(false), storage_(trivial_init) {}
  347. explicit constexpr trivially_copyable_optimization_optional_base(const T& v)
  348. : init_(true), storage_(v) {}
  349. explicit constexpr trivially_copyable_optimization_optional_base(T&& v)
  350. : init_(true), storage_(constexpr_move(v)) {}
  351. template <class... Args>
  352. explicit constexpr trivially_copyable_optimization_optional_base(
  353. in_place_t,
  354. Args&&... args)
  355. : init_(true), storage_(constexpr_forward<Args>(args)...) {}
  356. template <
  357. class U,
  358. class... Args,
  359. TR2_OPTIONAL_REQUIRES(std::is_constructible<T, std::initializer_list<U>>)>
  360. constexpr explicit trivially_copyable_optimization_optional_base(
  361. in_place_t,
  362. std::initializer_list<U> il,
  363. Args&&... args)
  364. : init_(true), storage_(il, std::forward<Args>(args)...) {}
  365. ~trivially_copyable_optimization_optional_base() = default;
  366. constexpr bool initialized() const noexcept {
  367. return init_;
  368. }
  369. void setInitialized(bool init) noexcept {
  370. init_ = init;
  371. }
  372. };
  373. // HACK: Optimization for ArrayRef<T>. We take advantage of an unused
  374. // bit pattern in ArrayRef (inspired by Arthur O'Dwyer's
  375. // tombstone_traits -- see https://youtu.be/MWBfmmg8-Yo?t=2466) to
  376. // keep the size of c10::optional::ArrayRef<T> down to 16 bytes, which
  377. // allows it to be passed to functions in registers instead of getting
  378. // passed in memory per item 5c of the classification algorithm in
  379. // section 3.2.3 of the System V ABI document
  380. // (https://www.uclibc.org/docs/psABI-x86_64.pdf).
  381. template <class ArrayRefT>
  382. class arrayref_optional_base {
  383. public:
  384. union storage {
  385. struct raw {
  386. // ArrayRef has the invariant that if Data is nullptr then
  387. // Length must be zero, so this is an unused bit pattern.
  388. const void* p = nullptr;
  389. size_t sz = 1;
  390. } uninitialized_{};
  391. ArrayRefT value_;
  392. constexpr storage() noexcept : uninitialized_() {
  393. setUninitialized();
  394. }
  395. constexpr void setUninitialized() noexcept {
  396. uninitialized_.p = nullptr;
  397. uninitialized_.sz = 1;
  398. }
  399. explicit constexpr storage(ArrayRefT& v) : value_(v) {}
  400. template <typename T>
  401. explicit constexpr storage(const std::initializer_list<T>& v) : value_(v) {}
  402. template <class... Args>
  403. explicit constexpr storage(Args&&... args)
  404. : value_(constexpr_forward<Args>(args)...) {}
  405. };
  406. storage storage_;
  407. constexpr arrayref_optional_base() noexcept = default;
  408. explicit constexpr arrayref_optional_base(const ArrayRefT& v) : storage_(v) {}
  409. template <class... Args>
  410. explicit constexpr arrayref_optional_base(in_place_t, Args&&... args)
  411. : storage_(constexpr_forward<Args>(args)...) {}
  412. template <typename T>
  413. explicit constexpr arrayref_optional_base(
  414. in_place_t,
  415. const std::initializer_list<T>& v)
  416. : storage_(v) {}
  417. constexpr bool initialized() const noexcept {
  418. return storage_.uninitialized_.p != nullptr ||
  419. storage_.uninitialized_.sz == 0;
  420. }
  421. void setInitialized(bool init) noexcept {
  422. if (!init) {
  423. storage_.setUninitialized();
  424. } else {
  425. assert(initialized());
  426. }
  427. }
  428. };
  429. namespace detail_ {
  430. template <typename T>
  431. struct is_arrayref : std::false_type {};
  432. template <typename T>
  433. struct is_arrayref<c10::ArrayRef<T>> : std::true_type {};
  434. } // namespace detail_
  435. template <class T>
  436. using OptionalBase = std::conditional_t<
  437. detail_::is_arrayref<T>::value,
  438. arrayref_optional_base<T>,
  439. std::conditional_t<
  440. std::is_trivially_destructible<T>::value &&
  441. C10_IS_TRIVIALLY_COPYABLE(T) &&
  442. // Avoid using is_trivially_copy_{constructible,assignable}
  443. // because old GCC versions don't support them. Also,
  444. // is_trivially_copyable seems not to do what I expect, so check
  445. // trivially_copyable_optimization_optional_base directly.
  446. std::is_copy_constructible<
  447. trivially_copyable_optimization_optional_base<T>>::value &&
  448. std::is_copy_assignable<
  449. trivially_copyable_optimization_optional_base<T>>::value,
  450. trivially_copyable_optimization_optional_base<T>,
  451. std::conditional_t<
  452. std::is_trivially_destructible<T>::value, // if possible
  453. constexpr_optional_base<std::remove_const_t<T>>, // use base with
  454. // trivial
  455. // destructor
  456. optional_base<std::remove_const_t<T>>>>>;
  457. template <class T>
  458. class optional : private OptionalBase<T> {
  459. template <class U> // re-declaration for nvcc on Windows.
  460. using OptionalBase = std::conditional_t<
  461. detail_::is_arrayref<U>::value,
  462. arrayref_optional_base<U>,
  463. std::conditional_t<
  464. std::is_trivially_destructible<U>::value &&
  465. C10_IS_TRIVIALLY_COPYABLE(U) &&
  466. // Avoid using is_trivially_copy_{constructible,assignable}
  467. // because old GCC versions don't support them. Also,
  468. // is_trivially_copyable seems not to do what I expect, so
  469. // check trivially_copyable_optimization_optional_base
  470. // directly.
  471. std::is_copy_constructible<
  472. trivially_copyable_optimization_optional_base<U>>::value &&
  473. std::is_copy_assignable<
  474. trivially_copyable_optimization_optional_base<U>>::value,
  475. trivially_copyable_optimization_optional_base<U>,
  476. std::conditional_t<
  477. std::is_trivially_destructible<U>::value, // if possible
  478. constexpr_optional_base<std::remove_const_t<U>>, // use base
  479. // with
  480. // trivial
  481. // destructor
  482. optional_base<std::remove_const_t<U>>>>>;
  483. static_assert(
  484. !std::is_same<typename std::decay<T>::type, nullopt_t>::value,
  485. "bad T");
  486. static_assert(
  487. !std::is_same<typename std::decay<T>::type, in_place_t>::value,
  488. "bad T");
  489. constexpr bool initialized() const noexcept {
  490. return OptionalBase<T>::initialized();
  491. }
  492. typename std::remove_const<T>::type* dataptr() {
  493. return std::addressof(OptionalBase<T>::storage_.value_);
  494. }
  495. constexpr const T* dataptr() const {
  496. return detail_::static_addressof(OptionalBase<T>::storage_.value_);
  497. }
  498. constexpr const T& contained_val() const& {
  499. return OptionalBase<T>::storage_.value_;
  500. }
  501. constexpr T&& contained_val() && {
  502. return std::move(OptionalBase<T>::storage_.value_);
  503. }
  504. constexpr T& contained_val() & {
  505. return OptionalBase<T>::storage_.value_;
  506. }
  507. void clear() noexcept {
  508. if (initialized())
  509. dataptr()->~T();
  510. OptionalBase<T>::setInitialized(false);
  511. }
  512. template <class... Args>
  513. void initialize(Args&&... args) noexcept(
  514. noexcept(T(std::forward<Args>(args)...))) {
  515. assert(!initialized());
  516. ::new (static_cast<void*>(dataptr())) T(std::forward<Args>(args)...);
  517. OptionalBase<T>::setInitialized(true);
  518. }
  519. template <class U, class... Args>
  520. void initialize(std::initializer_list<U> il, Args&&... args) noexcept(
  521. noexcept(T(il, std::forward<Args>(args)...))) {
  522. assert(!initialized());
  523. ::new (static_cast<void*>(dataptr())) T(il, std::forward<Args>(args)...);
  524. OptionalBase<T>::setInitialized(true);
  525. }
  526. public:
  527. typedef T value_type;
  528. // 20.5.5.1, constructors
  529. constexpr optional() noexcept = default;
  530. constexpr optional(nullopt_t) noexcept : OptionalBase<T>(){};
  531. optional(const optional& rhs) = default;
  532. optional(optional&& rhs) = default;
  533. // see https://github.com/akrzemi1/Optional/issues/16
  534. // and https://en.cppreference.com/w/cpp/utility/optional/optional,
  535. // in constructor 8, the std::optional spec can allow initialization
  536. // of optionals from convertible type U
  537. //
  538. // 8 - implicit move construct from value
  539. template <
  540. typename U = T,
  541. TR2_OPTIONAL_REQUIRES(
  542. std::is_constructible<T, U&&>::value &&
  543. !std::is_same<typename std::decay<U>::type, in_place_t>::value &&
  544. !std::is_same<typename std::decay<U>::type, optional<T>>::value &&
  545. std::is_convertible<U&&, T>)>
  546. constexpr optional(U&& u) : OptionalBase<T>(std::forward<U>(u)) {}
  547. // 8 - explicit move construct from value
  548. template <
  549. typename U = T,
  550. TR2_OPTIONAL_REQUIRES(
  551. std::is_constructible<T, U&&>::value &&
  552. !std::is_same<typename std::decay<U>::type, in_place_t>::value &&
  553. !std::is_same<typename std::decay<U>::type, optional<T>>::value &&
  554. !std::is_convertible<U&&, T>)>
  555. explicit constexpr optional(U&& u) : OptionalBase<T>(std::forward<U>(u)) {}
  556. template <class... Args>
  557. explicit constexpr optional(in_place_t, Args&&... args)
  558. : OptionalBase<T>(in_place_t{}, constexpr_forward<Args>(args)...) {}
  559. template <
  560. class U,
  561. class... Args,
  562. TR2_OPTIONAL_REQUIRES(std::is_constructible<T, std::initializer_list<U>>)>
  563. constexpr explicit optional(
  564. in_place_t,
  565. std::initializer_list<U> il,
  566. Args&&... args)
  567. : OptionalBase<T>(in_place_t{}, il, constexpr_forward<Args>(args)...) {}
  568. // 20.5.4.2, Destructor
  569. ~optional() = default;
  570. // 20.5.4.3, assignment
  571. optional& operator=(nullopt_t) noexcept {
  572. clear();
  573. return *this;
  574. }
  575. optional& operator=(const optional& rhs) = default;
  576. optional& operator=(optional&& rhs) = default;
  577. template <class U = T>
  578. auto operator=(U&& v) -> typename std::enable_if<
  579. std::is_constructible<T, U>::value &&
  580. !std::is_same<typename std::decay<U>::type, optional<T>>::value &&
  581. (std::is_scalar<T>::value ||
  582. std::is_same<typename std::decay<U>::type, T>::value) &&
  583. std::is_assignable<T&, U>::value,
  584. optional&>::type {
  585. if (initialized()) {
  586. contained_val() = std::forward<U>(v);
  587. } else {
  588. initialize(std::forward<U>(v));
  589. }
  590. return *this;
  591. }
  592. template <class... Args>
  593. void emplace(Args&&... args) {
  594. clear();
  595. initialize(std::forward<Args>(args)...);
  596. }
  597. template <class U, class... Args>
  598. void emplace(std::initializer_list<U> il, Args&&... args) {
  599. clear();
  600. initialize<U, Args...>(il, std::forward<Args>(args)...);
  601. }
  602. // 20.5.4.4, Swap
  603. void swap(optional<T>& rhs) noexcept(
  604. std::is_nothrow_move_constructible<T>::value&& noexcept(
  605. std::swap(std::declval<T&>(), std::declval<T&>()))) {
  606. if (initialized() == true && rhs.initialized() == false) {
  607. rhs.initialize(std::move(**this));
  608. clear();
  609. } else if (initialized() == false && rhs.initialized() == true) {
  610. initialize(std::move(*rhs));
  611. rhs.clear();
  612. } else if (initialized() == true && rhs.initialized() == true) {
  613. using std::swap;
  614. swap(**this, *rhs);
  615. }
  616. }
  617. // 20.5.4.5, Observers
  618. explicit constexpr operator bool() const noexcept {
  619. return initialized();
  620. }
  621. constexpr bool has_value() const noexcept {
  622. return initialized();
  623. }
  624. TR2_OPTIONAL_HOST_CONSTEXPR T const* operator->() const {
  625. return TR2_OPTIONAL_ASSERTED_EXPRESSION(initialized(), dataptr());
  626. }
  627. TR2_OPTIONAL_HOST_CONSTEXPR T* operator->() {
  628. assert(initialized());
  629. return dataptr();
  630. }
  631. TR2_OPTIONAL_HOST_CONSTEXPR T const& operator*() const& {
  632. return TR2_OPTIONAL_ASSERTED_EXPRESSION(initialized(), contained_val());
  633. }
  634. TR2_OPTIONAL_HOST_CONSTEXPR T& operator*() & {
  635. assert(initialized());
  636. return contained_val();
  637. }
  638. TR2_OPTIONAL_HOST_CONSTEXPR T&& operator*() && {
  639. assert(initialized());
  640. return constexpr_move(contained_val());
  641. }
  642. TR2_OPTIONAL_HOST_CONSTEXPR T const& value() const& {
  643. return initialized()
  644. ? contained_val()
  645. : (throw bad_optional_access("bad optional access"), contained_val());
  646. }
  647. TR2_OPTIONAL_HOST_CONSTEXPR T& value() & {
  648. return initialized()
  649. ? contained_val()
  650. : (throw bad_optional_access("bad optional access"), contained_val());
  651. }
  652. TR2_OPTIONAL_HOST_CONSTEXPR T&& value() && {
  653. if (!initialized())
  654. throw bad_optional_access("bad optional access");
  655. return std::move(contained_val());
  656. }
  657. template <class V>
  658. constexpr T value_or(V&& v) const& {
  659. return *this ? **this : detail_::convert<T>(constexpr_forward<V>(v));
  660. }
  661. template <class V>
  662. constexpr T value_or(V&& v) && {
  663. return *this
  664. ? constexpr_move(const_cast<optional<T>&>(*this).contained_val())
  665. : detail_::convert<T>(constexpr_forward<V>(v));
  666. }
  667. // 20.6.3.6, modifiers
  668. void reset() noexcept {
  669. clear();
  670. }
  671. };
  672. template <class T, class F>
  673. constexpr T value_or_else(const optional<T>& v, F&& func) {
  674. static_assert(
  675. std::is_convertible<
  676. typename guts::infer_function_traits_t<F>::return_type,
  677. T>::value,
  678. "func parameters must be a callable that returns a type convertible to the value stored in the optional");
  679. return v.has_value() ? *v : detail_::convert<T>(std::forward<F>(func)());
  680. }
  681. template <class T, class F>
  682. constexpr T value_or_else(optional<T>&& v, F&& func) {
  683. static_assert(
  684. std::is_convertible<
  685. typename guts::infer_function_traits_t<F>::return_type,
  686. T>::value,
  687. "func parameters must be a callable that returns a type convertible to the value stored in the optional");
  688. return v.has_value() ? constexpr_move(std::move(v).contained_val())
  689. : detail_::convert<T>(std::forward<F>(func)());
  690. }
  691. // XXX: please refrain from using optional<T&>, since it is being against with
  692. // the optional standard in c++ 17, see the debate and the details here:
  693. // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3406#rationale.refs
  694. // if you need it, consider using optional<std::reference_wrapper<T>> or *
  695. // pointer
  696. //
  697. // we leave the implementation here in case we want to reconsider using it in
  698. // the future if it becomes a definitely necessary case.
  699. template <class T>
  700. class optional<T&> {
  701. // add this assert to prevent user from using optional reference as indicated
  702. // above
  703. static_assert(
  704. sizeof(T) == 0,
  705. "optional references is ill-formed, \
  706. consider use optional of a std::reference_wrapper of type T to \
  707. hold a reference if you really need to");
  708. static_assert(!std::is_same<T, nullopt_t>::value, "bad T");
  709. static_assert(!std::is_same<T, in_place_t>::value, "bad T");
  710. T* ref;
  711. public:
  712. // 20.5.5.1, construction/destruction
  713. constexpr optional() noexcept : ref(nullptr) {}
  714. constexpr optional(nullopt_t) noexcept : ref(nullptr) {}
  715. template <typename U = T>
  716. constexpr optional(U& u) noexcept : ref(detail_::static_addressof(u)) {}
  717. template <typename U = T>
  718. optional(U&&) = delete;
  719. constexpr optional(const optional& rhs) noexcept : ref(rhs.ref) {}
  720. explicit constexpr optional(in_place_t, T& v) noexcept
  721. : ref(detail_::static_addressof(v)) {}
  722. explicit optional(in_place_t, T&&) = delete;
  723. ~optional() = default;
  724. // 20.5.5.2, mutation
  725. optional& operator=(nullopt_t) noexcept {
  726. ref = nullptr;
  727. return *this;
  728. }
  729. // optional& operator=(const optional& rhs) noexcept {
  730. // ref = rhs.ref;
  731. // return *this;
  732. // }
  733. // optional& operator=(optional&& rhs) noexcept {
  734. // ref = rhs.ref;
  735. // return *this;
  736. // }
  737. template <typename U>
  738. auto operator=(U&& rhs) noexcept -> typename std::enable_if<
  739. std::is_same<typename std::decay<U>::type, optional<T&>>::value,
  740. optional&>::type {
  741. ref = rhs.ref;
  742. return *this;
  743. }
  744. template <typename U>
  745. auto operator=(U&& rhs) noexcept -> typename std::enable_if<
  746. !std::is_same<typename std::decay<U>::type, optional<T&>>::value,
  747. optional&>::type = delete;
  748. void emplace(T& v) noexcept {
  749. ref = detail_::static_addressof(v);
  750. }
  751. void emplace(T&&) = delete;
  752. void swap(optional<T&>& rhs) noexcept {
  753. std::swap(ref, rhs.ref);
  754. }
  755. // 20.5.5.3, observers
  756. TR2_OPTIONAL_HOST_CONSTEXPR T* operator->() const {
  757. return TR2_OPTIONAL_ASSERTED_EXPRESSION(ref, ref);
  758. }
  759. TR2_OPTIONAL_HOST_CONSTEXPR T& operator*() const {
  760. return TR2_OPTIONAL_ASSERTED_EXPRESSION(ref, *ref);
  761. }
  762. constexpr T& value() const {
  763. return ref ? *ref
  764. : (throw bad_optional_access("bad optional access"), *ref);
  765. }
  766. explicit constexpr operator bool() const noexcept {
  767. return ref != nullptr;
  768. }
  769. constexpr bool has_value() const noexcept {
  770. return ref != nullptr;
  771. }
  772. template <class V>
  773. constexpr typename std::decay<T>::type value_or(V&& v) const {
  774. return *this ? **this
  775. : detail_::convert<typename std::decay<T>::type>(
  776. constexpr_forward<V>(v));
  777. }
  778. // x.x.x.x, modifiers
  779. void reset() noexcept {
  780. ref = nullptr;
  781. }
  782. };
  783. template <class T>
  784. class optional<T&&> {
  785. static_assert(sizeof(T) == 0, "optional rvalue references disallowed");
  786. };
  787. // 20.5.8, Relational operators
  788. template <class T>
  789. constexpr bool operator==(const optional<T>& x, const optional<T>& y) {
  790. return bool(x) != bool(y) ? false : bool(x) == false ? true : *x == *y;
  791. }
  792. template <class T>
  793. constexpr bool operator!=(const optional<T>& x, const optional<T>& y) {
  794. return !(x == y);
  795. }
  796. template <class T>
  797. constexpr bool operator<(const optional<T>& x, const optional<T>& y) {
  798. return (!y) ? false : (!x) ? true : *x < *y;
  799. }
  800. template <class T>
  801. constexpr bool operator>(const optional<T>& x, const optional<T>& y) {
  802. return (y < x);
  803. }
  804. template <class T>
  805. constexpr bool operator<=(const optional<T>& x, const optional<T>& y) {
  806. return !(y < x);
  807. }
  808. template <class T>
  809. constexpr bool operator>=(const optional<T>& x, const optional<T>& y) {
  810. return !(x < y);
  811. }
  812. // 20.5.9, Comparison with nullopt
  813. template <class T>
  814. constexpr bool operator==(const optional<T>& x, nullopt_t) noexcept {
  815. return (!x);
  816. }
  817. template <class T>
  818. constexpr bool operator==(nullopt_t, const optional<T>& x) noexcept {
  819. return (!x);
  820. }
  821. template <class T>
  822. constexpr bool operator!=(const optional<T>& x, nullopt_t) noexcept {
  823. return bool(x);
  824. }
  825. template <class T>
  826. constexpr bool operator!=(nullopt_t, const optional<T>& x) noexcept {
  827. return bool(x);
  828. }
  829. template <class T>
  830. constexpr bool operator<(const optional<T>&, nullopt_t) noexcept {
  831. return false;
  832. }
  833. template <class T>
  834. constexpr bool operator<(nullopt_t, const optional<T>& x) noexcept {
  835. return bool(x);
  836. }
  837. template <class T>
  838. constexpr bool operator<=(const optional<T>& x, nullopt_t) noexcept {
  839. return (!x);
  840. }
  841. template <class T>
  842. constexpr bool operator<=(nullopt_t, const optional<T>&) noexcept {
  843. return true;
  844. }
  845. template <class T>
  846. constexpr bool operator>(const optional<T>& x, nullopt_t) noexcept {
  847. return bool(x);
  848. }
  849. template <class T>
  850. constexpr bool operator>(nullopt_t, const optional<T>&) noexcept {
  851. return false;
  852. }
  853. template <class T>
  854. constexpr bool operator>=(const optional<T>&, nullopt_t) noexcept {
  855. return true;
  856. }
  857. template <class T>
  858. constexpr bool operator>=(nullopt_t, const optional<T>& x) noexcept {
  859. return (!x);
  860. }
  861. // 20.5.10, Comparison with T
  862. template <class T, class U>
  863. constexpr bool operator==(const optional<T>& x, const U& v) {
  864. return bool(x) ? *x == v : false;
  865. }
  866. template <class T, class U>
  867. constexpr bool operator==(const U& v, const optional<T>& x) {
  868. return bool(x) ? v == *x : false;
  869. }
  870. template <class T, class U>
  871. constexpr bool operator!=(const optional<T>& x, const U& v) {
  872. return bool(x) ? *x != v : true;
  873. }
  874. template <class T, class U>
  875. constexpr bool operator!=(const U& v, const optional<T>& x) {
  876. return bool(x) ? v != *x : true;
  877. }
  878. template <class T, class U>
  879. constexpr bool operator<(const optional<T>& x, const U& v) {
  880. return bool(x) ? *x < v : true;
  881. }
  882. template <class T, class U>
  883. constexpr bool operator>(const U& v, const optional<T>& x) {
  884. return bool(x) ? v > *x : true;
  885. }
  886. template <class T, class U>
  887. constexpr bool operator>(const optional<T>& x, const U& v) {
  888. return bool(x) ? *x > v : false;
  889. }
  890. template <class T, class U>
  891. constexpr bool operator<(const U& v, const optional<T>& x) {
  892. return bool(x) ? v < *x : false;
  893. }
  894. template <class T, class U>
  895. constexpr bool operator>=(const optional<T>& x, const U& v) {
  896. return bool(x) ? *x >= v : false;
  897. }
  898. template <class T, class U>
  899. constexpr bool operator<=(const U& v, const optional<T>& x) {
  900. return bool(x) ? v <= *x : false;
  901. }
  902. template <class T, class U>
  903. constexpr bool operator<=(const optional<T>& x, const U& v) {
  904. return bool(x) ? *x <= v : true;
  905. }
  906. template <class T, class U>
  907. constexpr bool operator>=(const U& v, const optional<T>& x) {
  908. return bool(x) ? v >= *x : true;
  909. }
  910. // Comparison of optional<T&> with T
  911. template <class T>
  912. constexpr bool operator==(const optional<T&>& x, const T& v) {
  913. return bool(x) ? *x == v : false;
  914. }
  915. template <class T>
  916. constexpr bool operator==(const T& v, const optional<T&>& x) {
  917. return bool(x) ? v == *x : false;
  918. }
  919. template <class T>
  920. constexpr bool operator!=(const optional<T&>& x, const T& v) {
  921. return bool(x) ? *x != v : true;
  922. }
  923. template <class T>
  924. constexpr bool operator!=(const T& v, const optional<T&>& x) {
  925. return bool(x) ? v != *x : true;
  926. }
  927. template <class T>
  928. constexpr bool operator<(const optional<T&>& x, const T& v) {
  929. return bool(x) ? *x < v : true;
  930. }
  931. template <class T>
  932. constexpr bool operator>(const T& v, const optional<T&>& x) {
  933. return bool(x) ? v > *x : true;
  934. }
  935. template <class T>
  936. constexpr bool operator>(const optional<T&>& x, const T& v) {
  937. return bool(x) ? *x > v : false;
  938. }
  939. template <class T>
  940. constexpr bool operator<(const T& v, const optional<T&>& x) {
  941. return bool(x) ? v < *x : false;
  942. }
  943. template <class T>
  944. constexpr bool operator>=(const optional<T&>& x, const T& v) {
  945. return bool(x) ? *x >= v : false;
  946. }
  947. template <class T>
  948. constexpr bool operator<=(const T& v, const optional<T&>& x) {
  949. return bool(x) ? v <= *x : false;
  950. }
  951. template <class T>
  952. constexpr bool operator<=(const optional<T&>& x, const T& v) {
  953. return bool(x) ? *x <= v : true;
  954. }
  955. template <class T>
  956. constexpr bool operator>=(const T& v, const optional<T&>& x) {
  957. return bool(x) ? v >= *x : true;
  958. }
  959. // Comparison of optional<T const&> with T
  960. template <class T>
  961. constexpr bool operator==(const optional<const T&>& x, const T& v) {
  962. return bool(x) ? *x == v : false;
  963. }
  964. template <class T>
  965. constexpr bool operator==(const T& v, const optional<const T&>& x) {
  966. return bool(x) ? v == *x : false;
  967. }
  968. template <class T>
  969. constexpr bool operator!=(const optional<const T&>& x, const T& v) {
  970. return bool(x) ? *x != v : true;
  971. }
  972. template <class T>
  973. constexpr bool operator!=(const T& v, const optional<const T&>& x) {
  974. return bool(x) ? v != *x : true;
  975. }
  976. template <class T>
  977. constexpr bool operator<(const optional<const T&>& x, const T& v) {
  978. return bool(x) ? *x < v : true;
  979. }
  980. template <class T>
  981. constexpr bool operator>(const T& v, const optional<const T&>& x) {
  982. return bool(x) ? v > *x : true;
  983. }
  984. template <class T>
  985. constexpr bool operator>(const optional<const T&>& x, const T& v) {
  986. return bool(x) ? *x > v : false;
  987. }
  988. template <class T>
  989. constexpr bool operator<(const T& v, const optional<const T&>& x) {
  990. return bool(x) ? v < *x : false;
  991. }
  992. template <class T>
  993. constexpr bool operator>=(const optional<const T&>& x, const T& v) {
  994. return bool(x) ? *x >= v : false;
  995. }
  996. template <class T>
  997. constexpr bool operator<=(const T& v, const optional<const T&>& x) {
  998. return bool(x) ? v <= *x : false;
  999. }
  1000. template <class T>
  1001. constexpr bool operator<=(const optional<const T&>& x, const T& v) {
  1002. return bool(x) ? *x <= v : true;
  1003. }
  1004. template <class T>
  1005. constexpr bool operator>=(const T& v, const optional<const T&>& x) {
  1006. return bool(x) ? v >= *x : true;
  1007. }
  1008. // 20.5.12, Specialized algorithms
  1009. template <class T>
  1010. void swap(optional<T>& x, optional<T>& y) noexcept(noexcept(x.swap(y))) {
  1011. x.swap(y);
  1012. }
  1013. template <class T>
  1014. constexpr optional<typename std::decay<T>::type> make_optional(T&& v) {
  1015. return optional<typename std::decay<T>::type>(constexpr_forward<T>(v));
  1016. }
  1017. template <class X>
  1018. constexpr optional<X&> make_optional(std::reference_wrapper<X> v) {
  1019. return optional<X&>(v.get());
  1020. }
  1021. } // namespace c10
  1022. namespace std {
  1023. template <typename T>
  1024. struct hash<c10::optional<T>> {
  1025. typedef c10::invoke_result_t<std::hash<T>, T> result_type;
  1026. typedef c10::optional<T> argument_type;
  1027. constexpr result_type operator()(argument_type const& arg) const {
  1028. return arg ? std::hash<T>{}(*arg) : result_type{};
  1029. }
  1030. };
  1031. template <typename T>
  1032. struct hash<c10::optional<T&>> {
  1033. typedef typename hash<T>::result_type result_type;
  1034. typedef c10::optional<T&> argument_type;
  1035. constexpr result_type operator()(argument_type const& arg) const {
  1036. return arg ? std::hash<T>{}(*arg) : result_type{};
  1037. }
  1038. };
  1039. } // namespace std
  1040. #undef TR2_OPTIONAL_REQUIRES
  1041. #undef TR2_OPTIONAL_ASSERTED_EXPRESSION
  1042. #undef TR2_OPTIONAL_HOST_CONSTEXPR
  1043. C10_CLANG_DIAGNOSTIC_POP()
  1044. #endif // C10_UTIL_OPTIONAL_H_