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