Велосипедик в отсутствии rvalue references
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 22.06.08 14:28
Оценка: 28 (2)
Доброго дня!

Занимаясь последние несколько дней оптимизацией старого кода столкнулся несколько раз с ситуациями, для которых в C++0x придуманы rvalue references. Но в C++98 их нет, поэтому пришлось написать собственный велосипедик. Его код приведен ниже.

Если кому-то приходилось делать что-нибудь подобное самому или же кто-то видит в данном решении явные ляпы, то поделитесь, пожалуйста информацией и впечатлениями. Буду очень признателен.

//
// temporary_object_ref_t
//

/*!
 * \since v.2.4.0
 * \brief Шаблон ссылки на временный объект.
 *
 * Данный класс является вспомогательным инструментом для
 * компенсации отсутствия в C++98 т.н. rvalue references из
 * будущего стандарта C++0x.
 *
 * <b>Пример использования.</b> Допустим есть некоторый
 * контейнер тяжеловесных объектов (например, std::vector<int>).
 * Иногда добавляемое в контейнер значение нужно скопировать и
 * создать новую копию в контейнере, для чего предназначен
 * метод add, получающий константную ссылку на std::vector<int>:
 * \code
 * class heavy_object_container_t
 *     {
 *     public:
 *         void add( const std::vector<int> & obj ) {
 *             m_underlying_storage.push_back( obj );
 *         }
 *     ...
 *     private:
 *         std::list< std::vector<int> > m_underlying_storage;
 *     };
 * \endcode
 * Но иногда заранее известно, что при добавлении объекта в
 * контейнер используется временный объект, который будет
 * выброшен сразу после добавления. В этом случае операцию
 * добавления можно реализовать более эффективно -- забрать из
 * аргумента метода add имеющееся в нем значение:
 * \code
 *         void add( std::vector<int> & obj ) {
 *             m_underlying_storage.push_back( std::vector() );
 *             m_underlying_storage.back().swap( obj );
 *         }
 * \endcode
 * При таком подходе желательно, чтобы сигнатура метода add для
 * временного объекта явно указывала, что она требует именно
 * временный объект.
 *
 * В C++0x для этих целей применялись бы rvalue references, a
 * для C++98 предназначен данный класс:
 * \code
 *         void add( temporary_object_ref_t< std::vector<int> > obj ) {
 *             m_underlying_storage.push_back( std::vector() );
 *             m_underlying_storage.back().swap( obj.writeable() );
 *         }
 * \endcode
 */
template< class T >
class temporary_object_ref_t
    {
    public :
        /*!
         * Инициализирующий конструктор.
         *
         * Пользователь должен гарантировать, что время жизни
         * объекта \a o будет большей, чем время жизни данного
         * экземпляра temporary_object_ref_t.
         */
        explicit temporary_object_ref_t( T & o )
            :    m_object( o )
            {}

        /*!
         * Получение ссылки временный объект для последующего
         * изменения временного объекта.
         */
        T &
        writeable()
            {
                return m_object;
            }

        /*!
         * Получение константной ссылки на временный объект.
         */
        const T &
        readonly() const
            {
                return m_object;
            }

    private :
        //! Ссылка на временный объект.
        T & m_object;
    };

/*!
 * \since v.2.4.0
 * \brief Вспомогательная функция для упрощения формирования
 * ссылки на временный объект.
 *
 * Пример использования:
 * \code
 * void make_and_add_next_item(
 *     heavy_object_container_t & container )
 *     {
 *         std::vector< int > next_item;
 *         ...
 *         container.add( make_temporary_object_ref( next_item ) );
 *     }
 * \endcode
 */
template< class T >
temporary_object_ref_t< T >
make_temporary_object_ref( T & o )
    {
        return temporary_object_ref_t< T >( o );
    }


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.