26

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.

ivan.ukr
  • 2,853
  • 1
  • 23
  • 41
  • Same question basically: https://stackoverflow.com/questions/53797967/using-breakconstructorinitializers-aftercolon-of-clang-format – stijn Apr 25 '21 at 07:54
  • Look at https://stackoverflow.com/questions/47884523/put-break-before-colon-and-after-comma-in-constructor. It works if column limit is not reached. – MoonRaiser Dec 27 '21 at 14:43

4 Answers4

15

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.

Nikolai
  • 359
  • 2
  • 10
  • Thank you, will check this soon. – ivan.ukr Jan 03 '20 at 20:48
  • For convenience I made a release with the binary for Ubuntu16.04 so you don't need to build clang to test it. – Nikolai Jan 07 '20 at 00:02
  • 1
    they closed your pull request, as expected :( what a shame, definitely have my vote of +1 to include this one in official release. Not sure also why `PackConstructorInitializers` isn't available, as documented in https://clang.llvm.org/docs/ClangFormatStyleOptions.html – IdanB Oct 14 '21 at 16:40
  • 2
    Much better, I fought this through and the option *PackConstructorInitializers* fixes this issue, while addressing all corner cases. If it doesn't work for you, this change is new and only for Clang14 which is probably not released yet. – Nikolai Oct 15 '21 at 18:36
  • you are right, i had v13. is there expected date for v14 ? – IdanB Oct 20 '21 at 06:36
10

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.

Thomas
  • 4,980
  • 2
  • 15
  • 30
  • 1
    Already have it, still it doesn't affect the situation. Look above at my update. – ivan.ukr Jun 30 '19 at 17:00
  • all I can say that if I remove that line from my .clang-format, the initializers are not on a separate line each anymore. maybe you're editing the wrong file? just happened to me while trying this out ... – Thomas Jun 30 '19 at 18:47
  • If you are interested, I've added content of my .clang-format. – ivan.ukr Jun 30 '19 at 21:05
  • 1
    Your file seems to behave ok after I removed `ConstructorInitializerAllOnOneLineOrOnePerLine: 'false'` – Thomas Jun 30 '19 at 22:25
  • tried to remove - gives me "A() : m_a(someValue1), m_b(someValue2), m_c(someValue3)" as a single line, and I want these m_a, m_b and m_c to be on the separate lines... – ivan.ukr Jun 30 '19 at 22:57
  • Maybe bug in clang-format? By common sense ConstructorInitializerAllOnOneLineOrOnePerLine: 'false' should have put them onto separate lines. – ivan.ukr Jun 30 '19 at 22:59
4

I am trying to do the same thing. The best I could do was:

SpaceBeforeCtorInitializerColon: true
ConstructorInitializerIndentWidth: 4
BreakBeforeInheritanceComma: false
BreakInheritanceList: AfterColon
BreakConstructorInitializersBeforeComma: false
BreakConstructorInitializers: AfterColon
ConstructorInitializerAllOnOneLineOrOnePerLine: true

However, this will still place the list on a single line unless you break the column limit.

gregpaton08
  • 383
  • 3
  • 7
4

There are 2 other workarounds (with disadvantages):

  • Use pairs of // clang-format off and // clang-format on around the initializer list -> Disadvantage: clang-format also does not apply the useful reformatting for that part.
  • Set ColumnLimit to 0. This somehow fixes the use of AfterColon, making it work. Disadvantage: You can't enforce column limits for your project. In one of our projects (LMMS), we decided to only suggest a column limit: our coding conventions now contain a clause saying "Every line of text SHOULD be at most 120 characters long".
  • Use BreakConstructorInitializers: BeforeComma. It looks a bit different, but it works and it does pack any initialization into a separate line.
Johannes
  • 2,901
  • 5
  • 30
  • 50