Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[3.139.82.23] |
|
Сообщ.
#1
,
|
|
|
Вот опять всплыла тема про property, в ней была ссылка на RSDN ( http://www.rsdn.ru/article/vcpp/props.xml ),
и раньше видет эту статейку но тогда я еще на читал Александреску, а сейчас посмотрел..., сразу захотелось подпатчить код про property. Вот представляю на суд след. код. namespace detail { // определяем свойства для property, типы которые будут фигурировать // в функциях set, get. А так же сигнатуры самих функций, чтобы был простор // для маневра. template< typename T, typename U > struct property_traits { typedef T type; typedef T & reference_type; typedef const T & const_reference_type; typedef type ( U::* getter_type )() const; typedef void ( U::* setter_type )( const_reference_type ); }; // частный случай, сделаем так, чтобы property для типа int не извращалось // с передачей константной ссылки, а чтобы передавалось по значению. template< typename U > struct property_traits< int, U > { typedef int type; typedef int reference_type; typedef int const_reference_type; typedef type ( U::* getter_type )() const; typedef void ( U::* setter_type )( const_reference_type ); }; }; // Наше property, прошу обратить внимание на параметры шаблона, мы шаблон // специализируем вместе с сигнатурой функций, это позволяет нам избавиться от // хранения указателей на функции в нутри шаблона, а это по 12 байт на указатель! template< typename T, typename U, detail::property_traits< T, U >::getter_type Getter, detail::property_traits< T, U >::setter_type Setter > class property { private: U & m_owner; private: property & operator = ( const property & ); public: typedef detail::property_traits< T, U > traits; typedef traits::type type; property( U & owner ): m_owner( owner ) { } inline operator type () const { return ( m_owner.* Getter )(); } inline property & operator = ( traits::const_reference_type value ) { return ( m_owner.* Setter )( value ), ( * this ); } }; // Вот и все, разворачиваеться в несколько строчек асма при работе, занимает 4 байта (или столько, сколько отводиться под ссылку). юзается в классе так: property< int, PC, &PC::getValue, &PC::setValue > prop1; property< SomeClass, PC, &PC::getSomeClass, &PC::setSomeClass > prop2; затем в конструкторе: prop1( *this ), prop2( *this ){} функции get, set, разумеется, должны быть. Что хотелось бы обсудить помимо замечаний/предложений: 1) не уверен в правильности выбора ссылки для хранения объекта класса, с одной стороны это заставляет на этапе компиляции проверить инициализацию property, с другой возможны трудности ( лень ) с описанием нескольких конструкторов класса с property 2) Не получилось переопределить read_only property, с тем же именем ( property ) Возможно компилятор не позволил..., возможно получиться у Вас ? 3) Приходиться брать адрес функции, а для inline это чревато тем что она перестанет быть inline. |
Сообщ.
#2
,
|
|
|
Цитата Sazabis @ 3) Приходиться брать адрес функции, а для inline это чревато тем что она перестанет быть inline. Читаем последнюю книгку Саттера. inline - лишь подсказка компилятору. Поверь, он (в некотором отношении) гораздо умней разработчика, и сам в состоянии решить - какие функции, когда и как подставлять. Ты бы, кстати, решил проблемку по-интереснее - как избавиться от инициализации пропертей в конструкторе? Цитата Sazabis @ 2) Не получилось переопределить read_only property, с тем же именем ( property ) Возможно компилятор не позволил..., возможно получиться у Вас ? Попробуй detail::property_traits< T, U >::setter_type Setter указать значение по умолчанию в виде NULL. |
Сообщ.
#3
,
|
|
|
А почему ссылка? property - это же, по сути, переменная. Почему она не хранит свое значение? U - это класс-хозяин свойства? Может сделать его другом и создать в property защищенные методы чтения и записи значения? Заодно добавить в шаблон еще один параметр T def_value=T(), которым свойство инициализируется.
|
Сообщ.
#4
,
|
|
|
Цитата Flex Ferrum @ Читаем последнюю книгку Саттера. inline - лишь подсказка компилятору. Поверь, он (в некотором отношении) гораздо умней разработчика, и сам в состоянии решить - какие функции, когда и как подставлять. Это я в курсе, и на форуме создавал тему по inline. Только книжки хорошо, а в жизни еще не все компиляторы такие умные. Хотя в этом вопросе тут врят ли можно достичь чего то лучше, но раз это можно на асме сделать проще, возможно можено написать код так, чтобы не нужна была супер умность компилятора. Borland например не развертывает inline , вроде бы. Цитата Flex Ferrum @ Попробуй detail::property_traits< T, U >::setter_type Setter указать значение по умолчанию в виде NULL. inline property & operator = ( traits::const_reference_type value ) { return ( m_owner.* Setter )( value ), ( * this ); // <-- } Member pointer required on right side of .* or ->* Сам понимаешь условный переход тут не катит, да и сам метод то этот не нужен. для read_only Цитата Flex Ferrum @ Ты бы, кстати, решил проблемку по-интереснее - как избавиться от инициализации пропертей в конструкторе? считаешь реально ? что то в голову ничего не лезет, хотя были конечно попытки избавиться и от этого, но не вышло сделать так, чтобы ничего не писать. Цитата trainer @ А почему ссылка? property - это же, по сути, переменная. Почему она не хранит свое значение? U - это класс-хозяин свойства? Может сделать его другом и создать в property защищенные методы чтения и записи значения? Хм, ну это как посмотреть, я сначала тоже подумал что можно так сделать, но смысл в чем ? - Есть переменная max_value и value, value меняеться, класс должен определить на сколько он может изменить это value. Это свойство класса и метод изменения является свойством класса, получаеться мы должны работать с U - хозяином свойства. ( если ты имел ввиду некий универсалиный подход, то я не догнал ) Цитата trainer @ Заодно добавить в шаблон еще один параметр T def_value=T(), которым свойство инициализируется. в пред релизе был еще один параметр T Default, который инициализировался в конструкторе property, но я не смог реализовать подход, который бы инициализировал и класс дефаултом и int уже нулем. Причем наличие коструктора по умолчанию не хотелось бы делать необходимым для использования property. Хотя уверен тут решение есть, но это отдельная интересная задача, потребующая написания чего то типа boost::has_trivial_ctor |
Сообщ.
#5
,
|
|
|
Вообще да, по поводу хранения своего значения - это я не подумал как следует.
|
Сообщ.
#6
,
|
|
|
Цитата Sazabis @ Сам понимаешь условный переход тут не катит, да и сам метод то этот не нужен. для read_only Интересная задачка. Надо будет подумать. Цитата Sazabis @ считаешь реально ? что то в голову ничего не лезет, хотя были конечно попытки избавиться и от этого, но не вышло сделать так, чтобы ничего не писать. Ну, совсем ничего не писать, конечно, не получится. Но можно, например, в качестве одного из параметров шаблона передавать offsetof свойства. Дальше логика следующая: template<typename T, ..., int Offset> property::property() { // Воплне возможно, что грязный хак. Но, по идее, должно работать unsigned char* ptr = reinterpret_cast<unsigned char*>(this); m_HostObject = reinterpret_cast<T*>(ptr - Offset); // Дальше идет код по инициализации свойства } |
Сообщ.
#7
,
|
|
|
Цитата Flex Ferrum @ Ну, совсем ничего не писать, конечно, не получится. Но можно, например, в качестве одного из параметров шаблона передавать offsetof свойства. Дальше логика следующая: Хм.., прикольная идея, грязновата правда, особенно для редактирования кода через месяц. Тут мысля такая крутиться, ни как не оформиться: пропустить инициализацию через функцию со статик датой. Получаеться главное надо запустить функцию перед инициализацией проперти класса( а проперти тогда уже будет по деволту конструироваться используя доступ к этой функции/функтору ). И надо бы еще уникальность обеспечить |