На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Модераторы: Qraizer, Hsilgos
  
> property на С++
    Вот опять всплыла тема про property, в ней была ссылка на RSDN ( http://www.rsdn.ru/article/vcpp/props.xml ),
    и раньше видет эту статейку но тогда я еще на читал Александреску, а сейчас посмотрел..., сразу захотелось подпатчить
    код про property. Вот представляю на суд след. код.


    ExpandedWrap disabled
      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 байта (или столько, сколько отводиться под ссылку).


    юзается в классе так:
    ExpandedWrap disabled
        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.
      Цитата Sazabis @
      3) Приходиться брать адрес функции, а для inline это чревато тем что она
      перестанет быть inline.

      Читаем последнюю книгку Саттера. inline - лишь подсказка компилятору. Поверь, он (в некотором отношении) гораздо умней разработчика, и сам в состоянии решить - какие функции, когда и как подставлять.
      Ты бы, кстати, решил проблемку по-интереснее - как избавиться от инициализации пропертей в конструкторе? :D
      Цитата Sazabis @
      2) Не получилось переопределить read_only property, с тем же именем ( property )
      Возможно компилятор не позволил..., возможно получиться у Вас ?

      Попробуй detail::property_traits< T, U >::setter_type Setter указать значение по умолчанию в виде NULL.
        А почему ссылка? property - это же, по сути, переменная. Почему она не хранит свое значение? U - это класс-хозяин свойства? Может сделать его другом и создать в property защищенные методы чтения и записи значения? Заодно добавить в шаблон еще один параметр T def_value=T(), которым свойство инициализируется.
          Цитата Flex Ferrum @
          Читаем последнюю книгку Саттера. inline - лишь подсказка компилятору. Поверь, он (в некотором отношении) гораздо умней разработчика, и сам в состоянии решить - какие функции, когда и как подставлять.

          Это я в курсе, и на форуме создавал тему по inline. Только книжки хорошо, а в жизни еще не все компиляторы такие умные. Хотя в этом вопросе тут врят ли можно достичь чего то лучше, но раз это можно на асме сделать проще, возможно можено написать код так, чтобы не нужна была супер умность компилятора. Borland например не развертывает inline :( , вроде бы.


          Цитата Flex Ferrum @
          Попробуй detail::property_traits< T, U >::setter_type Setter указать значение по умолчанию в виде NULL.

          ExpandedWrap disabled
                    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 :unsure:
            Вообще да, по поводу хранения своего значения - это я не подумал как следует. :)
              Цитата Sazabis @
              Сам понимаешь условный переход тут не катит, да и сам метод то этот не нужен. <_< для read_only

              Интересная задачка. Надо будет подумать.

              Цитата Sazabis @
              считаешь реально ? что то в голову ничего не лезет, хотя были конечно попытки избавиться и от этого, но не вышло сделать так, чтобы ничего не писать.

              Ну, совсем ничего не писать, конечно, не получится. Но можно, например, в качестве одного из параметров шаблона передавать offsetof свойства. Дальше логика следующая:
              ExpandedWrap disabled
                template<typename T, ..., int Offset> property::property()
                {
                   // Воплне возможно, что грязный хак. Но, по идее, должно работать
                   unsigned char* ptr = reinterpret_cast<unsigned char*>(this);
                   m_HostObject = reinterpret_cast<T*>(ptr - Offset);
                   // Дальше идет код по инициализации свойства
                }
                Цитата Flex Ferrum @
                Ну, совсем ничего не писать, конечно, не получится. Но можно, например, в качестве одного из параметров шаблона передавать offsetof свойства. Дальше логика следующая:

                Хм.., прикольная идея, грязновата правда, особенно для редактирования кода через месяц.

                Тут мысля такая крутиться, ни как не оформиться: пропустить инициализацию через функцию со статик датой. Получаеться главное надо запустить функцию перед инициализацией проперти класса( а проперти тогда уже будет по деволту конструироваться используя доступ к этой функции/функтору ). И надо бы еще уникальность обеспечить <_<
                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                0 пользователей:


                Рейтинг@Mail.ru
                [ Script execution time: 0,0296 ]   [ 16 queries used ]   [ Generated: 6.05.24, 20:39 GMT ]