Replaceable.h 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648
  1. /*
  2. * Copyright 2017-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. #pragma once
  17. #include <initializer_list>
  18. #include <new>
  19. #include <type_traits>
  20. #include <utility>
  21. #include <folly/Portability.h>
  22. #include <folly/Traits.h>
  23. #include <folly/Utility.h>
  24. #include <folly/lang/Launder.h>
  25. /**
  26. * An instance of `Replaceable<T>` wraps an instance of `T`.
  27. *
  28. * You access the inner `T` instance with `operator*` and `operator->` (as if
  29. * it were a smart pointer).
  30. *
  31. * `Replaceable<T>` adds no indirection cost and performs no allocations.
  32. *
  33. * `Replaceable<T>` has the same size and alignment as `T`.
  34. *
  35. * You can replace the `T` within a `Replaceable<T>` using the `emplace` method
  36. * (presuming that it is constructible and destructible without throwing
  37. * exceptions). If the destructor or constructor you're using could throw an
  38. * exception you should use `Optional<T>` instead, as it's not a logic error
  39. * for that to be empty.
  40. *
  41. * Frequently Asked Questions
  42. * ==========================
  43. *
  44. * Why does this need to be so complicated?
  45. * ----------------------------------------
  46. *
  47. * If a `T` instance contains `const`-qualified member variables or reference
  48. * member variables we can't safely replace a `T` instance by destructing it
  49. * manually and using placement new. This is because compilers are permitted to
  50. * assume that the `const` or reference members of a named, referenced, or
  51. * pointed-to object do not change.
  52. *
  53. * For pointed-to objects in allocated storage you can use the pointer returned
  54. * by placement new or use the `launder` function to get a pointer to the new
  55. * object. Note that `launder` doesn't affect its argument, it's still
  56. * undefined behaviour to use the original pointer. And none of this helps if
  57. * the object is a local or a member variable because the destructor call will
  58. * not have been laundered. In summary, this is the only way to use placement
  59. * new that is both simple and safe:
  60. *
  61. * T* pT = new T(...);
  62. * pT->~T();
  63. * pT = ::new (pT) T(...);
  64. * delete pT;
  65. *
  66. * What are the other safe solutions to this problem?
  67. * --------------------------------------------------
  68. *
  69. * * Ask the designer of `T` to de-`const` and -`reference` the members of `T`.
  70. * - Makes `T` harder to reason about
  71. * - Can reduce the performance of `T` methods
  72. * - They can refuse to make the change
  73. * * Put the `T` on the heap and use a raw/unique/shared pointer.
  74. * - Adds a level of indirection, costing performance.
  75. * - Harder to reason about your code as you need to check for nullptr.
  76. * * Put the `T` in an `Optional`.
  77. * - Harder to reason about your code as you need to check for None.
  78. * * Pass the problem on, making the new code also not-replaceable
  79. * - Contagion is not really a solution
  80. *
  81. * Are there downsides to this?
  82. * ----------------------------
  83. *
  84. * There is a potential performance penalty after converting `T` to
  85. * `Replaceable<T>` if you have non-`T`-member-function code which repeatedly
  86. * examines the value of a `const` or `reference` data member of `T`, because
  87. * the compiler now has to look at the value each time whereas previously it
  88. * was permitted to load it once up-front and presume that it could never
  89. * change.
  90. *
  91. * Usage notes
  92. * ===========
  93. *
  94. * Don't store a reference to the `T` within a `Replaceable<T>` unless you can
  95. * show that its lifetime does not cross an `emplace` call. For safety a
  96. * reasonable rule is to always use `operator*()` to get a fresh temporary each
  97. * time you need a `T&.
  98. *
  99. * If you store a pointer to the `T` within a `Replaceable<T>` you **must**
  100. * launder it after each call to `emplace` before using it. Again you can
  101. * reasonably choose to always use `operator->()` to get a fresh temporary each
  102. * time you need a `T*.
  103. *
  104. * Thus far I haven't thought of a good reason to use `Replaceable<T>` or
  105. * `Replaceable<T> const&` as a function parameter type.
  106. *
  107. * `Replaceable<T>&` can make sense to pass to a function that conditionally
  108. * replaces the `T`, where `T` has `const` or reference member variables.
  109. *
  110. * The main use of `Replaceable<T>` is as a class member type or a local type
  111. * in long-running functions.
  112. *
  113. * It's probably time to rethink your design choices if you end up with
  114. * `Replaceable<Replaceable<T>>`, `Optional<Replaceable<T>>`,
  115. * `Replaceable<Optional<T>>`, `unique_ptr<Replaceable<T>>` etc. except as a
  116. * result of template expansion.
  117. */
  118. namespace folly {
  119. template <class T>
  120. class Replaceable;
  121. namespace replaceable_detail {
  122. /* Mixin templates to give `replaceable<T>` the following properties:
  123. *
  124. * 1. Trivial destructor if `T` has a trivial destructor; user-provided
  125. * otherwise
  126. * 2. Move constructor if `T` has a move constructor; deleted otherwise
  127. * 3. Move assignment operator if `T` has a move constructor; deleted
  128. * otherwise
  129. * 4. Copy constructor if `T` has a copy constructor; deleted otherwise
  130. * 5. Copy assignment operator if `T` has a copy constructor; deleted
  131. * otherwise
  132. *
  133. * Has to be done in this way because we can't `enable_if` them away
  134. */
  135. template <
  136. class T,
  137. bool = std::is_destructible<T>::value,
  138. bool = std::is_trivially_destructible<T>::value>
  139. struct dtor_mixin;
  140. /* Destructible and trivially destructible */
  141. template <class T>
  142. struct dtor_mixin<T, true, true> {};
  143. /* Destructible and not trivially destructible */
  144. template <class T>
  145. struct dtor_mixin<T, true, false> {
  146. dtor_mixin() = default;
  147. dtor_mixin(dtor_mixin&&) = default;
  148. dtor_mixin(dtor_mixin const&) = default;
  149. dtor_mixin& operator=(dtor_mixin&&) = default;
  150. dtor_mixin& operator=(dtor_mixin const&) = default;
  151. ~dtor_mixin() noexcept(std::is_nothrow_destructible<T>::value) {
  152. T* destruct_ptr = launder(reinterpret_cast<T*>(
  153. reinterpret_cast<Replaceable<T>*>(this)->storage_));
  154. destruct_ptr->~T();
  155. }
  156. };
  157. /* Not destructible */
  158. template <class T, bool A>
  159. struct dtor_mixin<T, false, A> {
  160. dtor_mixin() = default;
  161. dtor_mixin(dtor_mixin&&) = default;
  162. dtor_mixin(dtor_mixin const&) = default;
  163. dtor_mixin& operator=(dtor_mixin&&) = default;
  164. dtor_mixin& operator=(dtor_mixin const&) = default;
  165. ~dtor_mixin() = delete;
  166. };
  167. template <
  168. class T,
  169. bool = std::is_default_constructible<T>::value,
  170. bool = std::is_move_constructible<T>::value>
  171. struct default_and_move_ctor_mixin;
  172. /* Not default-constructible and not move-constructible */
  173. template <class T>
  174. struct default_and_move_ctor_mixin<T, false, false> {
  175. default_and_move_ctor_mixin() = delete;
  176. default_and_move_ctor_mixin(default_and_move_ctor_mixin&&) = delete;
  177. default_and_move_ctor_mixin(default_and_move_ctor_mixin const&) = default;
  178. default_and_move_ctor_mixin& operator=(default_and_move_ctor_mixin&&) =
  179. default;
  180. default_and_move_ctor_mixin& operator=(default_and_move_ctor_mixin const&) =
  181. default;
  182. protected:
  183. inline explicit default_and_move_ctor_mixin(int) {}
  184. };
  185. /* Default-constructible and move-constructible */
  186. template <class T>
  187. struct default_and_move_ctor_mixin<T, true, true> {
  188. inline default_and_move_ctor_mixin() noexcept(
  189. std::is_nothrow_constructible<T>::value) {
  190. ::new (reinterpret_cast<Replaceable<T>*>(this)->storage_) T();
  191. }
  192. inline default_and_move_ctor_mixin(
  193. default_and_move_ctor_mixin&&
  194. other) noexcept(std::is_nothrow_constructible<T, T&&>::value) {
  195. ::new (reinterpret_cast<Replaceable<T>*>(this)->storage_)
  196. T(*std::move(reinterpret_cast<Replaceable<T>&>(other)));
  197. }
  198. default_and_move_ctor_mixin(default_and_move_ctor_mixin const&) = default;
  199. default_and_move_ctor_mixin& operator=(default_and_move_ctor_mixin&&) =
  200. default;
  201. inline default_and_move_ctor_mixin& operator=(
  202. default_and_move_ctor_mixin const&) = default;
  203. protected:
  204. inline explicit default_and_move_ctor_mixin(int) {}
  205. };
  206. /* Default-constructible and not move-constructible */
  207. template <class T>
  208. struct default_and_move_ctor_mixin<T, true, false> {
  209. inline default_and_move_ctor_mixin() noexcept(
  210. std::is_nothrow_constructible<T>::value) {
  211. ::new (reinterpret_cast<Replaceable<T>*>(this)->storage_) T();
  212. }
  213. default_and_move_ctor_mixin(default_and_move_ctor_mixin&&) = delete;
  214. default_and_move_ctor_mixin(default_and_move_ctor_mixin const&) = default;
  215. default_and_move_ctor_mixin& operator=(default_and_move_ctor_mixin&&) =
  216. default;
  217. default_and_move_ctor_mixin& operator=(default_and_move_ctor_mixin const&) =
  218. default;
  219. protected:
  220. inline explicit default_and_move_ctor_mixin(int) {}
  221. };
  222. /* Not default-constructible but is move-constructible */
  223. template <class T>
  224. struct default_and_move_ctor_mixin<T, false, true> {
  225. default_and_move_ctor_mixin() = delete;
  226. inline default_and_move_ctor_mixin(
  227. default_and_move_ctor_mixin&&
  228. other) noexcept(std::is_nothrow_constructible<T, T&&>::value) {
  229. ::new (reinterpret_cast<Replaceable<T>*>(this)->storage_)
  230. T(*std::move(reinterpret_cast<Replaceable<T>&>(other)));
  231. }
  232. default_and_move_ctor_mixin(default_and_move_ctor_mixin const&) = default;
  233. default_and_move_ctor_mixin& operator=(default_and_move_ctor_mixin&&) =
  234. default;
  235. default_and_move_ctor_mixin& operator=(default_and_move_ctor_mixin const&) =
  236. default;
  237. protected:
  238. inline explicit default_and_move_ctor_mixin(int) {}
  239. };
  240. template <
  241. class T,
  242. bool = (std::is_destructible<T>::value) &&
  243. (std::is_move_constructible<T>::value)>
  244. struct move_assignment_mixin;
  245. /* Not (destructible and move-constructible) */
  246. template <class T>
  247. struct move_assignment_mixin<T, false> {
  248. move_assignment_mixin() = default;
  249. move_assignment_mixin(move_assignment_mixin&&) = default;
  250. move_assignment_mixin(move_assignment_mixin const&) = default;
  251. move_assignment_mixin& operator=(move_assignment_mixin&&) = delete;
  252. move_assignment_mixin& operator=(move_assignment_mixin const&) = default;
  253. };
  254. /* Both destructible and move-constructible */
  255. template <class T>
  256. struct move_assignment_mixin<T, true> {
  257. move_assignment_mixin() = default;
  258. move_assignment_mixin(move_assignment_mixin&&) = default;
  259. move_assignment_mixin(move_assignment_mixin const&) = default;
  260. inline move_assignment_mixin&
  261. operator=(move_assignment_mixin&& other) noexcept(
  262. std::is_nothrow_destructible<T>::value&&
  263. std::is_nothrow_move_constructible<T>::value) {
  264. T* destruct_ptr = launder(reinterpret_cast<T*>(
  265. reinterpret_cast<Replaceable<T>*>(this)->storage_));
  266. destruct_ptr->~T();
  267. ::new (reinterpret_cast<Replaceable<T>*>(this)->storage_)
  268. T(*std::move(reinterpret_cast<Replaceable<T>&>(other)));
  269. return *this;
  270. }
  271. move_assignment_mixin& operator=(move_assignment_mixin const&) = default;
  272. };
  273. template <class T, bool = std::is_copy_constructible<T>::value>
  274. struct copy_ctor_mixin;
  275. /* Not copy-constructible */
  276. template <class T>
  277. struct copy_ctor_mixin<T, false> {
  278. copy_ctor_mixin() = default;
  279. copy_ctor_mixin(copy_ctor_mixin&&) = default;
  280. copy_ctor_mixin(copy_ctor_mixin const&) = delete;
  281. copy_ctor_mixin& operator=(copy_ctor_mixin&&) = default;
  282. copy_ctor_mixin& operator=(copy_ctor_mixin const&) = delete;
  283. };
  284. /* Copy-constructible */
  285. template <class T>
  286. struct copy_ctor_mixin<T, true> {
  287. copy_ctor_mixin() = default;
  288. inline copy_ctor_mixin(copy_ctor_mixin const& other) noexcept(
  289. std::is_nothrow_constructible<T, T const&>::value) {
  290. ::new (reinterpret_cast<Replaceable<T>*>(this)->storage_)
  291. T(*reinterpret_cast<Replaceable<T> const&>(other));
  292. }
  293. copy_ctor_mixin(copy_ctor_mixin&&) = default;
  294. copy_ctor_mixin& operator=(copy_ctor_mixin&&) = default;
  295. copy_ctor_mixin& operator=(copy_ctor_mixin const&) = default;
  296. };
  297. template <
  298. class T,
  299. bool = (std::is_destructible<T>::value) &&
  300. (std::is_copy_constructible<T>::value)>
  301. struct copy_assignment_mixin;
  302. /* Not (destructible and copy-constructible) */
  303. template <class T>
  304. struct copy_assignment_mixin<T, false> {
  305. copy_assignment_mixin() = default;
  306. copy_assignment_mixin(copy_assignment_mixin&&) = default;
  307. copy_assignment_mixin(copy_assignment_mixin const&) = default;
  308. copy_assignment_mixin& operator=(copy_assignment_mixin&&) = default;
  309. copy_assignment_mixin& operator=(copy_assignment_mixin const&) = delete;
  310. };
  311. /* Both destructible and copy-constructible */
  312. template <class T>
  313. struct copy_assignment_mixin<T, true> {
  314. copy_assignment_mixin() = default;
  315. copy_assignment_mixin(copy_assignment_mixin&&) = default;
  316. copy_assignment_mixin(copy_assignment_mixin const&) = default;
  317. copy_assignment_mixin& operator=(copy_assignment_mixin&&) = default;
  318. inline copy_assignment_mixin&
  319. operator=(copy_assignment_mixin const& other) noexcept(
  320. std::is_nothrow_destructible<T>::value&&
  321. std::is_nothrow_copy_constructible<T>::value) {
  322. T* destruct_ptr = launder(reinterpret_cast<T*>(
  323. reinterpret_cast<Replaceable<T>*>(this)->storage_));
  324. destruct_ptr->~T();
  325. ::new (reinterpret_cast<Replaceable<T>*>(this)->storage_)
  326. T(*reinterpret_cast<Replaceable<T> const&>(other));
  327. return *this;
  328. }
  329. };
  330. template <typename T>
  331. struct is_constructible_from_replaceable
  332. : bool_constant<
  333. std::is_constructible<T, Replaceable<T>&>::value ||
  334. std::is_constructible<T, Replaceable<T>&&>::value ||
  335. std::is_constructible<T, const Replaceable<T>&>::value ||
  336. std::is_constructible<T, const Replaceable<T>&&>::value> {};
  337. template <typename T>
  338. struct is_convertible_from_replaceable
  339. : bool_constant<
  340. std::is_convertible<Replaceable<T>&, T>::value ||
  341. std::is_convertible<Replaceable<T>&&, T>::value ||
  342. std::is_convertible<const Replaceable<T>&, T>::value ||
  343. std::is_convertible<const Replaceable<T>&&, T>::value> {};
  344. } // namespace replaceable_detail
  345. // Type trait template to statically test whether a type is a specialization of
  346. // Replaceable
  347. template <class T>
  348. struct is_replaceable : std::false_type {};
  349. template <class T>
  350. struct is_replaceable<Replaceable<T>> : std::true_type {};
  351. // Function to make a Replaceable with a type deduced from its input
  352. template <class T>
  353. constexpr Replaceable<std::decay_t<T>> make_replaceable(T&& t) {
  354. return Replaceable<std::decay_t<T>>(std::forward<T>(t));
  355. }
  356. template <class T, class... Args>
  357. constexpr Replaceable<T> make_replaceable(Args&&... args) {
  358. return Replaceable<T>(in_place, std::forward<Args>(args)...);
  359. }
  360. template <class T, class U, class... Args>
  361. constexpr Replaceable<T> make_replaceable(
  362. std::initializer_list<U> il,
  363. Args&&... args) {
  364. return Replaceable<T>(in_place, il, std::forward<Args>(args)...);
  365. }
  366. template <class T>
  367. class alignas(T) Replaceable
  368. : public replaceable_detail::dtor_mixin<T>,
  369. public replaceable_detail::default_and_move_ctor_mixin<T>,
  370. public replaceable_detail::copy_ctor_mixin<T>,
  371. public replaceable_detail::move_assignment_mixin<T>,
  372. public replaceable_detail::copy_assignment_mixin<T> {
  373. using ctor_base = replaceable_detail::default_and_move_ctor_mixin<T>;
  374. public:
  375. using value_type = T;
  376. /* Rule-of-zero default- copy- and move- constructors. The ugly code to make
  377. * these work are above, in namespace folly::replaceable_detail.
  378. */
  379. constexpr Replaceable() = default;
  380. constexpr Replaceable(const Replaceable&) = default;
  381. constexpr Replaceable(Replaceable&&) = default;
  382. /* Rule-of-zero copy- and move- assignment operators. The ugly code to make
  383. * these work are above, in namespace folly::replaceable_detail.
  384. *
  385. * Note - these destruct the `T` and then in-place construct a new one based
  386. * on what is in the other replaceable; they do not invoke the assignment
  387. * operator of `T`.
  388. */
  389. Replaceable& operator=(const Replaceable&) = default;
  390. Replaceable& operator=(Replaceable&&) = default;
  391. /* Rule-of-zero destructor. The ugly code to make this work is above, in
  392. * namespace folly::replaceable_detail.
  393. */
  394. ~Replaceable() = default;
  395. /**
  396. * Constructors; these are modeled very closely on the definition of
  397. * `std::optional` in C++17.
  398. */
  399. template <
  400. class... Args,
  401. std::enable_if_t<std::is_constructible<T, Args&&...>::value, int> = 0>
  402. FOLLY_CPP14_CONSTEXPR explicit Replaceable(in_place_t, Args&&... args)
  403. // clang-format off
  404. noexcept(std::is_nothrow_constructible<T, Args&&...>::value)
  405. // clang-format on
  406. : ctor_base(0) {
  407. ::new (storage_) T(std::forward<Args>(args)...);
  408. }
  409. template <
  410. class U,
  411. class... Args,
  412. std::enable_if_t<
  413. std::is_constructible<T, std::initializer_list<U>, Args&&...>::value,
  414. int> = 0>
  415. FOLLY_CPP14_CONSTEXPR explicit Replaceable(
  416. in_place_t,
  417. std::initializer_list<U> il,
  418. Args&&... args)
  419. // clang-format off
  420. noexcept(std::is_nothrow_constructible<
  421. T,
  422. std::initializer_list<U>,
  423. Args&&...>::value)
  424. // clang-format on
  425. : ctor_base(0) {
  426. ::new (storage_) T(il, std::forward<Args>(args)...);
  427. }
  428. template <
  429. class U = T,
  430. std::enable_if_t<
  431. std::is_constructible<T, U&&>::value &&
  432. !std::is_same<std::decay_t<U>, in_place_t>::value &&
  433. !std::is_same<Replaceable<T>, std::decay_t<U>>::value &&
  434. std::is_convertible<U&&, T>::value,
  435. int> = 0>
  436. FOLLY_CPP14_CONSTEXPR /* implicit */ Replaceable(U&& other)
  437. // clang-format off
  438. noexcept(std::is_nothrow_constructible<T, U&&>::value)
  439. // clang-format on
  440. : ctor_base(0) {
  441. ::new (storage_) T(std::forward<U>(other));
  442. }
  443. template <
  444. class U = T,
  445. std::enable_if_t<
  446. std::is_constructible<T, U&&>::value &&
  447. !std::is_same<std::decay_t<U>, in_place_t>::value &&
  448. !std::is_same<Replaceable<T>, std::decay_t<U>>::value &&
  449. !std::is_convertible<U&&, T>::value,
  450. int> = 0>
  451. FOLLY_CPP14_CONSTEXPR explicit Replaceable(U&& other)
  452. // clang-format off
  453. noexcept(std::is_nothrow_constructible<T, U&&>::value)
  454. // clang-format on
  455. : ctor_base(0) {
  456. ::new (storage_) T(std::forward<U>(other));
  457. }
  458. template <
  459. class U,
  460. std::enable_if_t<
  461. std::is_constructible<T, const U&>::value &&
  462. !replaceable_detail::is_constructible_from_replaceable<
  463. T>::value &&
  464. !replaceable_detail::is_convertible_from_replaceable<T>::value &&
  465. std::is_convertible<const U&, T>::value,
  466. int> = 0>
  467. /* implicit */ Replaceable(const Replaceable<U>& other)
  468. // clang-format off
  469. noexcept(std::is_nothrow_constructible<T, U const&>::value)
  470. // clang-format on
  471. : ctor_base(0) {
  472. ::new (storage_) T(*other);
  473. }
  474. template <
  475. class U,
  476. std::enable_if_t<
  477. std::is_constructible<T, const U&>::value &&
  478. !replaceable_detail::is_constructible_from_replaceable<
  479. T>::value &&
  480. !replaceable_detail::is_convertible_from_replaceable<T>::value &&
  481. !std::is_convertible<const U&, T>::value,
  482. int> = 0>
  483. explicit Replaceable(const Replaceable<U>& other)
  484. // clang-format off
  485. noexcept(std::is_nothrow_constructible<T, U const&>::value)
  486. // clang-format on
  487. : ctor_base(0) {
  488. ::new (storage_) T(*other);
  489. }
  490. template <
  491. class U,
  492. std::enable_if_t<
  493. std::is_constructible<T, U&&>::value &&
  494. !replaceable_detail::is_constructible_from_replaceable<
  495. T>::value &&
  496. !replaceable_detail::is_convertible_from_replaceable<T>::value &&
  497. std::is_convertible<U&&, T>::value,
  498. int> = 0>
  499. /* implicit */ Replaceable(Replaceable<U>&& other)
  500. // clang-format off
  501. noexcept(std::is_nothrow_constructible<T, U&&>::value)
  502. // clang-format on
  503. : ctor_base(0) {
  504. ::new (storage_) T(std::move(*other));
  505. }
  506. template <
  507. class U,
  508. std::enable_if_t<
  509. std::is_constructible<T, U&&>::value &&
  510. !replaceable_detail::is_constructible_from_replaceable<
  511. T>::value &&
  512. !replaceable_detail::is_convertible_from_replaceable<T>::value &&
  513. !std::is_convertible<U&&, T>::value,
  514. int> = 0>
  515. explicit Replaceable(Replaceable<U>&& other)
  516. // clang-format off
  517. noexcept(std::is_nothrow_constructible<T, U&&>::value)
  518. // clang-format on
  519. : ctor_base(0) {
  520. ::new (storage_) T(std::move(*other));
  521. }
  522. /**
  523. * `emplace` destructs the contained object and in-place constructs the
  524. * replacement.
  525. *
  526. * The destructor must not throw (as usual). The constructor must not throw
  527. * because that would violate the invariant that a `Replaceable<T>` always
  528. * contains a T instance.
  529. *
  530. * As these methods are `noexcept` the program will be terminated if an
  531. * exception is thrown. If you are encountering this issue you should look at
  532. * using `Optional` instead.
  533. */
  534. template <class... Args>
  535. T& emplace(Args&&... args) noexcept {
  536. T* destruct_ptr = launder(reinterpret_cast<T*>(storage_));
  537. destruct_ptr->~T();
  538. return *::new (storage_) T(std::forward<Args>(args)...);
  539. }
  540. template <class U, class... Args>
  541. T& emplace(std::initializer_list<U> il, Args&&... args) noexcept {
  542. T* destruct_ptr = launder(reinterpret_cast<T*>(storage_));
  543. destruct_ptr->~T();
  544. return *::new (storage_) T(il, std::forward<Args>(args)...);
  545. }
  546. /**
  547. * `swap` just calls `swap(T&, T&)`.
  548. *
  549. * Should be `noexcept(std::is_nothrow_swappable<T>::value)` but we don't
  550. * depend on C++17 features.
  551. */
  552. void swap(Replaceable& other) {
  553. using std::swap;
  554. swap(*(*this), *other);
  555. }
  556. /**
  557. * Methods to access the contained object. Intended to be very unsurprising.
  558. */
  559. constexpr const T* operator->() const {
  560. return launder(reinterpret_cast<T const*>(storage_));
  561. }
  562. FOLLY_CPP14_CONSTEXPR T* operator->() {
  563. return launder(reinterpret_cast<T*>(storage_));
  564. }
  565. constexpr const T& operator*() const& {
  566. return *launder(reinterpret_cast<T const*>(storage_));
  567. }
  568. FOLLY_CPP14_CONSTEXPR T& operator*() & {
  569. return *launder(reinterpret_cast<T*>(storage_));
  570. }
  571. FOLLY_CPP14_CONSTEXPR T&& operator*() && {
  572. return std::move(*launder(reinterpret_cast<T*>(storage_)));
  573. }
  574. constexpr const T&& operator*() const&& {
  575. return std::move(*launder(reinterpret_cast<T const*>(storage_)));
  576. }
  577. private:
  578. friend struct replaceable_detail::dtor_mixin<T>;
  579. friend struct replaceable_detail::default_and_move_ctor_mixin<T>;
  580. friend struct replaceable_detail::copy_ctor_mixin<T>;
  581. friend struct replaceable_detail::move_assignment_mixin<T>;
  582. friend struct replaceable_detail::copy_assignment_mixin<T>;
  583. std::aligned_storage_t<sizeof(T), alignof(T)> storage_[1];
  584. };
  585. #if __cplusplus > 201402L
  586. // C++17 allows us to define a deduction guide:
  587. template <class T>
  588. Replaceable(T)->Replaceable<T>;
  589. #endif
  590. } // namespace folly