转载请注明出处为KlayGE游戏引擎,本文的永久链接为http://www.klayge.org/?p=2215

长期以来,KlayGE的很多代码都依赖于boost。(这里有个列表)。上次我提到过,随着C++11编译器和库的普及,boost中的很多东西都可以用C++11来代替。我这两天正试着在KFL中做这件事情,以下的过程中总结的经验和教训。当然,这里只涉及到KlayGE使用的boost组件,没使用到的我没做测试。所有这些替换都保证了可以通过宏来切换回boost的实现。

可以直接替换

标记了*的表示需要编译才能使用的boost组件。下同。

  • Array
  • Chrono *
  • Foreach
  • Regex *
  • System *
  • Static Assert
  • Type Traits
  • Typeof
  • Unordered

这些boost组件都可以直接用C++11的相应组件替换掉。Foreach、Static Assert和Typeof是语言核心提供的,需要写个宏来统一接口。其他都只要把namespace从boost换到std即可。用法和功能都不变。

稍作修改后可以替换

  • Integer
  • Thread *
  • Tuple

这三个boost组件的接口和C++11的几乎一样,但替换后需要做一点点修改。cstdint中定义的int8_t、uint32_t等类型和boost/cstdint.hpp的一样,但在VC11下会报warning 4503。再工程中设置忽略即可。std::thread和boost::thread的析构函数行为不同,std::thread如果没有join,就会abort,但boost::thread会安静地detach。除非定义了BOOST_THREAD_PROVIDES_THREAD_DESTRUCTOR_CALLS_TERMINATE_IF_JOINABLE,它们的行为才会一致。在使用中需要注意这点。std::tuple和boost::tuple本身没什么区别,但std::tuple提供了tuple_size,而boost的叫boost::tuples::length。所以只要简单地用boost::tuples::length实现一个tuple_size。另一个不一致的接口是,boost实现了tuple.get和boost::get,而C++11只有std::get,这个也需要稍微修改。

看似一样却没法替换

  • Bind
  • Function
  • Member Function
  • Ref
  • Smart Ptr

这几个boost组件看似可以直接替换,但在修改了几百处之后问题暴露出来了。情况比较复杂,function、mem_fn、ref依赖于bind,bind依赖于smart ptr,结果就是要么这几个都用boost的,要么都用C++11的,混用会导致无数编译错误。更大的问题在于, VC11的mem_fn不支持stdcall,而boost得则可以通过定义BOOST_MEM_FN_ENABLE_STDCALL来支持stdcall。因为需要配合COM使用,不支持stdcall使得要么这一大套都得用boost的,要么就试着避开mem_fn。目前我选择了前者。

除了名字其他都不一样没法替换

  • Random

C++11的Random和boost的接口完全不同,除了名字一样之外就不是同个东西,没法替换。

不存在于C++11

  • Algorithm
  • Any
  • Assign
  • Assert
  • Circular Buffer
  • Container
  • Filesystem *
  • Functional/Hash
  • Interprocess
  • Lexical Cast
  • MPL
  • Operators
  • Pool
  • Program Options *
  • Signals *
  • Tokenizer
  • Utility

这些组件在C++11中并没有类似的东西,还是得用boost的。值得一提的是,VC11里实现了一个类似于Boost Filesystem V2的版本,并可能很快升级到Filesystem V3。相信2013年内Filesystem TS(TR2的一部分)会获得通过,所以有更多编译器的库会跟进实现它。