property.hpp 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  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_PROPERTY_HPP
  19. #define SOL_PROPERTY_HPP
  20. #include <sol/types.hpp>
  21. #include <sol/ebco.hpp>
  22. #include <type_traits>
  23. #include <utility>
  24. namespace sol {
  25. namespace detail {
  26. struct no_prop { };
  27. } // namespace detail
  28. template <typename R, typename W>
  29. struct property_wrapper : detail::ebco<R, 0>, detail::ebco<W, 1> {
  30. private:
  31. using read_base_t = detail::ebco<R, 0>;
  32. using write_base_t = detail::ebco<W, 1>;
  33. public:
  34. template <typename Rx, typename Wx>
  35. property_wrapper(Rx&& r, Wx&& w) : read_base_t(std::forward<Rx>(r)), write_base_t(std::forward<Wx>(w)) {
  36. }
  37. W& write() {
  38. return write_base_t::value();
  39. }
  40. const W& write() const {
  41. return write_base_t::value();
  42. }
  43. R& read() {
  44. return read_base_t::value();
  45. }
  46. const R& read() const {
  47. return read_base_t::value();
  48. }
  49. };
  50. template <typename F, typename G>
  51. inline decltype(auto) property(F&& f, G&& g) {
  52. typedef lua_bind_traits<meta::unqualified_t<F>> left_traits;
  53. typedef lua_bind_traits<meta::unqualified_t<G>> right_traits;
  54. if constexpr (left_traits::free_arity < right_traits::free_arity) {
  55. return property_wrapper<std::decay_t<F>, std::decay_t<G>>(std::forward<F>(f), std::forward<G>(g));
  56. }
  57. else {
  58. return property_wrapper<std::decay_t<G>, std::decay_t<F>>(std::forward<G>(g), std::forward<F>(f));
  59. }
  60. }
  61. template <typename F>
  62. inline decltype(auto) property(F&& f) {
  63. typedef lua_bind_traits<meta::unqualified_t<F>> left_traits;
  64. if constexpr (left_traits::free_arity < 2) {
  65. return property_wrapper<std::decay_t<F>, detail::no_prop>(std::forward<F>(f), detail::no_prop());
  66. }
  67. else {
  68. return property_wrapper<detail::no_prop, std::decay_t<F>>(detail::no_prop(), std::forward<F>(f));
  69. }
  70. }
  71. template <typename F>
  72. inline decltype(auto) readonly_property(F&& f) {
  73. return property_wrapper<std::decay_t<F>, detail::no_prop>(std::forward<F>(f), detail::no_prop());
  74. }
  75. template <typename F>
  76. inline decltype(auto) writeonly_property(F&& f) {
  77. return property_wrapper<detail::no_prop, std::decay_t<F>>(detail::no_prop(), std::forward<F>(f));
  78. }
  79. template <typename T>
  80. struct readonly_wrapper : detail::ebco<T> {
  81. private:
  82. using base_t = detail::ebco<T>;
  83. public:
  84. using base_t::base_t;
  85. operator T&() {
  86. return base_t::value();
  87. }
  88. operator const T&() const {
  89. return base_t::value();
  90. }
  91. };
  92. // Allow someone to make a member variable readonly (const)
  93. template <typename R, typename T>
  94. inline auto readonly(R T::*v) {
  95. return readonly_wrapper<meta::unqualified_t<decltype(v)>>(v);
  96. }
  97. template <typename T>
  98. struct var_wrapper : detail::ebco<T> {
  99. private:
  100. using base_t = detail::ebco<T>;
  101. public:
  102. using base_t::base_t;
  103. };
  104. template <typename V>
  105. inline auto var(V&& v) {
  106. typedef std::decay_t<V> T;
  107. return var_wrapper<T>(std::forward<V>(v));
  108. }
  109. namespace meta {
  110. template <typename T>
  111. using is_member_object = std::integral_constant<bool, std::is_member_object_pointer_v<T> || is_specialization_of_v<T, readonly_wrapper>>;
  112. template <typename T>
  113. inline constexpr bool is_member_object_v = is_member_object<T>::value;
  114. template <typename T>
  115. using is_member_object_or_function = std::integral_constant<bool, is_member_object_v<T> || std::is_member_pointer_v<T>>;
  116. template <typename T>
  117. inline constexpr bool is_member_object_or_function_v = is_member_object_or_function<T>::value;
  118. } // namespace meta
  119. } // namespace sol
  120. #endif // SOL_PROPERTY_HPP