有没有办法在新行上拆分逻辑条件?

Posted

技术标签:

【中文标题】有没有办法在新行上拆分逻辑条件?【英文标题】:Is there a way to split logical conditions on new lines? 【发布时间】:2021-11-15 01:25:46 【问题描述】:

例如,我希望我的行长为 120 - 所以通常代码仅在 120 个字符后包装。但更常见的情况是,我们不希望将逻辑条件放在新行上:

我有以下表达:

    if ((long_function_name_12345().get_some_status1() != status1) ||
        (long_function_name_12345().get_some_status2() != status2) || 
        force || 
        some_other_logical_bool)
    
    

当我将它格式化时,我得到:

    if ((long_function_name_12345().get_some_status1() != status1) ||
        (long_function_name_12345().get_some_status2() != status2) || force || some_other_logical_bool)
    
    

这不是那么好。我希望行为是,一旦我们超过列限制(在本例中为 120),然后在任何逻辑块上中断。我找到了一种强制方法:

    if ((long_function_name_12345().get_some_status1() != status1) ||
        (long_function_name_12345().get_some_status2() != status2) || // break
        force || // break
        some_other_logical_bool)
    
    

这有点废话,但有效,但(IMO)不那么丑陋,然后将其包装在 // clang-format off/on 标签中......

clang 格式版本 10.0.0-4ubuntu1~18.04.2

.clang 格式的内容:

---
Language:        Cpp
# BasedOnStyle:  WebKit
AccessModifierOffset: -4
AlignAfterOpenBracket: AlwaysBreak
AlignConsecutiveMacros: false
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AlignEscapedNewlines: Right
AlignOperands:   false
AlignTrailingComments: false
AllowAllArgumentsOnNextLine: false
AllowAllConstructorInitializersOnNextLine: false
AllowAllParametersOfDeclarationOnNextLine: false
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
# Don't allow function on one line, e.g. 'int f() return 1;' - unless its inline
AllowShortFunctionsOnASingleLine: InlineOnly
AllowShortLambdasOnASingleLine: All
AllowShortIfStatementsOnASingleLine: Never
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: MultiLine
BinPackArguments: false
BinPackParameters: false
BraceWrapping:
  AfterCaseLabel:  true
  AfterClass:      true
  AfterControlStatement: true
  AfterEnum:       true
  AfterFunction:   true
  AfterNamespace:  true
  AfterObjCDeclaration: true
  AfterStruct:     true
  AfterUnion:      true
  AfterExternBlock: true
  BeforeCatch:     true
  BeforeElse:      true
  IndentBraces:    true
  SplitEmptyFunction: true
  SplitEmptyRecord: true
  SplitEmptyNamespace: true
# have line breaks after operators: 'if (a ||' instead of on the next line ' || b'
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Allman
BreakBeforeInheritanceComma: false
BreakInheritanceList: BeforeColon
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
BreakConstructorInitializers: BeforeComma
BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: true
# effectively the line length limit before clang-format starts to use multiple lines
ColumnLimit:     120
CommentPragmas:  '^ IWYU pragma:'
CompactNamespaces: false
ConstructorInitializerAllOnOneLineOrOnePerLine: false
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
# format braces lists (uniform init) like a function param list
Cpp11BracedListStyle: true
DeriveLineEnding: true
DerivePointerAlignment: false
DisableFormat:   false
ExperimentalAutoDetectBinPacking: false
FixNamespaceComments: false
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: true
IndentGotoLabels: true
IndentPPDirectives: None
IndentWidth:     4
IndentWrappedFunctionNames: false
javascriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: true
MacroBlockBegin: ''
MacroBlockEnd:   ''
MaxEmptyLinesToKeep: 1
NamespaceIndentation: Inner
ObjCBinPackProtocolList: Auto
ObjCBlockIndentWidth: 4
ObjCSpaceAfterProperty: true
ObjCSpaceBeforeProtocolList: true
PenaltyBreakAssignment: 2
PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakString: 1000
PenaltyBreakTemplateDeclaration: 10
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 60
# 'int *p' instead of 'int* p;'
PointerAlignment: Right
ReflowComments:  true
SortIncludes:    true
SortUsingDeclarations: true
SpaceAfterCStyleCast: false
SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true
SpaceBeforeCpp11BracedList: true
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: ControlStatements
SpaceBeforeRangeBasedForLoopColon: true
SpaceInEmptyBlock: true
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
...

我找不到任何明显的东西 - 也许它有点太具体了。

【问题讨论】:

个人意见,但多行ifs 经常是代码气味...如果您的条件如此庞大,它不适合 120 列 if,也许值得将它移到它的自己的函数,有一个正确的名字。 @m88 我认为这是一个没有达到 120 字符限制的行的示例,但仍应包装 @m88 4630....数字是正确的 - 如果行(完全像示例)不是 120 个字符长,我想强制更短。如果 if 语句超过 120 个字符(可能会发生在具有几个命​​名空间深度的长变量名中)。 【参考方案1】:

这是我能找到/想出的最好的(如我更新的问题中所述):

    if ((long_function_name_12345().get_some_status1() != status1) ||
        (long_function_name_12345().get_some_status2() != status2) || // break
        force || // break
        some_other_logical_bool)
    
    

即通过添加某种注释,它会强制 clangformat 不合并行

【讨论】:

空评论有同样的效果吗? “break”这个词在 C 和 C++ 中具有超载的含义,使其成为一个不适用的令人困惑的评论。 (免责声明:我没有使用过该工具,虽然它看起来不错。) 是的,但我认为人们可能会删除空的//,认为它是错误留下的。也许// clangfmt 之类的会更好:)

以上是关于有没有办法在新行上拆分逻辑条件?的主要内容,如果未能解决你的问题,请参考以下文章

逻辑运算 (Python 3.4) - 有没有办法简化长条件语句?

一次简单易懂的多态重构实践,让你理解条件逻辑

将一个条件从else语句中拆分出来导致的bug

为啥 Rails 应用程序没有拆分,业务逻辑没有转移到 gem 中? [关闭]

如何通过案例分析证明 Isabelle/HOL 中的逻辑条件是真还是假?

如何最好地应用更新逻辑