Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

clang-format: How to keep each element of constructor's initializer list on a separate line

I have a C++ class like this:

class A {
public:
    A() :
        m_a(someValue1),
        m_b(someValue2),
        m_c(someValue3)
    {
    }

    // .... other class members

private:
    A m_a;
    B m_b;
    C m_c;
};

After formatting this code with clang-format I am getting:

class A {
public:
    A() :
        m_a(someValue1), m_b(someValue2), m_c(someValue3)
    {
    }

    // .... other class members

private:
    A m_a;
    B m_b;
    C m_c;
};

I.e. initializer list in constructor got formatted onto single line, until they permitted maximum line length is reached.

My question is how to tell clang-format to leave each element on its own line, like it was in my original code before formatting? I could not find any suitable parameter. I've tried to set parameter AllowShortBlocksOnASingleLine, which seemed to me the most appropriate, to the both true and false, but it had no effect on this. So can anyone suggest how to implement such formatting?

Here is my .clang-format:

BasedOnStyle: Google
AccessModifierOffset: '-4'
AlignAfterOpenBracket: DontAlign
AlignConsecutiveAssignments: 'false'
AlignConsecutiveDeclarations: 'false'
AlignEscapedNewlines: Left
AlignOperands: 'true'
AlignTrailingComments: 'false'
AllowAllParametersOfDeclarationOnNextLine: 'true'
AllowShortBlocksOnASingleLine: 'true'
AllowShortCaseLabelsOnASingleLine: 'true'
AllowShortFunctionsOnASingleLine: None
AllowShortIfStatementsOnASingleLine: 'true'
AllowShortLoopsOnASingleLine: 'false'
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: 'false'
AlwaysBreakTemplateDeclarations: 'true'
BinPackArguments: 'true'
BinPackParameters: 'true'
BreakAfterJavaFieldAnnotations: 'true'
BreakBeforeBinaryOperators: NonAssignment
BreakBeforeBraces: Custom
BraceWrapping:
AfterFunction: true
SplitEmptyFunction: true
BreakBeforeInheritanceComma: 'false'
BreakBeforeTernaryOperators: 'true'
BreakConstructorInitializers: AfterColon
BreakStringLiterals: 'true'
ColumnLimit: '100'
CompactNamespaces: 'false'
ConstructorInitializerAllOnOneLineOrOnePerLine: 'false'
ConstructorInitializerIndentWidth: '4'
ContinuationIndentWidth: '8'
Cpp11BracedListStyle: 'true'
DerivePointerAlignment: 'false'
DisableFormat: 'false'
ExperimentalAutoDetectBinPacking: 'false'
FixNamespaceComments: 'true'
IncludeBlocks: Preserve
IndentCaseLabels: 'true'
IndentPPDirectives: None
IndentWidth: '4'
IndentWrappedFunctionNames: 'false'
JavaScriptQuotes: Double
JavaScriptWrapImports: 'true'
KeepEmptyLinesAtTheStartOfBlocks: 'false'
NamespaceIndentation: None
PointerAlignment: Left
ReflowComments: 'false'
SortIncludes: 'true'
SortUsingDeclarations: 'true'
SpaceAfterCStyleCast: 'true'
SpaceAfterTemplateKeyword: 'false'
SpaceBeforeAssignmentOperators: 'true'
SpaceBeforeParens: ControlStatements
SpaceInEmptyParentheses: 'false'
SpacesBeforeTrailingComments: '2'
SpacesInAngles: 'false'
SpacesInCStyleCastParentheses: 'false'
SpacesInContainerLiterals: 'false'
SpacesInParentheses: 'false'
SpacesInSquareBrackets: 'false'
Standard: Cpp11
TabWidth: '4'
UseTab: Never

UPDATE: There is option in clang-format called "ConstructorInitializerAllOnOneLineOrOnePerLine" descrined as follows: "If the constructor initializers don’t fit on a line, put each initializer on its own line". However, it still doesn't do what I want, because it only moves initializer to a new line if it doesn't fit to column limit. So looks like there is no way to force clang-format to put subsequent initializer on next line even if column limit is not reached. It would be nice if abovementioned option turned into enum with additional value that forces to put initializer to a next line even if column limit is not reached.

like image 869
ivan.ukr Avatar asked Jun 28 '19 18:06

ivan.ukr


2 Answers

Update 2021:

In clang14 there is a new option called
PackConstructorInitializers
which will do what you want.

The other options ConstructorInitializerAllOnOneLineOrOnePerLine and AllowAllConstructorInitializersOnNextLine, which were confusing anyways, will be deprecated.

End Update

I am pretty sure that this is a bug / shortcoming of clang-format. The issue was already addressed in 2015, but rejected by the clang-format developers: https://reviews.llvm.org/D14484

For what it is worth, I made a simple change to clang-format that should give you, your intended behaviour: https://github.com/Nikolai-Hlubek/clang/tree/ConstructorInitializer_AlwaysBreakAfterColon

I made a push request to upstream, but I doubt that it will be accepted.

like image 90
Nikolai Avatar answered Sep 21 '22 00:09

Nikolai


I personally use

BreakConstructorInitializers: BeforeComma

but other options are available. See Clang-Format Style Options, in the section BreakConstructorInitializers. It looks like your style would be AfterColon.

like image 21
Thomas Avatar answered Sep 23 '22 00:09

Thomas