原文連結: http://hokein.me/clang-tools-…
雖然C++11標準出來已經有好些年了,但是由於歷史的原因,現在大部分C++專案仍然是C++03的語法。那麼有沒方法能夠自動地把老的C++03程式碼替換成C++11程式碼?從而讓我們享受到C++11新特性,像for-range loop,auto,nullptr,override等。
答案當然有的——clang-tidy。clang-tidy提供一系列的modernize-*
checks。這些checks就是用C++11改寫C++03。具體有下面這些:
-
modernize-avoid-bind: 使用
lambda
替換std::binding
。 -
modernize-deprecated-headers: 將C標準庫的標頭檔案include替換成C++style,
#include <assert.h>
=>#include <cassert>
。 -
modernize-loop-convert: 使用
for-range loop
替換for(...;...;...;)
, 並更新for
語句的相關變數。 -
modernize-make-shared: 找出所有顯式建立
std::shared_ptr
變數的表示式,並使用make_shared
替換。 -
modernize-make-unique: 跟
make-shared
一樣,使用std::make_unique
替換所有std::unique_ptr
顯式建立表示式。 -
modernize-pass-by-value: 在建構函式中使用move語義
-
modernize-raw-string-literal: 用C++11的
raw string literal
(R"..."
)替換原來的string literal
, 這樣的好處就是不用再新增轉義符“了。 -
modernize-redundant-void-arg: 去掉
void
函式引數。 -
modernize-replace-auto-ptr: 用
std::unique_ptr
替換std::shared_ptr
,std::shared_ptr
是不推薦使用的,即使在C++98。 -
modernize-shrink-to-fit: 在C++03中,如果我們想修改STL容器的
capacity
,只能通過copy & swap
的方式,C++11提供了shink_to_fit
的方法。 -
modernize-use-auto: 在變數定義的時候,使用
auto
代替顯式的型別宣告,這個在定義STL容器類的Iterator
特別方便。 -
modernize-use-bool-literals: 找出所有隱式從
int
轉成bool
的literal
, 使用true
或者false
代替。 -
modernize-use-default: 對於沒有任何自定義行為(定義為
{}
)的特殊的成員函式,建構函式,解構函式,移動/複製建構函式,用=default
代替掉{}
。 -
modernize-use-emplace: 使用STL容器中的
emplace
代替push_back
。 -
modernize-use-equals-delete: 在C++98中,類設計為了實現禁止呼叫某些特殊的成員函式,通常把它們宣告成
private
;在C++11中,只需要在宣告中體檢=delete
,找出所有private
的特殊成員函式,並將它們標記成=delete
。 -
modernize-use-nullptr: 用
nullptr
代替NULL
。 -
modernize-use-override: 對於子類改寫父類的
virtual
方法,在方法後面新增override
, 並刪掉virtual
字首,即virtual void NewOveride()
=>void NewOverride() override {}
。 -
modernize-use-using: 用
using
代替typedef
, 如typedef int V
=>using V = int
。
如何應用到專案中
這裡將以GitHub的electron開源專案為例子,如何應用clang-tidy來改寫它的C++03程式碼:
-
你需要匯出專案的
compilation database
, 通常命名為compile_commands.json
, 因為clang-tidy作為一個clang-based工具,需要知道如何編譯每一個原始檔(從compile_commands.json
查詢).ninja
提供這個匯出功能,只需要簡單執行下面命令。對於其它不用ninja
編譯的專案,也是有工具匯出的,方法請檢視前一篇介紹clang-tidy文章。
cd path/to/electron
# Make sure you can build electron successfully.
./script/build.py -c D
# Dump compilation database.
ninja -C out/D -t compdb cc cxx > compile_commands.json
-
現在,我們可以嘗試對專案中某個檔案執行
modernize-use-nullptr
check, 我們需要新增-fix
的命令引數,clang-tidy才會執行對原檔案修改, 不然結果會定向到標準輸出stdout
。
# Diagnose any `NULL` usage.
clang-tidy -checks="-*,modernize-use-nullptr" atom/browser/api/atom_api_menu.cc
# Replace all NULL usages to C++11 nullptr.
clang-tidy -checks="-*,modernize-use-nullptr" -fix atom/browser/api/atom_api_menu.cc
-
我們當然不需要每次都手動執行一個原始檔,
run_clang_tidy.py
指令碼能夠對每個compilation database
中的每個檔案都執行clang-tidy
(使用多程式方法)。
# Run `modernize-use-auto` on all files in atom/* and apply fixes.
path/to/run_clang_tidy.py -checks="-*,modernize-use-auto" -fix atom/*
真實執行的結果,請檢視electron#6423,已經被merge進upstream了。