长期以来,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的一部分)会获得通过,所以有更多编译器的库会跟进实现它。
Comments