You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

425 lines
12 KiB

  1. /* /////////////////////////////////////////////////////////////////////////
  2. * File: stlsoft/properties/field_properties.hpp
  3. *
  4. * Purpose: Field-based properties.
  5. *
  6. * Created: 6th October 2003
  7. * Updated: 3rd March 2010
  8. *
  9. * Home: http://stlsoft.org/
  10. *
  11. * Copyright (c) 2003-2010, Matthew Wilson and Synesis Software
  12. * All rights reserved.
  13. *
  14. * Redistribution and use in source and binary forms, with or without
  15. * modification, are permitted provided that the following conditions are met:
  16. *
  17. * - Redistributions of source code must retain the above copyright notice, this
  18. * list of conditions and the following disclaimer.
  19. * - Redistributions in binary form must reproduce the above copyright notice,
  20. * this list of conditions and the following disclaimer in the documentation
  21. * and/or other materials provided with the distribution.
  22. * - Neither the name(s) of Matthew Wilson and Synesis Software nor the names of
  23. * any contributors may be used to endorse or promote products derived from
  24. * this software without specific prior written permission.
  25. *
  26. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  27. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  28. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  29. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  30. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  31. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  32. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  33. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  34. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  35. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  36. * POSSIBILITY OF SUCH DAMAGE.
  37. *
  38. * ////////////////////////////////////////////////////////////////////// */
  39. /** \file stlsoft/properties/field_properties.hpp
  40. *
  41. * \brief [C++ only] Definition of the field property implementation
  42. * class templates:
  43. * stlsoft::field_property_get,
  44. * stlsoft::field_property_set,
  45. * stlsoft::field_property_get_external
  46. * and
  47. * stlsoft::field_property_set_external
  48. * (\ref group__library__properties "Properties" Library).
  49. */
  50. #ifndef STLSOFT_INCL_STLSOFT_PROPERTIES_HPP_FIELD_PROPERTIES
  51. #define STLSOFT_INCL_STLSOFT_PROPERTIES_HPP_FIELD_PROPERTIES
  52. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  53. # define STLSOFT_VER_STLSOFT_PROPERTIES_HPP_FIELD_PROPERTIES_MAJOR 4
  54. # define STLSOFT_VER_STLSOFT_PROPERTIES_HPP_FIELD_PROPERTIES_MINOR 0
  55. # define STLSOFT_VER_STLSOFT_PROPERTIES_HPP_FIELD_PROPERTIES_REVISION 3
  56. # define STLSOFT_VER_STLSOFT_PROPERTIES_HPP_FIELD_PROPERTIES_EDIT 32
  57. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  58. /* /////////////////////////////////////////////////////////////////////////
  59. * Compatibility
  60. */
  61. /*
  62. [Incompatibilies-start]
  63. STLSOFT_COMPILER_IS_GCC: __GNUC__ == 3 && defined(__APPLE__)
  64. [Incompatibilies-end]
  65. */
  66. /* /////////////////////////////////////////////////////////////////////////
  67. * Includes
  68. */
  69. #ifndef STLSOFT_INCL_STLSOFT_H_STLSOFT
  70. # include <stlsoft/stlsoft.h>
  71. #endif /* !STLSOFT_INCL_STLSOFT_H_STLSOFT */
  72. /* /////////////////////////////////////////////////////////////////////////
  73. * Namespace
  74. */
  75. #ifndef _STLSOFT_NO_NAMESPACE
  76. namespace stlsoft
  77. {
  78. #endif /* _STLSOFT_NO_NAMESPACE */
  79. /* /////////////////////////////////////////////////////////////////////////
  80. * Classes
  81. */
  82. /** \brief Class template used to define a read-only internal field
  83. * property.
  84. *
  85. \code
  86. class ClassWithReadOnlyProp
  87. {
  88. public: // Member Types
  89. typedef std::string string_type;
  90. typedef int index_type;
  91. public: // Construction
  92. ClassWithReadOnlyProp(char const* instanceName, index_type instanceIndex)
  93. : name(instanceName) // Property value can be initialised inside enclosing class
  94. , index(1) // Property value can be initialised inside enclosing class
  95. {}
  96. public: // Operations
  97. void ReBadge(char const* newInstanceName, index_type newInstanceIndex)
  98. {
  99. name = newInstanceName; // Property value can be assigned inside enclosing class
  100. index = newInstanceIndex; // Property value can be assigned inside enclosing class
  101. }
  102. public: // Properties
  103. stlsoft::field_property_get<index_type, index_type, ClassWithReadOnlyProp> index;
  104. stlsoft::field_property_get<string_type, string_type const&, ClassWithReadOnlyProp> name;
  105. };
  106. . . .
  107. ClassWithReadOnlyProp c("Object-#1", 1);
  108. int index = c.index; // Ok: access the value of the read-only property
  109. std::string const &name = c.name; // Ok: access the value of the read-only property
  110. c.index = 2; // Compile error: cannnot write to the read-only property
  111. c.name = "new name"; // Compile error: cannnot write to the read-only property
  112. \endcode
  113. *
  114. * \ingroup group__library__properties
  115. */
  116. template< ss_typename_param_k V /* The actual property value type */
  117. , ss_typename_param_k R /* The reference type */
  118. , ss_typename_param_k C /* The enclosing class */
  119. >
  120. class field_property_get
  121. {
  122. public:
  123. typedef V value_type;
  124. typedef R reference_type;
  125. typedef C container_type;
  126. typedef field_property_get<V, R, C> class_type;
  127. # if defined(STLSOFT_COMPILER_IS_DMC)
  128. public:
  129. # else /* ? compiler */
  130. private:
  131. # endif /* compiler */
  132. field_property_get()
  133. {}
  134. private:
  135. ss_explicit_k field_property_get(reference_type value)
  136. : m_value(value)
  137. {}
  138. class_type& operator =(reference_type value)
  139. {
  140. m_value = value;
  141. return *this;
  142. }
  143. STLSOFT_DECLARE_TEMPLATE_PARAM_AS_FRIEND(C);
  144. public:
  145. /// Provides read-only access to the property
  146. operator reference_type () const
  147. {
  148. return m_value;
  149. }
  150. // Members
  151. private:
  152. value_type m_value;
  153. // Not to be implemented
  154. private:
  155. field_property_get(class_type const&);
  156. class_type& operator =(class_type const&);
  157. };
  158. /** \brief Class template used to define a write-only internal field
  159. * property.
  160. *
  161. \code
  162. class ClassWithWriteOnlyProp
  163. {
  164. public:
  165. stlsoft::field_property_set<int, int, ClassWithWriteOnlyProp> prop2;
  166. };
  167. ClassWithWriteOnlyProp c;
  168. int i;
  169. c.prop2 = i; // Ok: Write to the write-only property
  170. i = c.prop2; // Compile error: Cannot access the value of the write-only property
  171. \endcode
  172. *
  173. * \ingroup group__library__properties
  174. */
  175. template< ss_typename_param_k V /* The actual property value type */
  176. , ss_typename_param_k R /* The reference type */
  177. , ss_typename_param_k C /* The enclosing class */
  178. >
  179. class field_property_set
  180. {
  181. public:
  182. typedef V value_type;
  183. typedef R reference_type;
  184. typedef C container_type;
  185. typedef field_property_set<V, R, C> class_type;
  186. # if defined(STLSOFT_COMPILER_IS_DMC)
  187. public:
  188. # else /* ? compiler */
  189. private:
  190. # endif /* compiler */
  191. field_property_set()
  192. {}
  193. private:
  194. ss_explicit_k field_property_set(reference_type value)
  195. : m_value(value)
  196. {}
  197. operator reference_type () const
  198. {
  199. return m_value;
  200. }
  201. STLSOFT_DECLARE_TEMPLATE_PARAM_AS_FRIEND(C);
  202. public:
  203. /// Provides write-only access to the property
  204. class_type& operator =(reference_type value)
  205. {
  206. m_value = value;
  207. return *this;
  208. }
  209. private:
  210. value_type m_value;
  211. // Not to be implemented
  212. private:
  213. field_property_set(class_type const&);
  214. class_type& operator =(class_type const&);
  215. };
  216. #if 1
  217. /** Class template that defines a read-only external property
  218. *
  219. * \ingroup group__library__properties
  220. */
  221. template< ss_typename_param_k V /* The actual property value type */
  222. , ss_typename_param_k R /* The reference type */
  223. >
  224. class field_property_get_external
  225. {
  226. public:
  227. typedef V value_type;
  228. typedef R reference_type;
  229. typedef field_property_get_external<V, R> class_type;
  230. public:
  231. field_property_get_external(value_type& value)
  232. : m_value(value)
  233. {}
  234. // Accessors
  235. public:
  236. /// Provides read-only access to the property
  237. operator reference_type() const
  238. {
  239. return m_value;
  240. }
  241. // Members
  242. private:
  243. value_type &m_value;
  244. };
  245. /** Class template that defines a write-only external property
  246. *
  247. * \ingroup group__library__properties
  248. */
  249. template< ss_typename_param_k V /* The actual property value type */
  250. , ss_typename_param_k R /* The reference type */
  251. >
  252. class field_property_set_external
  253. {
  254. public:
  255. typedef V value_type;
  256. typedef R reference_type;
  257. typedef field_property_get_external<V, R> class_type;
  258. public:
  259. field_property_set_external(value_type& value)
  260. : m_value(value)
  261. {}
  262. // Accessors
  263. public:
  264. /// Provides write-only access to the property
  265. field_property_set_external& operator =(reference_type value)
  266. {
  267. m_value = value;
  268. return *this;
  269. }
  270. // Members
  271. private:
  272. value_type &m_value;
  273. };
  274. #else /* ? 1 */
  275. template< ss_typename_param_k V /* The actual property value type */
  276. , ss_typename_param_k R /* The reference type */
  277. , ss_ptrdiff_t (*PFnOff)() /* Pointer to function providing offset from value to property */
  278. >
  279. class field_property_get_external
  280. {
  281. public:
  282. typedef V value_type;
  283. typedef R reference_type;
  284. typedef field_property_get_external<V, R, PFnOff> class_type;
  285. // Accessors
  286. public:
  287. /// Provides read-only access to the property
  288. operator reference_type() const
  289. {
  290. ss_ptrdiff_t offset = (*PFnOff)();
  291. value_type *pV = (value_type*)((ss_byte_t*)this - offset);
  292. return *pV;
  293. }
  294. };
  295. template< ss_typename_param_k V /* The actual property value type */
  296. , ss_typename_param_k R /* The reference type */
  297. , ss_ptrdiff_t (*PFnOff)() /* Pointer to function providing offset from value to property */
  298. >
  299. class field_property_set_external
  300. {
  301. public:
  302. typedef V value_type;
  303. typedef R reference_type;
  304. typedef field_property_get_external<V, R, PFnOff> class_type;
  305. // Accessors
  306. public:
  307. /// Provides write-only access to the property
  308. field_property_set_external& operator =(reference_type value)
  309. {
  310. ss_ptrdiff_t offset = (*PFnOff)();
  311. value_type *pV = (value_type*)((ss_byte_t*)this - offset);
  312. *pV = value;
  313. return *this;
  314. }
  315. };
  316. #endif /* 0 */
  317. /* /////////////////////////////////////////////////////////////////////////
  318. * IOStream compatibility
  319. */
  320. // field_property_get
  321. template< ss_typename_param_k V
  322. , ss_typename_param_k R
  323. , ss_typename_param_k C
  324. , ss_typename_param_k S
  325. >
  326. inline S& operator <<( S& s
  327. , field_property_get<V, R, C> const& prop)
  328. {
  329. s << static_cast<R>(prop);
  330. return s;
  331. }
  332. // field_property_get_external
  333. template< ss_typename_param_k V
  334. , ss_typename_param_k R
  335. , ss_typename_param_k S
  336. >
  337. inline S& operator <<( S& s
  338. , field_property_get_external<V, R> const& prop)
  339. {
  340. s << static_cast<R>(prop);
  341. return s;
  342. }
  343. ////////////////////////////////////////////////////////////////////////////
  344. // Unit-testing
  345. #ifdef STLSOFT_UNITTEST
  346. # include "./unittest/field_properties_unittest_.h"
  347. #endif /* STLSOFT_UNITTEST */
  348. /* ////////////////////////////////////////////////////////////////////// */
  349. #ifndef _STLSOFT_NO_NAMESPACE
  350. } // namespace stlsoft
  351. #endif /* _STLSOFT_NO_NAMESPACE */
  352. /* ////////////////////////////////////////////////////////////////////// */
  353. #endif /* !STLSOFT_INCL_STLSOFT_PROPERTIES_HPP_FIELD_PROPERTIES */
  354. /* ///////////////////////////// end of file //////////////////////////// */