fork download
  1. #include <utility>
  2.  
  3. enum access_flags {
  4. readable = 1 << 0,
  5. writeable = 1 << 1
  6. };
  7.  
  8. template <typename ValueT>
  9. class default_accessor {
  10. public:
  11. // Types.
  12. typedef ValueT value_type;
  13. typedef value_type& reference;
  14. typedef const value_type& const_reference;
  15.  
  16. // Constructors.
  17. default_accessor(const_reference value_ref) : m_value_ref(value_ref)
  18. {
  19. // Do nothing.
  20. }
  21.  
  22. // Accessors.
  23. const_reference operator()() const noexcept
  24. {
  25. return m_value_ref;
  26. }
  27. private:
  28. // Data.
  29. const_reference m_value_ref;
  30. };
  31.  
  32. template <typename ValueT>
  33. class default_mutator {
  34. public:
  35. // Types.
  36. typedef ValueT value_type;
  37. typedef value_type& reference;
  38. typedef const value_type& const_reference;
  39.  
  40. // Constructors.
  41. default_mutator(reference value_ref) : m_value_ref(value_ref)
  42. {
  43. // Do nothing.
  44. }
  45.  
  46. // Mutators.
  47. void operator()(const_reference value) noexcept
  48. {
  49. m_value_ref = value;
  50. }
  51.  
  52. void operator()(value_type&& value) noexcept
  53. {
  54. m_value_ref = std::move(value);
  55. }
  56. private:
  57. // Data.
  58. reference m_value_ref;
  59. };
  60.  
  61. template <typename ValueT, unsigned AccessFlags = readable | writeable, class Accessor = default_accessor<ValueT>,
  62. class Mutator = default_mutator<ValueT>>
  63. class property {
  64. public:
  65. // Types.
  66. typedef ValueT value_type;
  67. typedef value_type& reference;
  68. typedef const value_type& const_reference;
  69. typedef Accessor accessor_type;
  70. typedef Mutator mutator_type;
  71.  
  72. // Constructors.
  73. property() : m_accessor(m_value), m_mutator(m_value)
  74. {
  75. // Do nothing.
  76. }
  77.  
  78. property(accessor_type accessor, mutator_type mutator) : m_accessor(accessor), m_mutator(mutator)
  79. {
  80. // Do nothing.
  81. }
  82.  
  83. property(accessor_type accessor) : m_accessor(accessor), m_mutator(m_value)
  84. {
  85. // Do nothing.
  86. }
  87.  
  88. property(mutator_type mutator) : m_accessor(m_value), m_mutator(mutator)
  89. {
  90. // Do nothing.
  91. }
  92.  
  93. property(reference value_ref) : m_accessor(value_ref), m_mutator(value_ref)
  94. {
  95. // Do nothing.
  96. }
  97.  
  98. // Accessors.
  99. const_reference get() const noexcept
  100. {
  101. static_assert((AccessFlags & readable) == readable, "Can't read write-only property.");
  102. return m_accessor();
  103. }
  104.  
  105. const_reference get() noexcept
  106. {
  107. static_assert((AccessFlags & readable) == readable, "Can't read write-only property.");
  108. return m_accessor();
  109. }
  110.  
  111. // Mutators.
  112. void set(const_reference value)
  113. {
  114. static_assert((AccessFlags & readable) == readable, "Can't write to read-only property.");
  115. m_mutator(value);
  116. }
  117.  
  118. void set(value_type&& value)
  119. {
  120. static_assert((AccessFlags & readable) == readable, "Can't write to read-only property.");
  121. m_mutator(value);
  122. }
  123.  
  124. property& operator=(const_reference rhs)
  125. {
  126. const property& lhs(*this);
  127. lhs.set(rhs);
  128. return lhs;
  129. }
  130.  
  131. property& operator=(const property& rhs)
  132. {
  133. const property& lhs(*this);
  134. lhs.set(rhs.get());
  135. return lhs;
  136. }
  137. private:
  138. // Data.
  139. ValueT m_value;
  140. accessor_type m_accessor;
  141. mutator_type m_mutator;
  142. };
  143.  
  144. #include <iostream>
  145.  
  146. /// Custom accessor.
  147. class my_accessor {
  148. public:
  149. my_accessor(const int& value_ref, int& counter_ref) : m_value_ref(value_ref), m_counter_ref(counter_ref)
  150. {
  151. // Do nothing.
  152. }
  153.  
  154. const int& operator()() noexcept
  155. {
  156. ++m_counter_ref;
  157. return m_value_ref;
  158. }
  159. private:
  160. const int& m_value_ref;
  161. int& m_counter_ref;
  162. };
  163.  
  164. /// Example showing a read-only property with a custom accessor which increments a counter whenever the property is
  165. /// accessed.
  166. class foo {
  167. public:
  168. property<int, readable, my_accessor> readonly;
  169. property<int, readable> times_accessed;
  170.  
  171. foo(int value) : m_readonly(value), m_times_accessed(0), readonly(my_accessor(m_readonly, m_times_accessed)),
  172. times_accessed(m_times_accessed)
  173. {
  174. // Do nothing.
  175. }
  176. private:
  177. int m_readonly;
  178. int m_times_accessed;
  179. };
  180.  
  181. int main()
  182. {
  183. foo object(5);
  184. for (int i = 0; i < 5; ++i) {
  185. std::cout << "Times accessed: " << object.times_accessed.get() << '\n';
  186. int tmp = object.readonly.get();
  187. }
  188. std::cout << "Times accessed: " << object.times_accessed.get() << std::endl;
  189. return 0;
  190. }
Success #stdin #stdout 0s 3340KB
stdin
Standard input is empty
stdout
Times accessed: 0
Times accessed: 1
Times accessed: 2
Times accessed: 3
Times accessed: 4
Times accessed: 5