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.

89 lines
1.3 KiB

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