rice 4.0.4 → 4.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (105) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +37 -0
  3. data/CONTRIBUTORS.md +2 -0
  4. data/Rakefile +1 -1
  5. data/include/rice/rice.hpp +2851 -1955
  6. data/include/rice/stl.hpp +1654 -287
  7. data/lib/mkmf-rice.rb +5 -2
  8. data/lib/version.rb +1 -1
  9. data/rice/Arg.hpp +6 -6
  10. data/rice/Arg.ipp +8 -9
  11. data/rice/Constructor.hpp +2 -2
  12. data/rice/Data_Object.ipp +69 -15
  13. data/rice/Data_Object_defn.hpp +1 -15
  14. data/rice/Data_Type.ipp +56 -86
  15. data/rice/Data_Type_defn.hpp +14 -17
  16. data/rice/Director.hpp +0 -1
  17. data/rice/Enum.ipp +31 -22
  18. data/rice/Exception.ipp +2 -3
  19. data/rice/Exception_defn.hpp +5 -5
  20. data/rice/HandlerRegistration.hpp +15 -0
  21. data/rice/Return.hpp +5 -4
  22. data/rice/Return.ipp +8 -3
  23. data/rice/detail/ExceptionHandler.hpp +8 -0
  24. data/rice/detail/ExceptionHandler.ipp +28 -0
  25. data/rice/detail/{Exception_Handler_defn.hpp → ExceptionHandler_defn.hpp} +17 -21
  26. data/rice/detail/HandlerRegistry.hpp +51 -0
  27. data/rice/detail/HandlerRegistry.ipp +20 -0
  28. data/rice/detail/InstanceRegistry.hpp +34 -0
  29. data/rice/detail/InstanceRegistry.ipp +50 -0
  30. data/rice/detail/MethodInfo.ipp +1 -1
  31. data/rice/detail/NativeAttribute.hpp +26 -15
  32. data/rice/detail/NativeAttribute.ipp +76 -47
  33. data/rice/detail/NativeFunction.hpp +64 -14
  34. data/rice/detail/NativeFunction.ipp +138 -86
  35. data/rice/detail/NativeIterator.hpp +49 -0
  36. data/rice/detail/NativeIterator.ipp +102 -0
  37. data/rice/detail/NativeRegistry.hpp +31 -0
  38. data/rice/detail/{method_data.ipp → NativeRegistry.ipp} +20 -16
  39. data/rice/detail/Registries.hpp +26 -0
  40. data/rice/detail/Registries.ipp +23 -0
  41. data/rice/detail/RubyFunction.hpp +6 -11
  42. data/rice/detail/RubyFunction.ipp +10 -22
  43. data/rice/detail/Type.hpp +1 -1
  44. data/rice/detail/Type.ipp +2 -2
  45. data/rice/detail/TypeRegistry.hpp +8 -11
  46. data/rice/detail/TypeRegistry.ipp +3 -28
  47. data/rice/detail/Wrapper.hpp +0 -2
  48. data/rice/detail/Wrapper.ipp +74 -24
  49. data/rice/detail/cpp_protect.hpp +93 -0
  50. data/rice/detail/default_allocation_func.ipp +1 -1
  51. data/rice/detail/from_ruby.ipp +206 -2
  52. data/rice/detail/to_ruby.ipp +39 -5
  53. data/rice/detail/to_ruby_defn.hpp +1 -1
  54. data/rice/forward_declares.ipp +6 -0
  55. data/rice/global_function.hpp +0 -4
  56. data/rice/global_function.ipp +0 -6
  57. data/rice/rice.hpp +29 -24
  58. data/rice/stl.hpp +6 -1
  59. data/sample/callbacks/extconf.rb +0 -1
  60. data/sample/enum/extconf.rb +0 -1
  61. data/sample/inheritance/extconf.rb +0 -1
  62. data/sample/map/extconf.rb +0 -1
  63. data/test/embed_ruby.cpp +6 -15
  64. data/test/ext/t1/extconf.rb +0 -1
  65. data/test/ext/t2/extconf.rb +0 -1
  66. data/test/extconf.rb +0 -1
  67. data/test/test_Array.cpp +20 -24
  68. data/test/test_Attribute.cpp +6 -6
  69. data/test/test_Class.cpp +8 -47
  70. data/test/test_Constructor.cpp +0 -2
  71. data/test/test_Data_Object.cpp +25 -11
  72. data/test/test_Data_Type.cpp +124 -28
  73. data/test/test_Director.cpp +12 -13
  74. data/test/test_Enum.cpp +65 -26
  75. data/test/test_Inheritance.cpp +9 -9
  76. data/test/test_Iterator.cpp +134 -5
  77. data/test/test_Keep_Alive.cpp +7 -7
  78. data/test/test_Keep_Alive_No_Wrapper.cpp +80 -0
  79. data/test/test_Memory_Management.cpp +1 -1
  80. data/test/test_Module.cpp +25 -62
  81. data/test/test_Object.cpp +75 -3
  82. data/test/test_Ownership.cpp +12 -13
  83. data/test/test_Self.cpp +12 -13
  84. data/test/test_Stl_Map.cpp +696 -0
  85. data/test/test_Stl_Optional.cpp +3 -3
  86. data/test/test_Stl_Pair.cpp +38 -2
  87. data/test/test_Stl_Reference_Wrapper.cpp +102 -0
  88. data/test/test_Stl_SmartPointer.cpp +49 -9
  89. data/test/test_Stl_String.cpp +5 -2
  90. data/test/test_Stl_Unordered_Map.cpp +697 -0
  91. data/test/test_Stl_Variant.cpp +346 -0
  92. data/test/test_Stl_Vector.cpp +200 -41
  93. data/test/test_Struct.cpp +3 -3
  94. data/test/test_To_From_Ruby.cpp +8 -2
  95. data/test/test_Tracking.cpp +239 -0
  96. data/test/unittest.hpp +21 -4
  97. metadata +24 -13
  98. data/rice/detail/Exception_Handler.hpp +0 -8
  99. data/rice/detail/Exception_Handler.ipp +0 -28
  100. data/rice/detail/Iterator.hpp +0 -23
  101. data/rice/detail/Iterator.ipp +0 -47
  102. data/rice/detail/function_traits.hpp +0 -124
  103. data/rice/detail/method_data.hpp +0 -29
  104. data/rice/detail/rice_traits.hpp +0 -116
  105. data/rice/ruby_try_catch.hpp +0 -86
data/rice/Director.hpp CHANGED
@@ -40,5 +40,4 @@ namespace Rice
40
40
 
41
41
  };
42
42
  }
43
-
44
43
  #endif // Rice__Director__hpp_
data/rice/Enum.ipp CHANGED
@@ -54,21 +54,6 @@ namespace Rice
54
54
  // been included by the user
55
55
  return String(result.str());
56
56
  })
57
- .define_method("<=>", [](Enum_T& self, Enum_T& other)
58
- {
59
- if (self == other)
60
- {
61
- return 0;
62
- }
63
- else if (self < other)
64
- {
65
- return -1;
66
- }
67
- else
68
- {
69
- return 1;
70
- }
71
- })
72
57
  .define_method("hash", [](Enum_T& self) -> Underlying_T
73
58
  {
74
59
  return (Underlying_T)self;
@@ -82,19 +67,43 @@ namespace Rice
82
67
  rb_define_alias(klass, "===", "eql?");
83
68
 
84
69
  // Add comparable support
85
- klass.include_module(rb_mComparable);
70
+ klass.include_module(rb_mComparable)
71
+ .define_method("<=>", [](Enum_T& self, Enum_T& other)
72
+ {
73
+ if (self == other)
74
+ {
75
+ return 0;
76
+ }
77
+ else if (self < other)
78
+ {
79
+ return -1;
80
+ }
81
+ else
82
+ {
83
+ return 1;
84
+ }
85
+ });
86
86
 
87
- // Singleton methods
88
- klass.define_singleton_method("each", [](VALUE klass)
87
+ // Add enumerable support
88
+ klass.include_module(rb_mEnumerable)
89
+ .define_singleton_method("each", [](VALUE ruby_klass) -> VALUE
89
90
  {
91
+ if (!rb_block_given_p())
92
+ {
93
+ return rb_enumeratorize_with_size(ruby_klass, Identifier("each").to_sym(),
94
+ 0, nullptr, 0);
95
+ }
96
+
90
97
  for (auto& pair : valuesToNames_)
91
98
  {
92
99
  Enum_T enumValue = pair.first;
93
100
  VALUE value = detail::To_Ruby<Enum_T>().convert(enumValue);
94
101
  detail::protect(rb_yield, value);
95
102
  }
96
- })
97
- .define_singleton_method("from_int", [](VALUE klass, int32_t value)
103
+
104
+ return ruby_klass;
105
+ }, Return().setValue())
106
+ .define_singleton_method("from_int", [](VALUE ruby_klass, int32_t value) -> Object
98
107
  {
99
108
  auto iter = Enum<Enum_T>::valuesToNames_.find((Enum_T)value);
100
109
  if (iter == Enum<Enum_T>::valuesToNames_.end())
@@ -103,14 +112,14 @@ namespace Rice
103
112
  }
104
113
 
105
114
  std::string name = iter->second;
106
- return Class(klass).const_get(name);
115
+ return Object(ruby_klass).const_get(name);
107
116
  });
108
117
  }
109
118
 
110
119
  template<typename Enum_T>
111
120
  Enum<Enum_T> define_enum(char const* name, Module module)
112
121
  {
113
- if (detail::TypeRegistry::isDefined<Enum_T>())
122
+ if (detail::Registries::instance.types.isDefined<Enum_T>())
114
123
  {
115
124
  return Enum<Enum_T>();
116
125
  }
data/rice/Exception.ipp CHANGED
@@ -43,10 +43,9 @@ namespace Rice
43
43
  {
44
44
  if (this->message_.empty())
45
45
  {
46
- // Cache the message - this allows the returned pointer to be valid for the
47
- // lifetime of this exception instance.
46
+ // This isn't protected because if it fails then either we could eat the exception
47
+ // (not good) or crash the program (better)
48
48
  VALUE rubyMessage = rb_funcall(this->exception_, rb_intern("message"), 0);
49
- //this->message_ = detail::From_Ruby<std::string>::convert(rubyMessage);
50
49
  this->message_ = std::string(RSTRING_PTR(rubyMessage), RSTRING_LEN(rubyMessage));
51
50
  }
52
51
  return this->message_.c_str();
@@ -33,11 +33,11 @@ namespace Rice
33
33
  Exception(const Exception& other, char const* fmt, Arg_Ts&&...args);
34
34
 
35
35
  //! Construct a Exception with printf-style formatting.
36
- /*! \param exc either an exception object or a class that inherits
37
- * from Exception.
38
- * \param fmt a printf-style format string
39
- * \param ... the arguments to the format string.
40
- */
36
+ /*! \param exc either an exception object or a class that inherits
37
+ * from Exception.
38
+ * \param fmt a printf-style format string
39
+ * \param ... the arguments to the format string.
40
+ */
41
41
  template <typename... Arg_Ts>
42
42
  Exception(const VALUE exceptionType, char const* fmt, Arg_Ts&&...args);
43
43
 
@@ -0,0 +1,15 @@
1
+ #ifndef Rice__HandlerRegistration__hpp_
2
+ #define Rice__HandlerRegistration__hpp_
3
+
4
+ #include "detail/HandlerRegistry.hpp"
5
+
6
+ namespace Rice
7
+ {
8
+ // Register exception handler
9
+ template<typename Exception_T, typename Functor_T>
10
+ detail::HandlerRegistry register_handler(Functor_T functor)
11
+ {
12
+ return detail::Registries::instance.handlers.add<Exception_T, Functor_T>(std::forward<Functor_T>(functor));
13
+ }
14
+ }
15
+ #endif // Rice__HandlerRegistration__hpp_
data/rice/Return.hpp CHANGED
@@ -17,18 +17,19 @@ namespace Rice
17
17
  bool isOwner();
18
18
 
19
19
  //! Specifies the returned value is a Ruby value
20
- Return& isValue();
20
+ Return& setValue();
21
21
 
22
22
  //! Is the returned value a Ruby value?
23
- bool getIsValue();
23
+ bool isValue() const;
24
24
 
25
25
  //! Tell the returned object to keep alive the receving object
26
26
  Return& keepAlive();
27
27
 
28
- public:
29
- bool isKeepAlive = false;
28
+ //! Is the returned value being kept alive?
29
+ bool isKeepAlive() const;
30
30
 
31
31
  private:
32
+ bool isKeepAlive_ = false;
32
33
  bool isOwner_ = false;
33
34
  bool isValue_ = false;
34
35
  };
data/rice/Return.ipp CHANGED
@@ -14,20 +14,25 @@ namespace Rice
14
14
  return this->isOwner_;
15
15
  }
16
16
 
17
- inline Return& Return::isValue()
17
+ inline Return& Return::setValue()
18
18
  {
19
19
  this->isValue_ = true;
20
20
  return *this;
21
21
  }
22
22
 
23
- inline bool Return::getIsValue()
23
+ inline bool Return::isValue() const
24
24
  {
25
25
  return this->isValue_;
26
26
  }
27
27
 
28
28
  inline Return& Return::keepAlive()
29
29
  {
30
- this->isKeepAlive = true;
30
+ this->isKeepAlive_ = true;
31
31
  return *this;
32
32
  }
33
+
34
+ inline bool Return::isKeepAlive() const
35
+ {
36
+ return this->isKeepAlive_;
37
+ }
33
38
  } // Rice
@@ -0,0 +1,8 @@
1
+ #ifndef Rice__detail__ExceptionHandler__hpp_
2
+ #define Rice__detail__ExceptionHandler__hpp_
3
+
4
+ #include "ExceptionHandler_defn.hpp"
5
+ #include "ExceptionHandler.ipp"
6
+
7
+ #endif // Rice__detail__ExceptionHandler__hpp_
8
+
@@ -0,0 +1,28 @@
1
+ namespace Rice::detail
2
+ {
3
+ inline VALUE Rice::detail::DefaultExceptionHandler::handle() const
4
+ {
5
+ throw;
6
+ }
7
+
8
+ template <typename Exception_T, typename Functor_T>
9
+ inline Rice::detail::CustomExceptionHandler<Exception_T, Functor_T>::
10
+ CustomExceptionHandler(Functor_T handler, std::shared_ptr<ExceptionHandler> nextHandler)
11
+ : handler_(handler), nextHandler_(nextHandler)
12
+ {
13
+ }
14
+
15
+ template <typename Exception_T, typename Functor_T>
16
+ inline VALUE Rice::detail::CustomExceptionHandler<Exception_T, Functor_T>::handle() const
17
+ {
18
+ try
19
+ {
20
+ return this->nextHandler_->handle();
21
+ }
22
+ catch (Exception_T const& ex)
23
+ {
24
+ handler_(ex);
25
+ throw;
26
+ }
27
+ }
28
+ }
@@ -1,5 +1,5 @@
1
- #ifndef Rice__detail__Exception_Handler_defn__hpp_
2
- #define Rice__detail__Exception_Handler_defn__hpp_
1
+ #ifndef Rice__detail__ExceptionHandler_defn__hpp_
2
+ #define Rice__detail__ExceptionHandler_defn__hpp_
3
3
 
4
4
  #include <memory>
5
5
  #include "ruby.hpp"
@@ -14,7 +14,7 @@ namespace Rice::detail
14
14
  }
15
15
  catch(...)
16
16
  {
17
- handler->handle_exception();
17
+ handler->handle();
18
18
  }
19
19
 
20
20
  If an exception is thrown the handler will pass the exception up the
@@ -23,7 +23,7 @@ namespace Rice::detail
23
23
 
24
24
  try
25
25
  {
26
- return call_next_exception_handler();
26
+ return call_next_ExceptionHandler();
27
27
  }
28
28
  catch(MyException const & ex)
29
29
  {
@@ -36,27 +36,26 @@ namespace Rice::detail
36
36
  using std::shared_ptr. Thus the Module (or its inherited children) can be destroyed
37
37
  without corrupting the metadata references to the shared exception handler. */
38
38
 
39
- class Exception_Handler
39
+ class ExceptionHandler
40
40
  {
41
41
  public:
42
- Exception_Handler() = default;
43
- virtual ~Exception_Handler() = default;
42
+ ExceptionHandler() = default;
43
+ virtual ~ExceptionHandler() = default;
44
44
 
45
45
  // Don't allow copying or assignment
46
- Exception_Handler(const Exception_Handler& other) = delete;
47
- Exception_Handler& operator=(const Exception_Handler& other) = delete;
46
+ ExceptionHandler(const ExceptionHandler& other) = delete;
47
+ ExceptionHandler& operator=(const ExceptionHandler& other) = delete;
48
48
 
49
- virtual VALUE handle_exception() const = 0;
49
+ virtual VALUE handle() const = 0;
50
50
  };
51
51
 
52
52
  // The default exception handler just rethrows the exception. If there
53
53
  // are other handlers in the chain, they will try to handle the rethrown
54
54
  // exception.
55
- class Default_Exception_Handler
56
- : public Exception_Handler
55
+ class DefaultExceptionHandler : public ExceptionHandler
57
56
  {
58
57
  public:
59
- virtual VALUE handle_exception() const override;
58
+ virtual VALUE handle() const override;
60
59
  };
61
60
 
62
61
  // An exception handler that takes a functor as an argument. The
@@ -64,18 +63,15 @@ namespace Rice::detail
64
63
  // the functor does not handle the exception, the exception will be
65
64
  // re-thrown.
66
65
  template <typename Exception_T, typename Functor_T>
67
- class Functor_Exception_Handler
68
- : public Exception_Handler
66
+ class CustomExceptionHandler : public ExceptionHandler
69
67
  {
70
68
  public:
71
- Functor_Exception_Handler(Functor_T handler,
72
- std::shared_ptr<Exception_Handler> next_exception_handler);
73
-
74
- virtual VALUE handle_exception() const override;
69
+ CustomExceptionHandler(Functor_T handler, std::shared_ptr<ExceptionHandler> nextHandler);
70
+ virtual VALUE handle() const override;
75
71
 
76
72
  private:
77
73
  Functor_T handler_;
78
- std::shared_ptr<Exception_Handler> next_exception_handler_;
74
+ std::shared_ptr<ExceptionHandler> nextHandler_;
79
75
  };
80
76
  }
81
- #endif // Rice__detail__Exception_Handler_defn__hpp_
77
+ #endif // Rice__detail__ExceptionHandler_defn__hpp_
@@ -0,0 +1,51 @@
1
+ #ifndef Rice__detail__HandlerRegistry__hpp_
2
+ #define Rice__detail__HandlerRegistry__hpp_
3
+
4
+ #include "ExceptionHandler.hpp"
5
+
6
+ namespace Rice::detail
7
+ {
8
+ class HandlerRegistry
9
+ {
10
+ public:
11
+ //! Define an exception handler.
12
+ /*! Whenever an exception of type Exception_T is thrown from a
13
+ * function defined on this class, the supplied functor will be called to
14
+ * translate the exception into a ruby exception.
15
+ * \param Exception_T a template parameter indicating the type of
16
+ * exception to be translated.
17
+ * \param functor a functor to be called to translate the exception
18
+ * into a ruby exception. This functor should re-throw the exception
19
+ * as an Exception.
20
+ * Example:
21
+ * \code
22
+ * Class rb_cFoo;
23
+ *
24
+ * void translate_my_exception(MyException const& ex)
25
+ * {
26
+ * throw Rice::Exception(rb_eRuntimeError, ex.what_without_backtrace());
27
+ * }
28
+ *
29
+ * extern "C"
30
+ * void Init_MyExtension()
31
+ * {
32
+ * rb_cFoo = define_class("Foo");
33
+ * register_handler<MyException>(translate_my_exception);
34
+ * }
35
+ * \endcode
36
+ */
37
+ template<typename Exception_T, typename Functor_T>
38
+ HandlerRegistry& add(Functor_T functor);
39
+
40
+ std::shared_ptr<detail::ExceptionHandler> handler() const;
41
+
42
+ private:
43
+ mutable std::shared_ptr<detail::ExceptionHandler> handler_ = std::make_shared<Rice::detail::DefaultExceptionHandler>();
44
+
45
+ };
46
+ } // namespace Rice::detail
47
+
48
+ #include "HandlerRegistry.ipp"
49
+
50
+ #endif // Rice__detail__HandlerRegistry__hpp_
51
+
@@ -0,0 +1,20 @@
1
+ #include <memory>
2
+
3
+ namespace Rice::detail
4
+ {
5
+ template<typename Exception_T, typename Functor_T>
6
+ inline HandlerRegistry& HandlerRegistry::add(Functor_T functor)
7
+ {
8
+ // Create a new exception handler and pass ownership of the current handler to it (they
9
+ // get chained together). Then take ownership of the new handler.
10
+ this->handler_ = std::make_shared<detail::CustomExceptionHandler<Exception_T, Functor_T>>(
11
+ functor, std::move(this->handler_));
12
+
13
+ return *this;
14
+ }
15
+
16
+ inline std::shared_ptr<detail::ExceptionHandler> HandlerRegistry::handler() const
17
+ {
18
+ return this->handler_;
19
+ }
20
+ } // namespace
@@ -0,0 +1,34 @@
1
+ #ifndef Rice__detail__InstanceRegistry__hpp_
2
+ #define Rice__detail__InstanceRegistry__hpp_
3
+
4
+ #include <map>
5
+ #include "ruby.hpp"
6
+
7
+ namespace Rice::detail
8
+ {
9
+ class InstanceRegistry
10
+ {
11
+ public:
12
+ template <typename T>
13
+ VALUE lookup(T& cppInstance);
14
+
15
+ template <typename T>
16
+ VALUE lookup(T* cppInstance);
17
+
18
+ void add(void* cppInstance, VALUE rubyInstance);
19
+ void remove(void* cppInstance);
20
+ void clear();
21
+
22
+ public:
23
+ bool isEnabled = false;
24
+
25
+ private:
26
+ VALUE lookup(void* cppInstance);
27
+ std::map<void*, VALUE> objectMap_;
28
+ };
29
+ } // namespace Rice::detail
30
+
31
+ #include "InstanceRegistry.ipp"
32
+
33
+ #endif // Rice__detail__InstanceRegistry__hpp_
34
+
@@ -0,0 +1,50 @@
1
+ #include <memory>
2
+
3
+ namespace Rice::detail
4
+ {
5
+ template <typename T>
6
+ inline VALUE InstanceRegistry::lookup(T& cppInstance)
7
+ {
8
+ return this->lookup((void*)&cppInstance);
9
+ }
10
+
11
+ template <typename T>
12
+ inline VALUE InstanceRegistry::lookup(T* cppInstance)
13
+ {
14
+ return this->lookup((void*)cppInstance);
15
+ }
16
+
17
+ inline VALUE InstanceRegistry::lookup(void* cppInstance)
18
+ {
19
+ if (!this->isEnabled)
20
+ return Qnil;
21
+
22
+ auto it = this->objectMap_.find(cppInstance);
23
+ if (it != this->objectMap_.end())
24
+ {
25
+ return it->second;
26
+ }
27
+ else
28
+ {
29
+ return Qnil;
30
+ }
31
+ }
32
+
33
+ inline void InstanceRegistry::add(void* cppInstance, VALUE rubyInstance)
34
+ {
35
+ if (this->isEnabled)
36
+ {
37
+ this->objectMap_[cppInstance] = rubyInstance;
38
+ }
39
+ }
40
+
41
+ inline void InstanceRegistry::remove(void* cppInstance)
42
+ {
43
+ this->objectMap_.erase(cppInstance);
44
+ }
45
+
46
+ inline void InstanceRegistry::clear()
47
+ {
48
+ this->objectMap_.clear();
49
+ }
50
+ } // namespace
@@ -13,7 +13,7 @@ namespace Rice
13
13
  for (size_t i = this->args_.size(); i < argCount; i++)
14
14
  {
15
15
  Arg arg("arg_" + std::to_string(i));
16
- this->args_.emplace_back(arg);
16
+ this->addArg(arg);
17
17
  }
18
18
 
19
19
  // TODO - so hacky but update the Arg positions
@@ -2,8 +2,7 @@
2
2
  #define Rice__detail__Native_Attribute__hpp_
3
3
 
4
4
  #include "ruby.hpp"
5
- #include "Exception_Handler_defn.hpp"
6
- #include "MethodInfo.hpp"
5
+ #include "../traits/attribute_traits.hpp"
7
6
 
8
7
  namespace Rice
9
8
  {
@@ -16,35 +15,47 @@ namespace Rice
16
15
 
17
16
  namespace detail
18
17
  {
19
- template<typename Return_T, typename Attr_T, typename Self_T = void>
18
+ template<typename Attribute_T>
20
19
  class NativeAttribute
21
20
  {
22
21
  public:
23
- using Native_Return_T = Return_T;
22
+ using NativeAttribute_T = NativeAttribute<Attribute_T>;
24
23
 
25
- // Static member functions that Ruby calls
24
+ using T = typename attribute_traits<Attribute_T>::attr_type;
25
+ using T_Unqualified = remove_cv_recursive_t<T>;
26
+ using Receiver_T = typename attribute_traits<Attribute_T>::class_type;
27
+
28
+ public:
29
+ // Register attribute getter/setter with Ruby
30
+ static void define(VALUE klass, std::string name, Attribute_T attribute, AttrAccess access = AttrAccess::ReadWrite);
31
+
32
+ // Static member functions that Ruby calls to read an attribute value
26
33
  static VALUE get(VALUE self);
34
+
35
+ // Static member functions that Ruby calls to write an attribute value
27
36
  static VALUE set(VALUE self, VALUE value);
28
37
 
29
38
  public:
30
- NativeAttribute(Attr_T attr, AttrAccess access = AttrAccess::ReadWrite);
39
+ // Disallow creating/copying/moving
40
+ NativeAttribute() = delete;
41
+ NativeAttribute(const NativeAttribute_T&) = delete;
42
+ NativeAttribute(NativeAttribute_T&&) = delete;
43
+ void operator=(const NativeAttribute_T&) = delete;
44
+ void operator=(NativeAttribute_T&&) = delete;
45
+
46
+ protected:
47
+ NativeAttribute(VALUE klass, std::string name, Attribute_T attr, AttrAccess access = AttrAccess::ReadWrite);
31
48
 
32
49
  // Invokes the wrapped function
33
50
  VALUE read(VALUE self);
34
51
  VALUE write(VALUE self, VALUE value);
35
52
 
36
53
  private:
37
- Attr_T attr_;
54
+ VALUE klass_;
55
+ std::string name_;
56
+ Attribute_T attribute_;
38
57
  AttrAccess access_;
39
58
  };
40
-
41
- // A plain function or static member call
42
- template<typename T>
43
- auto* Make_Native_Attribute(T* attr, AttrAccess access);
44
-
45
- // Lambda function that does not take Self as first parameter
46
- template<typename Class_T, typename T>
47
- auto* Make_Native_Attribute(T Class_T::* attr, AttrAccess access);
48
59
  } // detail
49
60
  } // Rice
50
61