General Purpose library for Freestanding C++ and POSIX systems
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

107 regels
1.7 KiB

4 jaren geleden
4 jaren geleden
4 jaren geleden
4 jaren geleden
  1. #pragma once
  2. #include "gp_config.hpp"
  3. #include "gp/functional/bind_front.hpp"
  4. #include "gp/functional/monostates.hpp"
  5. #include "gp/algorithms/move.hpp"
  6. #include "gp/exception.hpp"
  7. #include <type_traits>
  8. #include <new>
  9. namespace gp{
  10. template<typename T>
  11. class optional final{
  12. bool ready = false;
  13. alignas(T) char buffer[sizeof(T)];
  14. public:
  15. constexpr optional()
  16. : ready{false}
  17. {}
  18. constexpr optional(nullopt_t)
  19. : ready{false}
  20. {}
  21. constexpr optional(T& value)
  22. : ready{true}
  23. {
  24. new(buffer) T(value);
  25. }
  26. constexpr optional(T&& value)
  27. : ready{true}
  28. {
  29. new(buffer) T(gp::forward<T>(value));
  30. }
  31. ~optional() {
  32. if(ready) {
  33. ((T*)buffer)->~T();
  34. }
  35. }
  36. optional& operator=(nullopt_t) {
  37. if(ready) {
  38. ((T*)buffer)->~T();
  39. ready = false;
  40. }
  41. return *this;
  42. }
  43. optional& operator=(T& value) {
  44. if(ready) {
  45. *(T*)buffer = value;
  46. } else {
  47. ready = true;
  48. new(buffer) T(value);
  49. }
  50. return *this;
  51. }
  52. optional& operator=(T&& value) {
  53. if(ready) {
  54. *(T*)buffer = gp::forward<T>(value);
  55. } else {
  56. ready = true;
  57. new(buffer) T(gp::forward<T>(value));
  58. }
  59. return *this;
  60. }
  61. constexpr bool has_value() const
  62. {
  63. return ready;
  64. }
  65. constexpr T& value()
  66. {
  67. if constexpr (gp_config::has_exceptions)
  68. {
  69. if(!ready)
  70. {
  71. throw bad_optional{};
  72. }
  73. } else {
  74. gp_config::assertion(ready, "bad optional access");
  75. }
  76. return *reinterpret_cast<T*>(buffer);
  77. }
  78. constexpr const T& value() const
  79. {
  80. if constexpr (gp_config::has_exceptions)
  81. {
  82. if(!ready)
  83. {
  84. throw bad_optional{};
  85. }
  86. } else {
  87. gp_config::assertion(ready, "bad optional access");
  88. }
  89. return *reinterpret_cast<const T*>(buffer);
  90. }
  91. };
  92. }