lean cpp library
A lean C++ library providing efficient utility classes for high-performance C++ applications.
|
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