戻る

clang-format解説

July 17, 2020

C++のコードの改行ルールやインデント幅, スペースの開け方などを一貫性を持たせたものにすることは機能的には変わらなくても美しさの面では重要だ. このような整形ルールは人や開発チームによって趣向が異なるはずであり, 同じ人でも別の整形ルールのコードをいじらなくてはならないこともある. clang-formatは整形するコマンドだが, 細かく整形ルールを定めることができそれを記述したファイルをプロジェクトに置くことでプロジェクト全体をコマンド一つで整形できる.

整形は一般にエディタの機能でありIDEなどでは標準的だしvimでも%で整形できるが, このように細かいルールを定めるためにこのようにclang-formatという規格がある. いくつかのエディタではclang-formatで整形する機能があり, vimもclang-formatと連携することができる.

http://clang.llvm.org/docs/ClangFormat.html このサイトが本家でドキュメントも十分にある. インストールはbrewでできる.


brew install clang-format

まず, ルールを定めるファイルを作らなくてはならない. ファイル名は .clang-formatもしくは_clang-formatにすること. 実際のサンプルは実はその場で生成することができる.


clang-format -style=llvm -dump-config > .clang-format

生成すると次のような内容になった:


---
Language:        Cpp
# BasedOnStyle:  LLVM
AccessModifierOffset: -2
AlignAfterOpenBracket: Align
AlignConsecutiveMacros: false
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AlignEscapedNewlines: Right
AlignOperands:   true
AlignTrailingComments: true
AllowAllArgumentsOnNextLine: true
AllowAllConstructorInitializersOnNextLine: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: Never
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: All
AllowShortLambdasOnASingleLine: All
AllowShortIfStatementsOnASingleLine: Never
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: MultiLine
BinPackArguments: true
BinPackParameters: true
BraceWrapping:
  AfterCaseLabel:  false
  AfterClass:      false
  AfterControlStatement: false
  AfterEnum:       false
  AfterFunction:   false
  AfterNamespace:  false
  AfterObjCDeclaration: false
  AfterStruct:     false
  AfterUnion:      false
  AfterExternBlock: false
  BeforeCatch:     false
  BeforeElse:      false
  IndentBraces:    false
  SplitEmptyFunction: true
  SplitEmptyRecord: true
  SplitEmptyNamespace: true
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Attach
BreakBeforeInheritanceComma: false
BreakInheritanceList: BeforeColon
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
BreakConstructorInitializers: BeforeColon
BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: true
ColumnLimit:     80
CommentPragmas:  '^ IWYU pragma:'
CompactNamespaces: false
ConstructorInitializerAllOnOneLineOrOnePerLine: false
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: true
DeriveLineEnding: true
DerivePointerAlignment: false
DisableFormat:   false
ExperimentalAutoDetectBinPacking: false
FixNamespaceComments: true
ForEachMacros:
  - foreach
  - Q_FOREACH
  - BOOST_FOREACH
IncludeBlocks:   Preserve
IncludeCategories:
  - Regex:           '^"(llvm|llvm-c|clang|clang-c)/'
    Priority:        2
    SortPriority:    0
  - Regex:           '^(<|"(gtest|gmock|isl|json)/)'
    Priority:        3
    SortPriority:    0
  - Regex:           '.*'
    Priority:        1
    SortPriority:    0
IncludeIsMainRegex: '(Test)?$'
IncludeIsMainSourceRegex: ''
IndentCaseLabels: false
IndentGotoLabels: true
IndentPPDirectives: None
IndentWidth:     2
IndentWrappedFunctionNames: false
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: true
MacroBlockBegin: ''
MacroBlockEnd:   ''
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
ObjCBinPackProtocolList: Auto
ObjCBlockIndentWidth: 2
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
PenaltyBreakAssignment: 2
PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakString: 1000
PenaltyBreakTemplateDeclaration: 10
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 60
PointerAlignment: Right
ReflowComments:  true
SortIncludes:    true
SortUsingDeclarations: true
SpaceAfterCStyleCast: false
SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true
SpaceBeforeCpp11BracedList: false
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: ControlStatements
SpaceBeforeRangeBasedForLoopColon: true
SpaceInEmptyBlock: false
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles:  false
SpacesInConditionalStatement: false
SpacesInContainerLiterals: true
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
SpaceBeforeSquareBrackets: false
Standard:        Latest
StatementMacros:
  - Q_UNUSED
  - QT_REQUIRE_VERSION
TabWidth:        8
UseCRLF:         false
UseTab:          Never
...



googleの.clang-formatも同様に生成してdiffコマンドによってformatの違いを比較した. diff -y とすることで二列で表示でき見やすい.


diff -y .clang-format .clang-format2 | less -R

見方はだいたいわかると思うが, | の行が違いが現れている部分で, > は一方の行にはない部分.


---                                                         ---
Language:        Cpp                                        Language:        Cpp
# BasedOnStyle:  LLVM                                     | # BasedOnStyle:  Google
AccessModifierOffset: -2                                  | AccessModifierOffset: -1
AlignAfterOpenBracket: Align                                AlignAfterOpenBracket: Align
AlignConsecutiveMacros: false                               AlignConsecutiveMacros: false
AlignConsecutiveAssignments: false                          AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false                         AlignConsecutiveDeclarations: false
AlignEscapedNewlines: Right                               | AlignEscapedNewlines: Left
AlignOperands:   true                                       AlignOperands:   true
AlignTrailingComments: true                                 AlignTrailingComments: true
AllowAllArgumentsOnNextLine: true                           AllowAllArgumentsOnNextLine: true
AllowAllConstructorInitializersOnNextLine: true             AllowAllConstructorInitializersOnNextLine: true
AllowAllParametersOfDeclarationOnNextLine: true             AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: Never                        AllowShortBlocksOnASingleLine: Never
AllowShortCaseLabelsOnASingleLine: false                    AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: All                       AllowShortFunctionsOnASingleLine: All
AllowShortLambdasOnASingleLine: All                         AllowShortLambdasOnASingleLine: All
AllowShortIfStatementsOnASingleLine: Never                | AllowShortIfStatementsOnASingleLine: WithoutElse
AllowShortLoopsOnASingleLine: false                       | AllowShortLoopsOnASingleLine: true
AlwaysBreakAfterDefinitionReturnType: None                  AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None                            AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false                  | AlwaysBreakBeforeMultilineStrings: true
AlwaysBreakTemplateDeclarations: MultiLine                | AlwaysBreakTemplateDeclarations: Yes
BinPackArguments: true                                      BinPackArguments: true
BinPackParameters: true                                     BinPackParameters: true
BraceWrapping:                                              BraceWrapping:
  AfterCaseLabel:  false                                      AfterCaseLabel:  false
  AfterClass:      false                                      AfterClass:      false
  AfterControlStatement: false                                AfterControlStatement: false
  AfterEnum:       false                                      AfterEnum:       false
  AfterFunction:   false                                      AfterFunction:   false
  AfterNamespace:  false                                      AfterNamespace:  false
  AfterObjCDeclaration: false                                 AfterObjCDeclaration: false
  AfterStruct:     false                                      AfterStruct:     false
  AfterUnion:      false                                      AfterUnion:      false
  AfterExternBlock: false                                     AfterExternBlock: false
  BeforeCatch:     false                                      BeforeCatch:     false
  BeforeElse:      false                                      BeforeElse:      false
  IndentBraces:    false                                      IndentBraces:    false
  SplitEmptyFunction: true                                    SplitEmptyFunction: true
  SplitEmptyRecord: true                                      SplitEmptyRecord: true
  SplitEmptyNamespace: true                                   SplitEmptyNamespace: true
BreakBeforeBinaryOperators: None                            BreakBeforeBinaryOperators: None
BreakBeforeBraces: Attach                                   BreakBeforeBraces: Attach
BreakBeforeInheritanceComma: false                          BreakBeforeInheritanceComma: false
BreakInheritanceList: BeforeColon                           BreakInheritanceList: BeforeColon
BreakBeforeTernaryOperators: true                           BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false              BreakConstructorInitializersBeforeComma: false
BreakConstructorInitializers: BeforeColon                   BreakConstructorInitializers: BeforeColon
BreakAfterJavaFieldAnnotations: false                       BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: true                                   BreakStringLiterals: true
ColumnLimit:     80                                         ColumnLimit:     80
CommentPragmas:  '^ IWYU pragma:'                           CommentPragmas:  '^ IWYU pragma:'
CompactNamespaces: false                                    CompactNamespaces: false
ConstructorInitializerAllOnOneLineOrOnePerLine: false     | ConstructorInitializerAllOnOneLineOrOnePerLine: true
ConstructorInitializerIndentWidth: 4                        ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4                                  ContinuationIndentWidth: 4
Cpp11BracedListStyle: true                                  Cpp11BracedListStyle: true
DeriveLineEnding: true                                      DeriveLineEnding: true
DerivePointerAlignment: false                             | DerivePointerAlignment: true
DisableFormat:   false                                      DisableFormat:   false
ExperimentalAutoDetectBinPacking: false                     ExperimentalAutoDetectBinPacking: false
FixNamespaceComments: true                                  FixNamespaceComments: true
ForEachMacros:                                              ForEachMacros:
  - foreach                                                   - foreach
  - Q_FOREACH                                                 - Q_FOREACH
  - BOOST_FOREACH                                             - BOOST_FOREACH
IncludeBlocks:   Preserve                                 | IncludeBlocks:   Regroup
IncludeCategories:                                          IncludeCategories:
  - Regex:           '^"(llvm|llvm-c|clang|clang-c)/'     |   - Regex:           '^<ext/.*\.h>'
    Priority:        2                                          Priority:        2
    SortPriority:    0                                          SortPriority:    0
  - Regex:           '^(<|"(gtest|gmock|isl|json)/)'      |   - Regex:           '^<.*\.h>'
    Priority:        3                                    |     Priority:        1
                                                          >     SortPriority:    0
                                                          >   - Regex:           '^<.*'
                                                          >     Priority:        2
    SortPriority:    0                                          SortPriority:    0
  - Regex:           '.*'                                     - Regex:           '.*'
    Priority:        1                                    |     Priority:        3
    SortPriority:    0                                          SortPriority:    0
IncludeIsMainRegex: '(Test)?$'                            | IncludeIsMainRegex: '([-_](test|unittest))?$'
IncludeIsMainSourceRegex: ''                                IncludeIsMainSourceRegex: ''
IndentCaseLabels: false                                   | IndentCaseLabels: true
IndentGotoLabels: true                                      IndentGotoLabels: true
IndentPPDirectives: None                                    IndentPPDirectives: None
IndentWidth:     2                                          IndentWidth:     2
IndentWrappedFunctionNames: false                           IndentWrappedFunctionNames: false
JavaScriptQuotes: Leave                                     JavaScriptQuotes: Leave
JavaScriptWrapImports: true                                 JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: true                    | KeepEmptyLinesAtTheStartOfBlocks: false
MacroBlockBegin: ''                                         MacroBlockBegin: ''
MacroBlockEnd:   ''                                         MacroBlockEnd:   ''
MaxEmptyLinesToKeep: 1                                      MaxEmptyLinesToKeep: 1
NamespaceIndentation: None                                  NamespaceIndentation: None
ObjCBinPackProtocolList: Auto                             | ObjCBinPackProtocolList: Never
ObjCBlockIndentWidth: 2                                     ObjCBlockIndentWidth: 2
ObjCSpaceAfterProperty: false                               ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true                           ObjCSpaceBeforeProtocolList: true
PenaltyBreakAssignment: 2                                   PenaltyBreakAssignment: 2
PenaltyBreakBeforeFirstCallParameter: 19                  | PenaltyBreakBeforeFirstCallParameter: 1
PenaltyBreakComment: 300                                    PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120                              PenaltyBreakFirstLessLess: 120
PenaltyBreakString: 1000                                    PenaltyBreakString: 1000
PenaltyBreakTemplateDeclaration: 10                         PenaltyBreakTemplateDeclaration: 10
PenaltyExcessCharacter: 1000000                             PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 60                         | PenaltyReturnTypeOnItsOwnLine: 200
PointerAlignment: Right                                   | PointerAlignment: Left
                                                          > RawStringFormats:
                                                          >   - Language:        Cpp
                                                          >     Delimiters:
                                                          >       - cc
                                                          >       - CC
                                                          >       - cpp
                                                          >       - Cpp
                                                          >       - CPP
                                                          >       - 'c++'
                                                          >       - 'C++'
                                                          >     CanonicalDelimiter: ''
                                                          >     BasedOnStyle:    google
                                                          >   - Language:        TextProto
                                                          >     Delimiters:
                                                          >       - pb
                                                          >       - PB
                                                          >       - proto
                                                          >       - PROTO
                                                          >     EnclosingFunctions:
                                                          >       - EqualsProto
                                                          >       - EquivToProto
                                                          >       - PARSE_PARTIAL_TEXT_PROTO
                                                          >       - PARSE_TEST_PROTO
                                                          >       - PARSE_TEXT_PROTO
                                                          >       - ParseTextOrDie
                                                          >       - ParseTextProtoOrDie
                                                          >     CanonicalDelimiter: ''
                                                          >     BasedOnStyle:    google
ReflowComments:  true                                       ReflowComments:  true
SortIncludes:    true                                       SortIncludes:    true
SortUsingDeclarations: true                                 SortUsingDeclarations: true
SpaceAfterCStyleCast: false                                 SpaceAfterCStyleCast: false
SpaceAfterLogicalNot: false                                 SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: true                             SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true                        SpaceBeforeAssignmentOperators: true
SpaceBeforeCpp11BracedList: false                           SpaceBeforeCpp11BracedList: false
SpaceBeforeCtorInitializerColon: true                       SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true                           SpaceBeforeInheritanceColon: true
SpaceBeforeParens: ControlStatements                        SpaceBeforeParens: ControlStatements
SpaceBeforeRangeBasedForLoopColon: true                     SpaceBeforeRangeBasedForLoopColon: true
SpaceInEmptyBlock: false                                    SpaceInEmptyBlock: false
SpaceInEmptyParentheses: false                              SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1                           | SpacesBeforeTrailingComments: 2
SpacesInAngles:  false                                      SpacesInAngles:  false
SpacesInConditionalStatement: false                         SpacesInConditionalStatement: false
SpacesInContainerLiterals: true                             SpacesInContainerLiterals: true
SpacesInCStyleCastParentheses: false                        SpacesInCStyleCastParentheses: false
SpacesInParentheses: false                                  SpacesInParentheses: false
SpacesInSquareBrackets: false                               SpacesInSquareBrackets: false
SpaceBeforeSquareBrackets: false                            SpaceBeforeSquareBrackets: false
Standard:        Latest                                   | Standard:        Auto
StatementMacros:                                            StatementMacros:
  - Q_UNUSED                                                  - Q_UNUSED
  - QT_REQUIRE_VERSION                                        - QT_REQUIRE_VERSION
TabWidth:        8                                          TabWidth:        8
UseCRLF:         false                                      UseCRLF:         false
UseTab:          Never                                      UseTab:          Never
...                                                         ...


これらのオプションはclang-formatという規格が厳密に定めている. オプションの意味は http://algo13.net/clang/clang-format-style-oputions.html#tophttp://clang.llvm.org/docs/ClangFormatStyleOptions.html を参照すれば良いが, オプションはとても多いのでここでは重要なものを取り上げて解説する.

AccessModifierOffset

public: privateなどのアクセス修飾子は悩ましい部分も多い. 目立たせなくてはならないので, -1か-2を選ぶべきだが-1は中途半端な感じが好きでないのでGoogleのスタイルがいいと思う.

llvm: AccessModifierOffset:-1


class Sample
{
 public:
  Sample();
  ~Sample();
};

Google: AccessModifierOffset: -2


class Sample
{
public:
  Sample();
  ~Sample();
};


AlignAfterOpenBracket(BracketAlignmentStyle)

Alignとすると, (), [], {} で改行した時に関数の引数を整列してくれる. これはllvm googleどちらもAlignとなっている.


someLongFunction(argument1,
                 argument2);

DontAlignでは次のようになる.


someLongFunction(argument1,
    argument2);

AlignConsecutiveAssignments

変数の代入の式が連続している時に=を揃えるかどうか. llvm googleどちらもfalseとなっている. コード入力時に揃えるのも大変な上そこまで見易いとも思えない. falseの時:


int aaaa = 12;
int b  = 23;
int ccc = 23;

trueのとき:


int aaaa = 12;
int b    = 23;
int ccc  = 23;

AlignEscapedNewlines

エスケープされた改行文字を左側と右側どちらに表示するか.

llvm:Right


#define TEST                           \
  "long long test"                     \
  "string"                             \
  "!!"

google:Left


#define TEST       \
  "long long test" \
  "string"         \
  "!!"

AllowShortIfStatementsOnASingleLine

if (a) { return; } のようにifが短く一行で収まる時に整形時にそのままにしても良いかを決める.

llvm:Never

google:WithoutElse

AlwaysBreakBeforeMultilineStrings

文字列リテラルが連続している時に改行するか. 次のような文があるとする.


auto a = "aaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaa";

llvm:false


auto a = "aaaaaaaaaaaaaaaaaaaaaaaaaaa"
         "aaa";

google:true


auto a =
  "aaaaaaaaaaaaaaaaaaaaaaaaaaa"
  "aaa";

AlwaysBreakTemplateDeclarations

template宣言の時に改行をどうするか. Noの場合:


template <typename T> T foo() {
}
template <typename T> T foo(int aaaaaaaaaaaaaaaaaaaaa,
                            int bbbbbbbbbbbbbbbbbbbbb) {
}

llvm:MultiLine 複数行にまたがっている場合のみ適用する.


template <typename T> T foo() {
}
template <typename T>
T foo(int aaaaaaaaaaaaaaaaaaaaa,
      int bbbbbbbbbbbbbbbbbbbbb) {
}

google:Yes 常に適用する.


template <typename T>
T foo() {
}
template <typename T>
T foo(int aaaaaaaaaaaaaaaaaaaaa,
      int bbbbbbbbbbbbbbbbbbbbb) {
}

BinPackArguments

関数呼び出しの引数をなるべく詰めるか. llvm, google共にtrue:


auto a = function(aaaaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbbbbbbbbbbb, ccccccccccccccccccccccccc,
                  ddddddddddddddddddddddddd, eeeeeeeeeeeeeeeeeeeeeeeee, ddddddddddddddddddddddddd);

flaseの場合. やりすぎのように思える.


auto a = function(aaaaaaaaaaaaaaaaaaaaaaaaa,
                  bbbbbbbbbbbbbbbbbbbbbbbbb,
                  ccccccccccccccccccccccccc,
                  ddddddddddddddddddddddddd,
                  eeeeeeeeeeeeeeeeeeeeeeeee,
                  ddddddddddddddddddddddddd);

BinPackParameters

関数宣言や定義時にパラメータをなるべく詰めるか. llvm, google共にtrue:


void a(const std::string& bbbbbbbbbbbbbbbbbbbbbbbbb, const std::string& ccccccccccccccccccccccccc,
       const std::string& ddddddddddddddddddddddddd);

flaseの場合: これもやりすぎ.


void a(const std::string& bbbbbbbbbbbbbbbbbbbbbbbbb,
       const std::string& ccccccccccccccccccccccccc,
       const std::string& ddddddddddddddddddddddddd);

ConstructorInitializerAllOnOneLineOrOnePerLine

コンストラクタ初期化子部分が行に収まらない場合, 1行ずつ表示.

llvm:false


A::A()
  : some_variable{}, some_variable2{}, some_variable3{}, some_variable4{},
    some_variable5{}
{
}

google:true


A::A()
  : some_variable{},
    some_variable2{},
    some_variable3{},
    some_variable4{},
    some_variable5{}
{
}

DerivePointerAlignment

trueとすると&と*の整形の好みを読み取り, それを元にフォーマットする. フォールバックとしてのみ利用.

llvm:false

google:true

IncludeBlocks

#include のソートの仕方.

llvm:Preserve ブロックごとにそれぞれソートする.


#include "b.h"               into      #include "b.h"

#include <lib/main.h>                  #include "a.h"
#include "a.h"                         #include <lib/main.h>

google:Regroup ブロック関係なくソートした後, カテゴリごとにブロックで分けられる.


#include "b.h"               into      #include "a.h"
                                       #include "b.h"
#include <lib/main.h>
#include "a.h"                         #include <lib/main.h>

IndentCaseLabels

case:のときのインデントの仕方.

llvm:false


switch (x)
{
case A: break;
case B: break;
}

google:true こっちの方が綺麗に見えるが, インデントが深くなりがち.


switch (x)
{
  case A: break;
  case B: break;
}

IndentWidth

インデント幅. llvm, google共に2. 4の人も多いのかもしれないが, 4はインデントが深くなると見辛くなる.

KeepEmptyLinesAtTheStartOfBlocks

ブロック内の改行の仕方は一般的に不規則ではあるが, 先頭行を開けるかどうかに関しては空けたままか空けないかのどちらかとなる.

llvm:true


true:                                  
if (foo) {
                                       
  bar();
}

google:false 先頭の空行は蛇足なのでこっちがいいだろう.


false:
if (foo) { 
  bar();
}

ObjCBinPackProtocolList

Objective-Cなので関係ない.

llvm:Auto

google:Never

PenaltyBreakBeforeFirstCallParameter

The penalty for breaking a function call after call(. これはよくあることだと思うのでgoogleはペナルティが最小限となっている.

llvm:19

google:1

PenaltyReturnTypeOnItsOwnLine

Penalty for putting the return type of a function onto its own line. つまりreturn型のみだけで一行を占有すること.

llvm:60

google:200

PointerAlignment

llvm:Right


int* a;

google:Left


int *a;

SpacesBeforeTrailingComments

//コメントの前のスペースの数. 2の方が見やすいと思う.

llvm:1

google:2

Standard

llvm:Latest 最新のc++の規格に沿って整形.

google:Auto コードから最も傾向が近いものを推測して整形. なるべく最新でいいと思うが, 最新の構文は古いコンパイラではエラーになったりするのでその時は古いものにする必要がある.


c++03:                                 
vector<set<int> > x;


latest:
vector<set<int>> x;

UseTab

Neverが妥当. Alwaysで通常通り, ForIndentationでインデント用のみ. タブはスペースと違い幅が4だったり2だったりのばらつきが酷いので使わないのが妥当.

clang-formatコマンドの使い方

llvmやgoogleが定めるclang-formatにしたがって整形する. 整形が標準出力されるのでリダイレクトで書き込める.


clang-format --style=google main.cpp > main_google.cpp

-iオプションをつけることで標準出力ではなくファイルをその場で変更する.


clang-format -i --style=google main.cpp

.clang-formatファイルで定めたスタイルで整形する. fileはファイル名ではなく本当にfileと入力する. .clang-formatがファイルと同じディレクトリになければ親ディレクトリの.clangformatを再帰的に探していく.


clang-format -i --style=file main.cpp

clang-formatをエディタと統合する

http://clang.llvm.org/docs/ClangFormat.html で様々なエディタとclang-formatの対応状況がわかるが, 今回はvim向けにvim-clang-formatというプラグインを使って整形を自動的に行う方法を調べていく. これによってインデントの仕方もこの設定通りになる. 似たものにclang-format.pyがあるが別物なので注意. vim-clang-formatはpythonが必要なかったり柔軟性がより高い.

dein_lazy.tomlに次のように追加した. vim-operator-userプラグインを使うことで選択した範囲だけを整形することができる. googleは元からスタイルが素晴らしいので特に何もオプションを付けなかった.


[[plugins]]
repo = 'rhysd/vim-clang-format'
on_ft = ['c', 'cpp']
hook_add = '''
    let g:clang_format#style_options = {
        \ "BasedOnStyle" : "Google"}
    let g:clang_format#auto_format = 1
    autocmd FileType c,cpp,objc map <buffer><Leader>f <Plug>(operator-clang-format)'''

[[plugins]]
repo = 'kana/vim-operator-user'
on_ft = ['c', 'cpp']