原文地址:http://blog.llvm.org/2013/04/status-of-c11-migrator.html
自从2012年12月早些时候,C++11迁移器工具cpp11-migrate的设计文档发布以来,我们的开发工作进展顺利。在这篇文章里,我将介绍一下cpp11-migrate目前已经实现了哪些功能,即将实现哪些功能,以及如何加参与到这个项目里来。
cpp11-migrate的目标是实现一个C++11迁移器,这个迁移器可以实现源码到源码的转换,使用C++11的新特性去迁移已有的C++代码,从而提高这些已有的C++代码的可维护性、可读性、运行性能以及缩短编译性能。开发工作仍然处于早期阶段,目前的转换器主要分为两类。这个迁移器是基于Clang的LibTooling和AST
Matching library。
如何获得cpp11-migrate
cpp11-migrate位于Clang额外工具包。构建cpp11-migrate,你将需要LLVM和Clang的源码。跟随Clang的 Getting
Started instructions 指引,确保履行下载了可选的额外的工具包。一旦下载到了构建系统对应的目录,重新认证之后,将自动包含Clang额外工具包作为接下来整体构建的一部分。如果你使用的是CMake构建系统,你可以构建 cpp11-migrate通过使用cpp11-migratetarget参数。CMake提供的 check-clang-tools将运行所有Clang额外工具包括cpp11-migrate的回归测试。
目前已经实现的转换器
- 基于范围的for循环
- 为空指针提供了nullptr关键字
- auto类型说明符
- override虚拟说明符
Panzer。当打算开发更多的转换器的时候,实现的思路就变成了把所有的转换器放在一个单独的工具管辖之下,于是 cpp11-migrate诞生了。基于范围的for循环转换器替换了下列三种普遍情况下的任何一种for循环:
- 使用迭代器遍历容器:
std::vector<int> myVec; for (std::vector<int>::iterator I = myVec.begin(), E = myVec.end(); I != E; ++I) llvm::outs() << *I;
⇒std::vector<int> myVec; for (auto & elem : myVec) llvm::outs() << elem;
- 遍历静态数组:
int arr[] = {1,2,3,4,5}; for (int i = 0; i < 5; ++i) llvm::outs() << arr[i];
⇒int arr[] = {1,2,3,4,5}; for (auto & elem : arr) llvm::outs() << elem;
- 使用操作符[]或者()遍历类似数组的容器:
std::vector<int> myVec; for (int i = 0; i < myVec.size(); ++i) llvm::outs() << v[i];
⇒std::vector<int> myVec; for (auto & elem : myVec) llvm::outs() << elem;
void foo(int *arg); void foo(float *arg); int *IntPtr = 0; float *FloatPtr = NULL; foo(static_cast<int*>(0));
void foo(int *arg); void foo(float *arg); int *IntPtr = nullptr; float *FloatPtr = nullptr; foo(static_cast<int*>(nullptr));
auto类型说明符转换器使用新的auto关键字替换了变量声明的类型说明符。一般来说,只要变量声明的类型和它的初始化类型相匹配,这样的替换就可以做。当然,这个转换器只是针对一小部分特殊的方便可读性和可维护性的实用场景:
- 当变量是一个STL容器的迭代器的时候。
std::vector<std::pair<int, std::string> >::iterator NameAgeI = People.begin(); for (std::vector<MyType>::iterator I = Container.begin(), E = Container.end; I != E; ++I) { // ... }
⇒auto NameAgeI = People.begin(); for (auto I = Container.begin(), E = Container.end; I != E; ++I) { // ... }
- 当初始化器是一个使用new操作符的分配空间动作时。
MyType *VarPtr = new MyType(); MyType * const VarCPtr = new MyType();
⇒auto VarPtr = new MyType(); auto const VarCPtr = new MyType();
MyType *FooPtr = makeObject<MyType>(/*...*/); MyType *BarPtr = MyType::create(/*...*/);
auto FooPtr = makeObject<MyType>(/*...*/); auto BarPtr = MyType::create(/*...*/);
override虚拟说明符转换器,Philip Dunstan贡献,它是这个迁移器的第四个转换器并且是第一个来自Intel核心小组之外的贡献。这个转换器检测派生来之中的重载父类成员函数的虚成员函数,并且给它们加上override虚拟说明符。
class Parent { public: virtual int getNumChildren(); }; class Child { public: virtual int getNumChildren(); };
class Parent { public: virtual int getNumChildren(); }; class Child { public: virtual int getNumChildren() override; };
User's Manual中找到。
在真实的工程上测试