lean cpp library
A lean C++ library providing efficient utility classes for high-performance C++ applications.
property_accessors.h
00001 /*****************************************************/
00002 /* lean Properties              (c) Tobias Zirr 2011 */
00003 /*****************************************************/
00004 
00005 #ifndef LEAN_PROPERTIES_PROPERTY_ACCESSORS
00006 #define LEAN_PROPERTIES_PROPERTY_ACCESSORS
00007 
00008 // Use short file names in logging
00009 #ifndef LEAN_DEFAULT_FILE_MACRO
00010     #line __LINE__ "property_accessors.h"
00011 #endif
00012 
00013 #include <typeinfo>
00014 #include "../lean.h"
00015 #include "../meta/strip.h"
00016 #include "../logging/log.h"
00017 #include "property.h"
00018 
00019 namespace lean
00020 {
00021 namespace properties
00022 {
00023 
00024 namespace impl
00025 {
00026 
00027 struct property_logging_policy
00028 {
00029     template <class Property>
00030     static LEAN_NOINLINE void type_mismatch(const std::type_info &value)
00031     {
00032         LEAN_LOG_ERROR("Property / value type mismatch: "
00033             << typeid(Property).name() << " vs. " << value.name());
00034     }
00035 
00036     static LEAN_NOINLINE void count_mismatch(size_t propertyCount, size_t valueCount)
00037     {
00038         LEAN_LOG_ERROR("Property / value count mismatch: "
00039             << propertyCount << " vs. " << valueCount);
00040     }
00041 };
00042 
00043 typedef property_logging_policy property_error_policy;
00044 
00045 } // namespace
00046 
00047 #pragma region property_constant
00048 
00050 template <class Class, class Value>
00051 class property_constant : public property_getter<Class>
00052 {
00053 private:
00054     const Value *m_constantValues;
00055     size_t m_count;
00056 
00057 public:
00058     typedef typename strip_modifiers<Value>::type value_type;
00059 
00060     property_constant(const Value *constantValues, size_t count)
00061         : m_constantValues(constantValues),
00062         m_count(count) { };
00063 
00065     bool operator ()(const Class &object, const std::type_info &type, void *values, size_t count) const
00066     {
00067         if (type == typeid(value_type))
00068         {
00069             std::copy_n(m_constantValues, min(count, m_count), static_cast<value_type*>(values));
00070             return true;
00071         }
00072         else
00073         {
00074             impl::property_error_policy::type_mismatch<value_type>(type);
00075             return false;
00076         }
00077     }
00078 
00079     property_constant* clone() const { return new property_constant(*this); }
00080     void destroy() const { delete this; }
00081 };
00082 
00084 template <class Class, class Value>
00085 LEAN_INLINE property_constant<Class, Value> make_property_constant(const Value *constantValues, size_t count)
00086 {
00087     return property_constant<Class, Value>(constantValues, count);
00088 }
00089 
00090 #pragma endregion
00091 
00092 namespace impl
00093 {
00094 
00095 template <class UnionValue, class Value>
00096 struct union_helper
00097 {
00098     LEAN_STATIC_ASSERT_MSG_ALT(
00099         (sizeof(UnionValue) >= sizeof(Value))
00100             ? (sizeof(UnionValue) % sizeof(Value) == 0)
00101             : (sizeof(Value) % sizeof(UnionValue) == 0),
00102         "Size of union type must be positive multiple of value type.",
00103         Size_of_union_type_must_be_positive_multiple_of_value_type);
00104 
00105     // Divide by zero prevented by if clause
00106     #pragma warning(push)
00107     #pragma warning(disable : 4723)
00108 
00109     template <class Count>
00110     static LEAN_INLINE Count union_count(Count count)
00111     {
00112         if (sizeof(UnionValue) >= sizeof(Value))
00113             return count / (sizeof(UnionValue) / sizeof(Value));
00114         else
00115             return count * (sizeof(Value) / sizeof(UnionValue));
00116     }
00117 
00118     #pragma warning(pop)
00119 };
00120 
00121 } // namespace
00122 
00123 #pragma region property_n_accessors
00124 
00126 template <class Class, class UnionValue, class Count, class Return,
00127     Return (Class::*Setter)(const UnionValue*, Count),
00128     class Value = UnionValue, class BaseClass = Class>
00129 class property_n_setter : public property_setter<BaseClass>
00130 {
00131 public:
00132     typedef typename strip_modifiers<Value>::type value_type;
00133     typedef typename strip_modifiers<UnionValue>::type union_type;
00134 
00136     bool operator ()(BaseClass &baseObject, const std::type_info &type, const void *values, size_t count)
00137     {
00138         typedef impl::union_helper<union_type, value_type> union_helper;
00139 
00140         Class &object = static_cast<Class&>(baseObject);
00141 
00142         if (type == typeid(value_type))
00143         {
00144             (object.*Setter)(
00145                     reinterpret_cast<const union_type*>( static_cast<const value_type*>(values) ),
00146                     static_cast<Count>( union_helper::union_count(count) )
00147                 );
00148             return true;
00149         }
00150         else if (type == typeid(union_type))
00151         {
00152             (object.*Setter)(
00153                     static_cast<const union_type*>( values ),
00154                     static_cast<Count>( count )
00155                 );
00156             return true;
00157         }
00158         else
00159         {
00160             impl::property_error_policy::type_mismatch<value_type>(type);
00161             return false;
00162         }
00163     }
00164 
00165     property_n_setter* clone() const { return new property_n_setter(*this); }
00166     void destroy() const { delete this; }
00167 };
00168 
00170 template <class Class, class UnionValue, class Count, class Return,
00171     Return (Class::*Getter)(UnionValue*, Count) const,
00172     class Value = UnionValue, class BaseClass = Class>
00173 class property_n_getter : public property_getter<BaseClass>
00174 {
00175 public:
00176     typedef typename strip_modifiers<Value>::type value_type;
00177     typedef typename strip_modifiers<UnionValue>::type union_type;
00178     
00180     bool operator ()(const BaseClass &baseObject, const std::type_info &type, void *values, size_t count) const
00181     {
00182         typedef impl::union_helper<union_type, value_type> union_helper;
00183 
00184         const Class &object = static_cast<const Class&>(baseObject);
00185 
00186         if (type == typeid(value_type))
00187         {
00188             (object.*Getter)(
00189                     reinterpret_cast<union_type*>( static_cast<value_type*>(values) ),
00190                     static_cast<Count>( union_helper::union_count(count) )
00191                 );
00192             return true;
00193         }
00194         else if (type == typeid(union_type))
00195         {
00196             (object.*Getter)(
00197                     static_cast<union_type*>( values ),
00198                     static_cast<Count>( count )
00199                 );
00200             return true;
00201         }
00202         else
00203         {
00204             impl::property_error_policy::type_mismatch<value_type>(type);
00205             return false;
00206         }
00207     }
00208 
00209     property_n_getter* clone() const { return new property_n_getter(*this); }
00210     void destroy() const { delete this; }
00211 };
00212 
00214 template <class Class, class UnionValue, class Count, class Return,
00215     class Value = UnionValue, class BaseClass = Class>
00216 struct property_n_accessor_binder
00217 {
00219     template <Return (Class::*Setter)(const UnionValue*, Count)>
00220     LEAN_INLINE property_n_setter<Class, UnionValue, Count, Return, Setter, Value, BaseClass> bind_setter()
00221     {
00222         return property_n_setter<Class, UnionValue, Count, Return, Setter, Value, BaseClass>();
00223     }
00224 
00226     template <Return (Class::*Getter)(UnionValue*, Count) const>
00227     LEAN_INLINE property_n_getter<Class, UnionValue, Count, Return, Getter, Value, BaseClass> bind_getter()
00228     {
00229         return property_n_getter<Class, UnionValue, Count, Return, Getter, Value, BaseClass>();
00230     }
00231 
00233     template <class NewValue>
00234     LEAN_INLINE property_n_accessor_binder<Class, UnionValue, Count, Return, NewValue, BaseClass> set_value()
00235     {
00236         return property_n_accessor_binder<Class, UnionValue, Count, Return, NewValue, BaseClass>();
00237     }
00238 
00240     template <class NewBase>
00241     LEAN_INLINE property_n_accessor_binder<Class, UnionValue, Count, Return, Value, NewBase> set_base()
00242     {
00243         return property_n_accessor_binder<Class, UnionValue, Count, Return, Value, NewBase>();
00244     }
00245 };
00246 
00248 template <class Class, class UnionValue, class Count, class Return>
00249 LEAN_INLINE property_n_accessor_binder<Class, UnionValue, Count, Return>
00250     deduce_accessor_binder(Return (Class::*)(const UnionValue*, Count))
00251 {
00252     return property_n_accessor_binder<Class, UnionValue, Count, Return>();
00253 }
00254 
00256 template <class Class, class UnionValue, class Count, class Return>
00257 LEAN_INLINE property_n_accessor_binder<Class, UnionValue, Count, Return>
00258     deduce_accessor_binder(Return (Class::*)(UnionValue*, Count) const)
00259 {
00260     return property_n_accessor_binder<Class, UnionValue, Count, Return>();
00261 }
00262 
00263 #pragma endregion
00264 
00265 #pragma region property_c_accessors
00266 
00267 namespace impl
00268 {
00269 
00270 template <class Class, class ValueArg, int ArgCount = 1, class Return = void>
00271 struct property_c_helper;
00272 
00273 template <class Class, class ValueArg, class Return>
00274 struct property_c_helper<Class, ValueArg, 1, Return>
00275 {
00276     typedef Return (Class::*setter_type)(ValueArg);
00277     typedef Return (Class::*getter_type)(ValueArg) const;
00278     static const int argument_count = 1;
00279 
00280     template <class Value>
00281     static LEAN_INLINE void set(Class &object, setter_type setter, const Value *values)
00282     {
00283         (object.*setter)(*values);
00284     }
00285     template <class Value>
00286     static LEAN_INLINE void get(const Class &object, getter_type getter, Value *values)
00287     {
00288         (object.*getter)(*values);
00289     }
00290 };
00291 
00292 template <class Class, class ValueArg, class Return>
00293 struct property_c_helper<Class, ValueArg, 2, Return>
00294 {
00295     typedef Return (Class::*setter_type)(ValueArg, ValueArg);
00296     typedef Return (Class::*getter_type)(ValueArg, ValueArg) const;
00297     static const int argument_count = 2;
00298 
00299     template <class Value>
00300     static LEAN_INLINE void set(Class &object, setter_type setter, const Value *values)
00301     {
00302         (object.*setter)(*values, values[1]);
00303     }
00304     template <class Value>
00305     static LEAN_INLINE void get(const Class &object, getter_type getter, Value *values)
00306     {
00307         (object.*getter)(*values, values[1]);
00308     }
00309 };
00310 
00311 template <class Class, class ValueArg, class Return>
00312 struct property_c_helper<Class, ValueArg, 3, Return>
00313 {
00314     typedef Return (Class::*setter_type)(ValueArg, ValueArg, ValueArg);
00315     typedef Return (Class::*getter_type)(ValueArg, ValueArg, ValueArg) const;
00316     static const int argument_count = 3;
00317 
00318     template <class Value>
00319     static LEAN_INLINE void set(Class &object, setter_type setter, const Value *values)
00320     {
00321         (object.*setter)(*values, values[1], values[2]);
00322     }
00323     template <class Value>
00324     static LEAN_INLINE void get(const Class &object, getter_type getter, Value *values)
00325     {
00326         (object.*getter)(*values, values[1], values[2]);
00327     }
00328 };
00329 
00330 template <class Class, class ValueArg, class Return>
00331 struct property_c_helper<Class, ValueArg, 4, Return>
00332 {
00333     typedef Return (Class::*setter_type)(ValueArg, ValueArg, ValueArg, ValueArg);
00334     typedef Return (Class::*getter_type)(ValueArg, ValueArg, ValueArg, ValueArg) const;
00335     static const int argument_count = 4;
00336 
00337     template <class Value>
00338     static LEAN_INLINE void set(Class &object, setter_type setter, const Value *values)
00339     {
00340         (object.*setter)(*values, values[1], values[2], values[3]);
00341     }
00342     template <class Value>
00343     static LEAN_INLINE void get(const Class &object, getter_type getter, Value *values)
00344     {
00345         (object.*getter)(*values, values[1], values[2], values[3]);
00346     }
00347 };
00348 
00349 } // namespace
00350 
00352 template <class Class, class UnionValueArg, int ArgCount, class Return,
00353     typename impl::property_c_helper<Class, UnionValueArg, ArgCount, Return>::setter_type Setter,
00354     class ValueArg = UnionValueArg, class BaseClass = Class>
00355 class property_c_setter : public property_setter<BaseClass>
00356 {
00357 private:
00358     typedef impl::property_c_helper<Class, UnionValueArg, ArgCount, Return> setter_helper;
00359 
00360 public:
00361     typedef typename strip_modifiers<typename strip_reference<ValueArg>::type>::type value_type;
00362     typedef typename strip_modifiers<typename strip_reference<UnionValueArg>::type>::type union_type;
00363 
00365     bool operator ()(BaseClass &baseObject, const std::type_info &type, const void *values, size_t count)
00366     {
00367         typedef impl::union_helper<union_type, value_type> union_helper;
00368         
00369         Class &object = static_cast<Class&>(baseObject);
00370 
00371         if (type == typeid(value_type))
00372         {
00373             size_t unionCount = union_helper::union_count(count);
00374 
00375             if (unionCount >= setter_helper::argument_count)
00376             {
00377                 setter_helper::set(
00378                     object, Setter,
00379                     reinterpret_cast<const union_type*>( static_cast<const value_type*>(values) ) );
00380                 return true;
00381             }
00382             else
00383                 impl::property_error_policy::count_mismatch(setter_helper::argument_count, unionCount);
00384         }
00385         else if (type == typeid(union_type))
00386         {
00387             if (count >= setter_helper::argument_count)
00388             {
00389                 setter_helper::set(
00390                     object, Setter,
00391                     static_cast<const union_type*>(values) );
00392                 return true;
00393             }
00394             else
00395                 impl::property_error_policy::count_mismatch(setter_helper::argument_count, count);
00396         }
00397         else
00398             impl::property_error_policy::type_mismatch<value_type>(type);
00399 
00400         return false;
00401     }
00402 
00403     property_c_setter* clone() const { return new property_c_setter(*this); }
00404     void destroy() const { delete this; }
00405 };
00406 
00408 template <class Class, class UnionValueArg, int ArgCount, class Return,
00409     typename impl::property_c_helper<Class, UnionValueArg, ArgCount, Return>::getter_type Getter,
00410     class ValueArg = UnionValueArg, class BaseClass = Class>
00411 class property_c_getter : public property_getter<BaseClass>
00412 {
00413 private:
00414     typedef impl::property_c_helper<Class, UnionValueArg, ArgCount, Return> getter_helper;
00415 
00416 public:
00417     typedef typename strip_modifiers<typename strip_reference<ValueArg>::type>::type value_type;
00418     typedef typename strip_modifiers<typename strip_reference<UnionValueArg>::type>::type union_type;
00419 
00421     bool operator ()(const BaseClass &object, const std::type_info &type, void *values, size_t count) const
00422     {
00423         typedef impl::union_helper<union_type, value_type> union_helper;
00424 
00425         const Class &object = static_cast<const Class&>(baseObject);
00426 
00427         if (type == typeid(value_type))
00428         {
00429             size_t unionCount = union_helper::union_count(count);
00430 
00431             if (unionCount >= getter_helper::argument_count)
00432             {
00433                 getter_helper::get(
00434                     object, Getter,
00435                     reinterpret_cast<union_type*>( static_cast<value_type*>(values) ) );
00436                 return true;
00437             }
00438             else
00439                 impl::property_error_policy::count_mismatch(getter_helper::argument_count, unionCount);
00440         }
00441         else if (type == typeid(union_type))
00442         {
00443             if (count >= getter_helper::argument_count)
00444             {
00445                 getter_helper::get(
00446                     object, Getter,
00447                     static_cast<union_type*>(values) );
00448                 return true;
00449             }
00450             else
00451                 impl::property_error_policy::count_mismatch(getter_helper::argument_count, count);
00452         }
00453         else
00454             impl::property_error_policy::type_mismatch<value_type>(type);
00455 
00456         return false;
00457     }
00458 
00459     property_c_getter* clone() const { return new property_c_getter(*this); }
00460     void destroy() const { delete this; }
00461 };
00462 
00464 template <class Class, class UnionValueArg, int ArgCount, class Return,
00465     class ValueArg = UnionValueArg, class BaseClass = Class>
00466 struct property_c_accessor_binder
00467 {
00469     template <typename impl::property_c_helper<Class, UnionValueArg, ArgCount, Return>::setter_type Setter>
00470     LEAN_INLINE property_c_setter<Class, UnionValueArg, ArgCount, Return, Setter, ValueArg, BaseClass> bind_setter()
00471     {
00472         return property_c_setter<Class, UnionValueArg, ArgCount, Return, Setter, ValueArg, BaseClass>();
00473     }
00474     
00476     template <typename impl::property_c_helper<Class, UnionValueArg, ArgCount, Return>::getter_type Getter>
00477     LEAN_INLINE property_c_getter<Class, UnionValueArg, ArgCount, Return, Getter, ValueArg, BaseClass> bind_getter()
00478     {
00479         return property_c_getter<Class, UnionValueArg, ArgCount, Return, Getter, ValueArg, BaseClass>();
00480     }
00481 
00483     template <class NewValue>
00484     LEAN_INLINE property_c_accessor_binder<Class, UnionValueArg, ArgCount, Return, NewValue, BaseClass> set_value()
00485     {
00486         return property_c_accessor_binder<Class, UnionValueArg, ArgCount, Return, NewValue, BaseClass>();
00487     }
00488 
00490     template <class NewBase>
00491     LEAN_INLINE property_c_accessor_binder<Class, UnionValueArg, ArgCount, Return, ValueArg, NewBase> set_base()
00492     {
00493         return property_c_accessor_binder<Class, UnionValueArg, ArgCount, Return, ValueArg, NewBase>();
00494     }
00495 };
00496 
00498 template <class Class, class UnionValueArg, class Return>
00499 LEAN_INLINE property_c_accessor_binder<Class, UnionValueArg, 1, Return>
00500     deduce_accessor_binder(Return (Class::*)(UnionValueArg))
00501 {
00502     return property_c_accessor_binder<Class, UnionValueArg, 1, Return>();
00503 }
00505 template <class Class, class UnionValueArg, class Return>
00506 LEAN_INLINE property_c_accessor_binder<Class, UnionValueArg, 1, Return>
00507     deduce_accessor_binder(Return (Class::*)(UnionValueArg) const)
00508 {
00509     return property_c_accessor_binder<Class, UnionValueArg, 1, Return>();
00510 }
00511 
00513 template <class Class, class UnionValueArg, class Return>
00514 LEAN_INLINE property_c_accessor_binder<Class, UnionValueArg, 2, Return>
00515     deduce_accessor_binder(Return (Class::*)(UnionValueArg, UnionValueArg))
00516 {
00517     return property_c_accessor_binder<Class, UnionValueArg, 2, Return>();
00518 }
00520 template <class Class, class UnionValueArg, class Return>
00521 LEAN_INLINE property_c_accessor_binder<Class, UnionValueArg, 2, Return>
00522     deduce_accessor_binder(Return (Class::*)(UnionValueArg, UnionValueArg) const)
00523 {
00524     return property_c_accessor_binder<Class, UnionValueArg, 2, Return>();
00525 }
00526 
00528 template <class Class, class UnionValueArg, class Return>
00529 LEAN_INLINE property_c_accessor_binder<Class, UnionValueArg, 3, Return>
00530     deduce_accessor_binder(Return (Class::*)(UnionValueArg, UnionValueArg, UnionValueArg))
00531 {
00532     return property_c_accessor_binder<Class, UnionValueArg, 3, Return>();
00533 }
00535 template <class Class, class UnionValueArg, class Return>
00536 LEAN_INLINE property_c_accessor_binder<Class, UnionValueArg, 3, Return>
00537     deduce_accessor_binder(Return (Class::*)(UnionValueArg, UnionValueArg, UnionValueArg) const)
00538 {
00539     return property_c_accessor_binder<Class, UnionValueArg, 3, Return>();
00540 }
00541 
00543 template <class Class, class UnionValueArg, class Return>
00544 LEAN_INLINE property_c_accessor_binder<Class, UnionValueArg, 4, Return>
00545     deduce_accessor_binder(Return (Class::*)(UnionValueArg, UnionValueArg, UnionValueArg, UnionValueArg))
00546 {
00547     return property_c_accessor_binder<Class, UnionValueArg, 4, Return>();
00548 }
00550 template <class Class, class UnionValueArg, class Return>
00551 LEAN_INLINE property_c_accessor_binder<Class, UnionValueArg, 4, Return>
00552     deduce_accessor_binder(Return (Class::*)(UnionValueArg, UnionValueArg, UnionValueArg, UnionValueArg) const)
00553 {
00554     return property_c_accessor_binder<Class, UnionValueArg, 4, Return>();
00555 }
00556 
00557 #pragma endregion
00558 
00559 #pragma region property_r_accessors
00560 
00562 template <class Class, class UnionValueReturn,
00563     UnionValueReturn (Class::*Getter)() const,
00564     class ValueReturn = UnionValueReturn, class BaseClass = Class>
00565 class property_r_getter : public property_getter<BaseClass>
00566 {
00567 public:
00568     typedef typename strip_modifiers<typename strip_reference<ValueReturn>::type>::type value_type;
00569     typedef typename strip_modifiers<typename strip_reference<UnionValueReturn>::type>::type union_type;
00570 
00572     bool operator ()(const BaseClass &baseObject, const std::type_info &type, void *values, size_t count) const
00573     {
00574         typedef impl::union_helper<union_type, value_type> union_helper;
00575 
00576         const Class &object = static_cast<const Class&>(baseObject);
00577 
00578         if (type == typeid(value_type))
00579         {
00580             size_t unionCount = union_helper::union_count(count);
00581 
00582             if (unionCount >= 1)
00583             {
00584                 *reinterpret_cast<union_type*>( static_cast<value_type*>(values) ) = (object.*Getter)();
00585                 return true;
00586             }
00587             else
00588                 impl::property_error_policy::count_mismatch(1, unionCount);
00589         }
00590         else if (type == typeid(union_type))
00591         {
00592             if (count >= 1)
00593             {
00594                 *static_cast<union_type*>(values) = (object.*Getter)();
00595                 return true;
00596             }
00597             else
00598                 impl::property_error_policy::count_mismatch(1, count);
00599         }
00600         else
00601             impl::property_error_policy::type_mismatch<value_type>(type);
00602 
00603         return false;
00604     }
00605 
00606     property_r_getter* clone() const { return new property_r_getter(*this); }
00607     void destroy() const { delete this; }
00608 };
00609 
00611 template <class Class, class UnionValueReturn,
00612     class ValueReturn = UnionValueReturn, class BaseClass = Class>
00613 struct property_r_accessor_binder
00614 {
00616     template <UnionValueReturn (Class::*Getter)() const>
00617     LEAN_INLINE property_r_getter<Class, UnionValueReturn, Getter, ValueReturn, BaseClass> bind_getter()
00618     {
00619         return property_r_getter<Class, UnionValueReturn, Getter, ValueReturn, BaseClass>();
00620     }
00621 
00623     template <class NewValue>
00624     LEAN_INLINE property_r_accessor_binder<Class, UnionValueReturn, NewValue, BaseClass> set_value()
00625     {
00626         return property_r_accessor_binder<Class, UnionValueReturn, NewValue, BaseClass>();
00627     }
00628 
00630     template <class NewBase>
00631     LEAN_INLINE property_r_accessor_binder<Class, UnionValueReturn, ValueReturn, NewBase> set_base()
00632     {
00633         return property_r_accessor_binder<Class, UnionValueReturn, ValueReturn, NewBase>();
00634     }
00635 };
00636 
00638 template <class Class, class UnionValueReturn>
00639 LEAN_INLINE property_r_accessor_binder<Class, UnionValueReturn>
00640     deduce_accessor_binder(UnionValueReturn (Class::*Getter)() const)
00641 {
00642     return property_r_accessor_binder<Class, UnionValueReturn>();
00643 }
00644 
00645 #pragma endregion
00646 
00647 } // namespace
00648 
00649 using properties::make_property_constant;
00650 
00651 } // namespace
00652 
00656 
00658 #define LEAN_MAKE_PROPERTY_CONSTANT(clazz, constants, count) ::lean::properties::make_property_constant<clazz>(constants, count)
00659 
00661 #define LEAN_MAKE_PROPERTY_SETTER(setter) ::lean::properties::deduce_accessor_binder(setter).bind_setter<setter>()
00662 
00663 #define LEAN_MAKE_PROPERTY_GETTER(getter) ::lean::properties::deduce_accessor_binder(getter).bind_getter<getter>()
00664 
00666 #define LEAN_MAKE_PROPERTY_SETTER_UNION(setter, value_type) ::lean::properties::deduce_accessor_binder(setter).set_value<value_type>().bind_setter<setter>()
00667 
00668 #define LEAN_MAKE_PROPERTY_GETTER_UNION(getter, value_type) ::lean::properties::deduce_accessor_binder(getter).set_value<value_type>().bind_getter<getter>()
00669 
00671 
00672 #endif