ebco.hpp 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. // sol2
  2. // The MIT License (MIT)
  3. // Copyright (c) 2013-2022 Rapptz, ThePhD and contributors
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy of
  5. // this software and associated documentation files (the "Software"), to deal in
  6. // the Software without restriction, including without limitation the rights to
  7. // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
  8. // the Software, and to permit persons to whom the Software is furnished to do so,
  9. // subject to the following conditions:
  10. // The above copyright notice and this permission notice shall be included in all
  11. // copies or substantial portions of the Software.
  12. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  13. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
  14. // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
  15. // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
  16. // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  17. // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  18. #ifndef SOL_EBCO_HPP
  19. #define SOL_EBCO_HPP
  20. #include <type_traits>
  21. #include <utility>
  22. #include <memory>
  23. namespace sol { namespace detail {
  24. template <typename T, std::size_t tag = 0, typename = void>
  25. struct ebco {
  26. T m_value;
  27. ebco() = default;
  28. ebco(const ebco&) = default;
  29. ebco(ebco&&) = default;
  30. ebco& operator=(const ebco&) = default;
  31. ebco& operator=(ebco&&) = default;
  32. ebco(const T& v) noexcept(std::is_nothrow_copy_constructible_v<T>) : m_value(v) {};
  33. ebco(T&& v) noexcept(std::is_nothrow_move_constructible_v<T>) : m_value(std::move(v)) {};
  34. ebco& operator=(const T& v) noexcept(std::is_nothrow_copy_assignable_v<T>) {
  35. m_value = v;
  36. return *this;
  37. }
  38. ebco& operator=(T&& v) noexcept(std::is_nothrow_move_assignable_v<T>) {
  39. m_value = std::move(v);
  40. return *this;
  41. };
  42. template <typename Arg, typename... Args,
  43. typename = std::enable_if_t<
  44. !std::is_same_v<std::remove_reference_t<std::remove_cv_t<Arg>>,
  45. ebco> && !std::is_same_v<std::remove_reference_t<std::remove_cv_t<Arg>>, T> && (sizeof...(Args) > 0 || !std::is_convertible_v<Arg, T>)>>
  46. ebco(Arg&& arg, Args&&... args) noexcept(std::is_nothrow_constructible_v<T, Arg, Args...>)
  47. : m_value(std::forward<Arg>(arg), std::forward<Args>(args)...) {
  48. }
  49. T& value() & noexcept {
  50. return m_value;
  51. }
  52. T const& value() const& noexcept {
  53. return m_value;
  54. }
  55. T&& value() && noexcept {
  56. return std::move(m_value);
  57. }
  58. };
  59. template <typename T, std::size_t tag>
  60. struct ebco<T, tag, std::enable_if_t<!std::is_reference_v<T> && std::is_class_v<T> && !std::is_final_v<T>>> : T {
  61. ebco() = default;
  62. ebco(const ebco&) = default;
  63. ebco(ebco&&) = default;
  64. ebco(const T& v) noexcept(std::is_nothrow_copy_constructible_v<T>) : T(v) {};
  65. ebco(T&& v) noexcept(std::is_nothrow_move_constructible_v<T>) : T(std::move(v)) {};
  66. template <typename Arg, typename... Args,
  67. typename = std::enable_if_t<
  68. !std::is_same_v<std::remove_reference_t<std::remove_cv_t<Arg>>,
  69. ebco> && !std::is_same_v<std::remove_reference_t<std::remove_cv_t<Arg>>, T> && (sizeof...(Args) > 0 || !std::is_convertible_v<Arg, T>)>>
  70. ebco(Arg&& arg, Args&&... args) noexcept(std::is_nothrow_constructible_v<T, Arg, Args...>) : T(std::forward<Arg>(arg), std::forward<Args>(args)...) {
  71. }
  72. ebco& operator=(const ebco&) = default;
  73. ebco& operator=(ebco&&) = default;
  74. ebco& operator=(const T& v) noexcept(std::is_nothrow_copy_assignable_v<T>) {
  75. static_cast<T&>(*this) = v;
  76. return *this;
  77. }
  78. ebco& operator=(T&& v) noexcept(std::is_nothrow_move_assignable_v<T>) {
  79. static_cast<T&>(*this) = std::move(v);
  80. return *this;
  81. };
  82. T& value() & noexcept {
  83. return static_cast<T&>(*this);
  84. }
  85. T const& value() const& noexcept {
  86. return static_cast<T const&>(*this);
  87. }
  88. T&& value() && noexcept {
  89. return std::move(static_cast<T&>(*this));
  90. }
  91. };
  92. template <typename T, std::size_t tag>
  93. struct ebco<T&, tag> {
  94. private:
  95. T* m_ref;
  96. public:
  97. ebco() = default;
  98. ebco(const ebco&) = default;
  99. ebco(ebco&&) = default;
  100. ebco(T& v) noexcept : m_ref(std::addressof(v)) {};
  101. ebco& operator=(const ebco&) = default;
  102. ebco& operator=(ebco&&) = default;
  103. ebco& operator=(T& v) noexcept {
  104. m_ref = std::addressof(v);
  105. return *this;
  106. }
  107. T& value() const noexcept {
  108. return *(const_cast<ebco<T&, tag>&>(*this).m_ref);
  109. }
  110. };
  111. template <typename T, std::size_t tag>
  112. struct ebco<T&&, tag> {
  113. T&& ref;
  114. ebco() = default;
  115. ebco(const ebco&) = delete;
  116. ebco(ebco&&) = default;
  117. ebco(T&& v) noexcept : ref(v) {};
  118. ebco& operator=(const ebco&) = delete;
  119. ebco& operator=(ebco&&) = delete;
  120. T& value() & noexcept {
  121. return ref;
  122. }
  123. const T& value() const& noexcept {
  124. return ref;
  125. }
  126. T&& value() && noexcept {
  127. return std::move(ref);
  128. }
  129. };
  130. }} // namespace sol::detail
  131. #endif // SOL_EBCO_HPP