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

经过前两次实验,大部分C++11里有的boost组件都被替换成了C++11中相应的。剩下的还有random库和bind/function/mem_fn/ref/smart_ptr这一组。看来,到了不得不改代码的时候了。

random

第一次实验里提到过,random虽然在boost和C++11都有,但接口不相同,所以原先我用Boost.Random实现的代码,无法直接替换成C++11的。翻了一遍boost文档,发现现在的boost其实有实现了一套名字和C++11相同的组件,于是我重写了所有用到random的地方,用和C++11兼容的代码,就解决了这个问题。好在random用得不多,改几个地方就都好了。

bind/function/mem_fn/ref/smart_ptr

这几个组件相互依赖,要么全换,要么不换。再加上牵扯面非常广,修改起来几乎都要rebuild所有代码,进展非常缓慢。经过多次痛苦的rebuild之后,问题集中在了几个地方:

signals2::disconnect

C++11的function的operator==只能和nullptr作比较,所以disconnect的时候一定会编译失败。按照boost文档,signals2的正确用法应该是,connect的时候返回一个连接对象,在那上面调用disconnect。这样避免了function的比较,同时也更高效。修改后这个地方正常了。

algorithm::string::split

可能是VC11的bind实现bug,bind(equal_to<char>(), ‘ ‘, _1)无法编译。同样参看文档,用了更常见的is_any_of(” “),问题解决。

function值传递

这也很可能是VC11的bind实现bug。一个function如果用值传递传给bind的functor,编译没问题,但执行的时候crash,debugger里看到的是那个function对象没有被传给真实的函数,而就被析构掉了,某一次传递被搞成了引用传递。于是这里只能放弃bind,用自己实现的functor代替。

没有Variadic templates

因为VC11目前不支持Variadic templates,不能做可变参数的template。所以vc11的stl里,对于不同参数的bind,在实现上只能手写展开。而他们估计偷懒了,只展开到了4个参数。如果bind要有更多参数,就只能改代码,把一些参数合并入一个struct。

mem_fn和stdcall

由于VC11的mem_fn实现不完全,stdcall的成员函数无法通过mem_fn来使用。这里只能暂时用boost的mem_fn来凑或。

完成

至此,所有C++11里有的boost组件都得到了替换(除了mem_fn是不完全替换),同时仍然可以通过宏切换回boost的实现。在VC11和MinGW 4.7上通过了测试。随着未来编译器的发展,相信现在的一些限制会逐渐消失。也希望有更多组件成为TR2和C++1y的标准,为开发提供更多方便。