clang-format:如何将构造函数的初始化列表的每个元素保持在单独的行中
clang-format: How to keep each element of constructor's initializer list on a separate line
我有一个像这样的 C++ class:
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;
};
用 clang-format 格式化此代码后,我得到:
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;
};
即构造函数中的初始化列表被格式化为单行,直到达到它们允许的最大行长度。
我的问题是如何告诉 clang-format 将每个元素保留在自己的行中,就像格式化之前在我的原始代码中一样?我找不到任何合适的参数。我试图将在我看来最合适的参数 AllowShortBlocksOnASingleLine 设置为 true 和 false,但它对此没有影响。那么有人可以建议如何实现这种格式吗?
这是我的 .clang 格式:
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: 在 clang 格式中有一个名为 "ConstructorInitializerAllOnOneLineOrOnePerLine" 的选项,描述如下:"If the constructor initializers don’t fit on a line, put each initializer on its own line"。
但是,它仍然无法满足我的要求,因为它只会在不符合列限制的情况下将初始值设定项移动到新行。所以看起来没有办法强制 clang-format 将后续初始化器放在下一行,即使未达到列限制。
如果上述选项变成具有附加值的枚举,即使未达到列限制也强制将初始化程序放入下一行,那就太好了。
我个人使用
BreakConstructorInitializers: BeforeComma
但还有其他选项可用。请参阅 BreakConstructorInitializers
部分中的 Clang-Format Style Options。看起来你的风格应该是 AfterColon
。
我正在尝试做同样的事情。我能做的最好的是:
SpaceBeforeCtorInitializerColon: true
ConstructorInitializerIndentWidth: 4
BreakBeforeInheritanceComma: false
BreakInheritanceList: AfterColon
BreakConstructorInitializersBeforeComma: false
BreakConstructorInitializers: AfterColon
ConstructorInitializerAllOnOneLineOrOnePerLine: true
但是,这仍会将列表放在一行中除非您打破了列数限制。
2021 年更新:
在 clang14 中有一个名为
的新选项
PackConstructorInitializers
这会做你想做的。
其他选项 ConstructorInitializerAllOnOneLineOrOnePerLine 和 AllowAllConstructorInitializersOnNextLine 无论如何都令人困惑,将被弃用。
结束更新
我很确定这是 clang-format 的错误/缺点。
该问题已在 2015 年得到解决,但被 clang 格式开发人员拒绝:https://reviews.llvm.org/D14484
对于它的价值,我对 clang-format 做了一个简单的改变,它应该给你,你的预期行为:
https://github.com/Nikolai-Hlubek/clang/tree/ConstructorInitializer_AlwaysBreakAfterColon
我向上游发出了推送请求,但我怀疑它是否会被接受。
还有 2 个其他解决方法(有缺点):
- 在初始化列表周围使用成对的
// clang-format off
和 // clang-format on
-> 缺点:clang-format
也不会对该部分应用有用的重新格式化。
- 将
ColumnLimit
设置为 0
。这以某种方式修复了 AfterColon
的使用,使其工作。缺点:您不能为项目强制执行列限制。在我们的一个项目 (LMMS) 中,我们决定只建议一个列限制:我们的编码约定现在包含一个子句说 "Every line of text SHOULD be at most 120 characters long".
- 使用
BreakConstructorInitializers: BeforeComma
。它看起来有点不同,但它确实有效,而且它确实将所有初始化打包到单独的行中。
我有一个像这样的 C++ class:
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;
};
用 clang-format 格式化此代码后,我得到:
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;
};
即构造函数中的初始化列表被格式化为单行,直到达到它们允许的最大行长度。
我的问题是如何告诉 clang-format 将每个元素保留在自己的行中,就像格式化之前在我的原始代码中一样?我找不到任何合适的参数。我试图将在我看来最合适的参数 AllowShortBlocksOnASingleLine 设置为 true 和 false,但它对此没有影响。那么有人可以建议如何实现这种格式吗?
这是我的 .clang 格式:
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: 在 clang 格式中有一个名为 "ConstructorInitializerAllOnOneLineOrOnePerLine" 的选项,描述如下:"If the constructor initializers don’t fit on a line, put each initializer on its own line"。 但是,它仍然无法满足我的要求,因为它只会在不符合列限制的情况下将初始值设定项移动到新行。所以看起来没有办法强制 clang-format 将后续初始化器放在下一行,即使未达到列限制。 如果上述选项变成具有附加值的枚举,即使未达到列限制也强制将初始化程序放入下一行,那就太好了。
我个人使用
BreakConstructorInitializers: BeforeComma
但还有其他选项可用。请参阅 BreakConstructorInitializers
部分中的 Clang-Format Style Options。看起来你的风格应该是 AfterColon
。
我正在尝试做同样的事情。我能做的最好的是:
SpaceBeforeCtorInitializerColon: true
ConstructorInitializerIndentWidth: 4
BreakBeforeInheritanceComma: false
BreakInheritanceList: AfterColon
BreakConstructorInitializersBeforeComma: false
BreakConstructorInitializers: AfterColon
ConstructorInitializerAllOnOneLineOrOnePerLine: true
但是,这仍会将列表放在一行中除非您打破了列数限制。
2021 年更新:
在 clang14 中有一个名为
的新选项
PackConstructorInitializers
这会做你想做的。
其他选项 ConstructorInitializerAllOnOneLineOrOnePerLine 和 AllowAllConstructorInitializersOnNextLine 无论如何都令人困惑,将被弃用。
结束更新
我很确定这是 clang-format 的错误/缺点。 该问题已在 2015 年得到解决,但被 clang 格式开发人员拒绝:https://reviews.llvm.org/D14484
对于它的价值,我对 clang-format 做了一个简单的改变,它应该给你,你的预期行为: https://github.com/Nikolai-Hlubek/clang/tree/ConstructorInitializer_AlwaysBreakAfterColon
我向上游发出了推送请求,但我怀疑它是否会被接受。
还有 2 个其他解决方法(有缺点):
- 在初始化列表周围使用成对的
// clang-format off
和// clang-format on
-> 缺点:clang-format
也不会对该部分应用有用的重新格式化。 - 将
ColumnLimit
设置为0
。这以某种方式修复了AfterColon
的使用,使其工作。缺点:您不能为项目强制执行列限制。在我们的一个项目 (LMMS) 中,我们决定只建议一个列限制:我们的编码约定现在包含一个子句说 "Every line of text SHOULD be at most 120 characters long". - 使用
BreakConstructorInitializers: BeforeComma
。它看起来有点不同,但它确实有效,而且它确实将所有初始化打包到单独的行中。