Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
Разработка программного обеспечения

Emulation limitations

Boost , The Boost C++ Libraries BoostBook Documentation Subset , Chapter 23. Boost.Move

Boost C++ Libraries

...one of the most highly regarded and expertly designed C++ library projects in the world. Herb Sutter and Andrei Alexandrescu, C++ Coding Standards

PrevUpHomeNext

Как и любое усилие эмуляции, библиотека имеет некоторые ограничения, которые пользователи должны учитывать при использовании библиотеки с компиляторами, соответствующими C++03:

При инициализации базовых классов в конструкторах перемещения пользователи должны отлить ссылку на ссылку базового класса перед ее перемещением или просто использовать<BOOST_MOVE_BASE>. Пример:

Derived(BOOST_RV_REF(Derived) x)             // Move ctor
   : Base(boost::move(static_cast<Base&>(x)))
     //...

или

Derived(BOOST_RV_REF(Derived) x)             // Move ctor
   : Base(BOOST_MOVE_BASE(Base, x))
     //...

Если литье не выполняется, эмуляция не будет перемещать конструкцию базового класса, поскольку преобразование не доступно с<BOOST_RV_REF(Derived)>до<BOOST_RV_REF(Base)>. Без литья или<BOOST_MOVE_BASE>мы можем получить ошибку компиляции (для некопируемых типов) или менее эффективный конструктор ходов (для копируемых типов):

//If Derived is copyable, then Base is copy-constructed.
//If not, a compilation error is issued
Derived(BOOST_RV_REF(Derived) x)             // Move ctor
   : Base(boost::move(x))
     //...

Эмуляция не может иметь дело с правилами свертывания ссылок C++0x, которые позволяют идеальную пересылку:

//C++0x
template<class T>
void forward_function(T &&t)
{  inner_function(std::forward<T>(t); }
//Wrong C++03 emulation
template<class T>
void forward_function(BOOST_RV_REF<T> t)
{  inner_function(boost::forward<T>(t); }

В C++03 эмуляция BOOST_RV_REF не улавливает никаких const rlvalues. Подробнее о пересылке см.Конструкторская экспедицияглава.

Предложениепервой ссылки на rvalueпозволило привязать ссылки на rvalue к lvalues:

func(Type &&t);
//....
Type t;  //Allowed
func(t)

Позже, как объясняется вУстранение проблемы безопасности с помощью ссылок на значения, такое поведение считалось опасным и устраняло это связывание, так что ссылки на значения r придерживались принципа безопасной перегрузки по типу:Каждая функция должна быть безопасна по типу, независимо от того, как она была перегружена.

Boost.Moveне может эмулировать этот принцип безопасной перегрузки для компиляторов C++03:

//Allowed by move emulation
movable m;
BOOST_RV_REF(movable) r = m;

Макрос<BOOST_COPYABLE_AND_MOVABLE>должен определить конструктор копий для<copyable_and_movable>взятия неконст-параметра в компиляторах C++03:

//Generated by BOOST_COPYABLE_AND_MOVABLE
copyable_and_movable &operator=(copyable_and_movable&){/**/}

Поскольку генерируется неконстная перегрузка конструктора копий, операторы присваивания, генерируемые компилятором для классов, содержащих<copyable_and_movable>, получат неконст-конструкторскую перегрузку, которая наверняка удивит пользователей:

class holder
{
   copyable_and_movable c;
};
void func(const holder& h)
{
   holder copy_h(h); //<--- ERROR: can't convert 'const holder&' to 'holder&'
   //Compiler-generated copy constructor is non-const:
   // holder& operator(holder &)
   //!!!
}

Это ограничение заставляет пользователя определять конст-версию присвоения копии во всех классах, содержащих копируемые и подвижные классы, которые могут раздражать в некоторых случаях.

Альтернативой является реализация единственного<operator =()>для копируемых и подвижных классовс использованием семантики «pass by value»:

T& operator=(T x)    // x is a copy of the source; hard work already done
{
   swap(*this, x);  // trade our resources for x's
   return *this;    // our (old) resources get destroyed with x
}

Однако «переход по значению» не является оптимальным для классов (например, контейнеров, строк и т.д.), которые повторно используют ресурсы (например, ранее выделенную память), когда x присваивается из lvalue.

При наличии подвижного и копируемого класса, если добавлен шаблонный оператор назначения (*):

class Foo
{
   BOOST_COPYABLE_AND_MOVABLE(Foo)
   public:
   int i;
   explicit Foo(int val)      : i(val)   {}
   Foo(BOOST_RV_REF(Foo) obj) : i(obj.i) {}
   Foo& operator=(BOOST_RV_REF(Foo) rhs)
   {  i = rhs.i; rhs.i = 0; return *this; }
   Foo& operator=(BOOST_COPY_ASSIGN_REF(Foo) rhs)
   {  i = rhs.i; return *this;   } //(1)
   template<class U> //(*) TEMPLATED ASSIGNMENT, potential problem
   Foo& operator=(const U& rhs)
   {  i = -rhs.i; return *this;  } //(2)
};

Компиляторы C++98 и C++11 будут вести себя по-разному при присвоении значения<[const] Foo>:

Foo foo1(1);
Foo foo2(2);
foo2 = foo1; // Calls (1) in C++11 but (2) in C++98
const Foo foo5(5);
foo2 = foo5; // Calls (1) in C++11 but (2) in C++98

Это различное поведение является побочным эффектом эмуляции движения, которого нелегко избежатьBoost.Move. Одним из обходных путей является SFINAE-устранение шаблонного оператора назначения с<disable_if>:

template<class U> // Modified templated assignment
typename boost::disable_if<boost::is_same<U, Foo>, Foo&>::type
   operator=(const U& rhs)
{  i = -rhs.i; return *this;  } //(2)

PrevUpHomeNext

Статья Emulation limitations раздела The Boost C++ Libraries BoostBook Documentation Subset Chapter 23. Boost.Move может быть полезна для разработчиков на c++ и boost.




Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.



:: Главная :: Chapter 23. Boost.Move ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-08-30 11:47:00
2025-05-19 17:43:01/0.0098400115966797/1