C++11 迁移器的状态--2013年4月15日

简介: 原文地址:http://blog.llvm.org/2013/04/status-of-c11-migrator.html 译者:史宁宁(snsn1984)         自从2012年12月早些时候,C++11迁移器工具cpp11-migrate的设计文档发布以来,我们的开发工作进展顺利。

原文地址:http://blog.llvm.org/2013/04/status-of-c11-migrator.html

译者:史宁宁snsn1984

        自从2012年12月早些时候,C++11迁移器工具cpp11-migrate的设计文档发布以来,我们的开发工作进展顺利。在这篇文章里,我将介绍一下cpp11-migrate目前已经实现了哪些功能,即将实现哪些功能,以及如何加参与到这个项目里来。

         cpp11-migrate的目标是实现一个C++11迁移器,这个迁移器可以实现源码到源码的转换,使用C++11的新特性去迁移已有的C++代码,从而提高这些已有的C++代码的可维护性、可读性、运行性能以及缩短编译性能。开发工作仍然处于早期阶段,目前的转换器主要分为两类。这个迁移器是基于Clang的LibToolingAST Matching library

    目前所有的开发工作是Intel的一个小核心组在进行。我们目前工作的中心是建立起基础平台和测试,实现一小部分基本的转换器,同时确保这些转换器工作良好。我们的目标是希望可以这个工具对社区是实用的,所以我们总是聆听转换器的想法和反馈。
如何获得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的回归测试。
目前已经实现的转换器
这个C++11迁移器目前支持C++11的四个特性:
  • 基于范围的for循环
  • 为空指针提供了nullptr关键字
  • auto类型说明符
  • override虚拟说明符
    基于范围的for循环转换器曾经作为一个单独的叫做loop-convert的工具存在过,它的贡献者是Sam Panzer。当打算开发更多的转换器的时候,实现的思路就变成了把所有的转换器放在一个单独的工具管辖之下,于是 cpp11-migrate诞生了。基于范围的for循环转换器替换了下列三种普遍情况下的任何一种for循环:
  1. 使用迭代器遍历容器:
    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;
    
  2. 遍历静态数组:
    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;
  3. 使用操作符[]或者()遍历类似数组的容器:
    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;
    
     nullprt转换器使用最新的nullprt关字,当指针被被初始化或者赋值为一个空值的时候。万一这时候还有一个显式的转换存在,这个显示的转换将保留下来,避免引入两意性到代码。
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关键字替换了变量声明的类型说明符。一般来说,只要变量声明的类型和它的初始化类型相匹配,这样的替换就可以做。当然,这个转换器只是针对一小部分特殊的方便可读性和可维护性的实用场景:
  1. 当变量是一个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) {
      // ...
    }
  2. 当初始化器是一个使用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(/*...*/);
     在每一种情形之下,为声明产生的类型都应该是读者来说非常明显的。标准容器的迭代器是通过具有特殊名字的函数所创建的,并且使用在特殊的情景之下。对于工厂方法和new操作符来说,类型已经在初始化的时候表明了,所以在变量声明的时候重复说明没有必要。
       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;
};
      更多关于这些转换器的细节,包括它们能做什么、不能做什么,怎么样调整它们的行为,甚至了解他们的局限性,这些都可以在这个文档cpp11-migrate User's Manual中找到。

  在真实的工程上测试


    还有什么比在真实的工程上运行C++11迁移器进行测试更好的方法么?我们已经建立起了一个持续的合成服务器去构建和运行cpp11-migrate,目前已经运行了两个工程,已经有计划运行至少三个工程。对于每个工程,目标是构建转换的代码并且运行这些工程的测试包,来确保语义没有被改变。
已经实现的:
1. LLVM3.1
2. ITK 4.3.1
计划实现的:
1. LLDB
2. OpenCV
3. Poco
      在实际的代码上运行迁移器对发现缺陷很有帮助。各种项目的真实代码经常揭示转换器的实际开发和单元测试无法揭示的代码表达式。每次转换这些工程的缺陷被修复,新的测试用例都会加到回归测试包里,迁移器就会变得更加健壮。

  接下来的工作


   尽可能快的通过迁移真实的代码去修复缺陷,是目前高优先级的,因为我们想给尽可能多的用户带来很好的用户体验。添加更多的转换器是另外一个优先的任务,同时社区最感兴趣的转换器将会首先被添加。目前列表的最顶端是:
1. 使用标准库去替代TR1
2. 取代使用已经废弃的auto_prt类。
   为了修复缺陷和添加转换器,还有一些更普遍的改进需要考虑。其中之一的改进已经正在实现,那就是去除只有源文件可以转换而它所包含的任何头文件都不转换的限制。这个限制直到现在才开始做是因为迁移器需要知道哪些头文件是可以安全转换的。系统头文件和第三方库的头文件很明显是不能碰的。
    加入我们!
   如果你想加入我们,你需要做的第一件事情就是在你的代码上试试cpp11-migrate。缺陷可以使用clang-tools-extra产品下的LLVM's bug tracker 去记录。如果你需要帮助或者你希望参与的更多,可以给 Clang Developer's Mailing List发一个邮件。我们期望收到你来信!
Labels: C++, Clang
Location: Waterloo, ON, Canada

目录
相关文章
|
4月前
|
Web App开发 Rust 分布式计算
Rust与C++的区别及使用问题之对于大量使用C++实现的产品来说,迁移到Rust的问题如何解决
Rust与C++的区别及使用问题之对于大量使用C++实现的产品来说,迁移到Rust的问题如何解决
|
存储 算法 编译器
C++ 从cstring函数向string类成员函数迁移2
C++ 从cstring函数向string类成员函数迁移
173 0
|
算法 编译器 C++
C++ 从cstring函数向string类成员函数迁移
C++ 从cstring函数向string类成员函数迁移
102 0
|
2天前
|
存储 编译器 C语言
【c++丨STL】string类的使用
本文介绍了C++中`string`类的基本概念及其主要接口。`string`类在C++标准库中扮演着重要角色,它提供了比C语言中字符串处理函数更丰富、安全和便捷的功能。文章详细讲解了`string`类的构造函数、赋值运算符、容量管理接口、元素访问及遍历方法、字符串修改操作、字符串运算接口、常量成员和非成员函数等内容。通过实例演示了如何使用这些接口进行字符串的创建、修改、查找和比较等操作,帮助读者更好地理解和掌握`string`类的应用。
15 2
|
8天前
|
存储 编译器 C++
【c++】类和对象(下)(取地址运算符重载、深究构造函数、类型转换、static修饰成员、友元、内部类、匿名对象)
本文介绍了C++中类和对象的高级特性,包括取地址运算符重载、构造函数的初始化列表、类型转换、static修饰成员、友元、内部类及匿名对象等内容。文章详细解释了每个概念的使用方法和注意事项,帮助读者深入了解C++面向对象编程的核心机制。
33 5
|
14天前
|
存储 编译器 C++
【c++】类和对象(中)(构造函数、析构函数、拷贝构造、赋值重载)
本文深入探讨了C++类的默认成员函数,包括构造函数、析构函数、拷贝构造函数和赋值重载。构造函数用于对象的初始化,析构函数用于对象销毁时的资源清理,拷贝构造函数用于对象的拷贝,赋值重载用于已存在对象的赋值。文章详细介绍了每个函数的特点、使用方法及注意事项,并提供了代码示例。这些默认成员函数确保了资源的正确管理和对象状态的维护。
46 4
|
15天前
|
存储 编译器 Linux
【c++】类和对象(上)(类的定义格式、访问限定符、类域、类的实例化、对象的内存大小、this指针)
本文介绍了C++中的类和对象,包括类的概念、定义格式、访问限定符、类域、对象的创建及内存大小、以及this指针。通过示例代码详细解释了类的定义、成员函数和成员变量的作用,以及如何使用访问限定符控制成员的访问权限。此外,还讨论了对象的内存分配规则和this指针的使用场景,帮助读者深入理解面向对象编程的核心概念。
43 4
|
1月前
|
存储 编译器 对象存储
【C++打怪之路Lv5】-- 类和对象(下)
【C++打怪之路Lv5】-- 类和对象(下)
28 4
|
1月前
|
编译器 C语言 C++
【C++打怪之路Lv4】-- 类和对象(中)
【C++打怪之路Lv4】-- 类和对象(中)
25 4
|
1月前
|
存储 安全 C++
【C++打怪之路Lv8】-- string类
【C++打怪之路Lv8】-- string类
22 1