Boost C++ 库

...世界上最受尊敬和专业设计的 C++ 库项目之一。 Herb SutterAndrei Alexandrescu, C++ 编码标准

PrevUpHomeNext

库的工作原理

Boost.Move 基于宏,这些宏在 C++0x 编译器中展开为真正的右值引用,在 C++03 编译器中则模拟右值引用类和转换运算符。

在 C++03 编译器中,Boost.Move 定义了一个名为 ::boost::rv 的类

template <class T>
class rv : public T
{
   rv();
   ~rv();
   rv(rv const&);
   void operator=(rv const&);
};

它可以转换为可移动的基类(通常的 C++ 派生类到基类的转换)。当用户将他们的类标记为 BOOST_MOVABLE_BUT_NOT_COPYABLEBOOST_COPYABLE_AND_MOVABLE 时,这些宏定义了到 ::boost::rv 引用的转换运算符

#define BOOST_MOVABLE_BUT_NOT_COPYABLE(TYPE)\
   public:\
   operator ::boost::rv<TYPE>&() \
   {  return *static_cast< ::boost::rv<TYPE>* >(this);  }\
   operator const ::boost::rv<TYPE>&() const \
   {  return static_cast<const ::boost::rv<TYPE>* >(this);  }\
   private:\
   //More stuff...

BOOST_MOVABLE_BUT_NOT_COPYABLE 也声明了一个私有的复制构造函数和赋值运算符。BOOST_COPYABLE_AND_MOVABLE 定义了一个非常量复制构造函数 TYPE &operator=(TYPE&),它转发到常量版本

#define BOOST_COPYABLE_AND_MOVABLE(TYPE)\
   public:\
   TYPE& operator=(TYPE &t)\
   {  this->operator=(static_cast<const ::boost::rv<TYPE> &>(const_cast<const TYPE &>(t))); return *this;}\
   //More stuff...

在 C++0x 编译器中,BOOST_COPYABLE_AND_MOVABLE 展开为空,而 BOOST_MOVABLE_BUT_NOT_COPYABLE 声明复制构造函数和赋值运算符为私有。

当用户定义 BOOST_RV_REF 复制构造函数/赋值运算符的重载时,在 C++0x 编译器中,它被展开为右值引用(T&&)重载,在 C++03 编译器中,它被展开为 ::boost::rv<T> & 重载

#define BOOST_RV_REF(TYPE) ::boost::rv< TYPE >& \

当用户定义 BOOST_COPY_ASSIGN_REF 重载时,它在 C++0x 编译器中被展开为通常的复制赋值(const T &)重载,在 C++03 编译器中被展开为 const ::boost::rv & 重载

#define BOOST_COPY_ASSIGN_REF(TYPE) const ::boost::rv< TYPE >&

如所见,Boost.Move 为 C++0x 移动语义生成高效且简洁的代码,而无需修改任何重载解析。对于 C++03 编译器,当执行重载解析时,这些是绑定

该库没有为复制构造函数定义等效于 BOOST_COPY_ASSIGN_REF 的宏(例如,BOOST_COPY_CTOR_REF),因为几乎所有现代编译器都实现了 RVO,这比任何移动模拟都更高效。move 只是将 TYPE & 转换为 ::boost::rv<TYPE> &

这是一个示例,演示了在 C++03 编译器中存在三个重载和转换运算符的情况下,不同的右值对象如何绑定到 ::boost::rv 引用

#include <boost/move/core.hpp>
#include <iostream>

class sink_tester
{
   public: //conversions provided by BOOST_COPYABLE_AND_MOVABLE
   operator ::boost::rv<sink_tester>&()
      {  return *static_cast< ::boost::rv<sink_tester>* >(this);  }
   operator const ::boost::rv<sink_tester>&() const
      {  return *static_cast<const ::boost::rv<sink_tester>* >(this);  }
};

//Functions returning different r/lvalue types
      sink_tester    rvalue()       {  return sink_tester(); }
const sink_tester    const_rvalue() {  return sink_tester(); }
      sink_tester &  lvalue()       {  static sink_tester lv; return lv; }
const sink_tester &  const_lvalue() {  static const sink_tester clv = sink_tester(); return clv; }

//BOOST_RV_REF overload
void sink(::boost::rv<sink_tester> &)      { std::cout << "non-const rvalue catched" << std::endl; }
//BOOST_COPY_ASSIGN_REF overload
void sink(const ::boost::rv<sink_tester> &){ std::cout << "const (r-l)value catched" << std::endl; }
//Overload provided by BOOST_COPYABLE_AND_MOVABLE
void sink(sink_tester &)                   { std::cout << "non-const lvalue catched" << std::endl; }

int main()
{
   sink(const_rvalue());   //"const (r-l)value catched"
   sink(const_lvalue());   //"const (r-l)value catched"
   sink(lvalue());         //"non-const lvalue catched"
   sink(rvalue());         //"non-const rvalue catched"
   return 0;
}

PrevUpHomeNext