BreakBeforeBraces,控制在哪种情况下把左花括号 { 放在同一行还是换到下一行,它有以下值:

Attach:        # 默认的“附在前一行”,各种场景(函数、类、控制语句等)都把 { 放在前一行末尾
Linux:         # 类/函数/命名空间等头部在下一行(像 Linux kernel 风格),控制语句仍附在前面
Mozilla:       # 类似 Attach,但对函数/enum 等有特定行为(主要与 Mozilla 风格一致)
Stroustrup:    # 函数/类通常把 { 放在下一行,但 else/catch 等仍放在同一行(折中)
Allman:        # 所有 { 都放在新行(最严格的换行风格)。
Whitesmiths:   # 把 { 放在新行并缩进(特殊缩进风格),主要为历史样式,较少用。
GNU:           # 大多数定义的 { 换行并额外缩进控制结构的 brace body(GNU 风格)
WebKit:        # 与 Attach 类似,但对函数有所区别(WebKit项目风格)。
Custom:        # 使用 BraceWrapping 子选项逐项控制(更精细)

推荐当需要混合行为时用 Custom + BraceWrapping 精确控制每种情况。

BraceWrapping 用在 BreakBeforeBraces: Custom 时,对不同情形的左花括号 { 如何换行
常见子项有布尔型(true / false)和少数枚举型(如 AfterControlStatement 可为 Never / MultiLine / Always)。

下面按子项逐条说明并给出示例。

1. 类名 之后

AfterClass,类定义后是否把 { 放在下一行

// true
class foo
{
};

// false
class foo {};

2. 函数名 之后

AfterFunction,函数定义头后 { 是否换行

// true
void f()
{
  // body
}

// false
void f() {
  // body
}

3. 控制语句 之后

AfterControlStatement (enum: Never / MultiLine / Always),控制语句(if / for / while / switch / …)后的 { 处理策略

  • Never: (默认) 保持 { 在同一行

  • MultiLine:仅当控制语句头换行时才换

  • Always:强制换行

3.1 效果一

  • AfterControlStatement: Never
#include <iostream>

int main () {
    int a = 1;
    int b = 2;

    // single-line condition
    if ( a == b ) {
        std::cout << "single-line if\n";
    }

    // multi-line condition
    if ( a == 1 && /* 当等于1时 */
         b == 2 /* 当等于2时 */ ) {
        std::cout << "multi-line if\n";
    }

    return 0;
}

3.2 效果二

  • AfterControlStatement: MultiLine
#include <iostream>

int main () {
    int a = 1;
    int b = 2;

    // single-line condition
    if ( a == b ) {
        std::cout << "single-line if\n";
    }

    // multi-line condition
    if ( a == 1 && /* 当等于1时 */
         b == 2 /* 当等于2时 */ )
    {
        std::cout << "multi-line if\n";
    }

    return 0;
}

3.3 效果三

  • AfterControlStatement: Always
#include <iostream>

int main () {
    int a = 1;
    int b = 2;

    // single-line condition
    if ( a == b )
    {
        std::cout << "single-line if\n";
    }

    // multi-line condition
    if ( a == 1 && /* 当等于1时 */
         b == 2 /* 当等于2时 */ )
    {
        std::cout << "multi-line if\n";
    }

    return 0;
}

4. case标签 之后

AfterCaseLabelcase 标签后的 { 是否换行

4.1 效果一

  • AfterCaseLabel: true
#include <iostream>

void handleValue (int v) {
    switch ( v )
    {
        case 0:
        {
            std::cout << "zero\n";
            break;
        }
        case 1:
        case 2:
        {
            std::cout << "one or two\n";
            break;
        }
        default:
        {
            std::cout << "other: " << v << '\n';
            break;
        }
    }
}

int main () {
    for ( int i = 0; i < 4; ++i ) handleValue(i);
    return 0;
}

4.2 效果二

  • AfterCaseLabel: false
#include <iostream>

void handleValue (int v) {
    switch ( v )
    {
        case 0: {
            std::cout << "zero\n";
            break;
        }
        case 1:
        case 2: {
            std::cout << "one or two\n";
            break;
        }
        default: {
            std::cout << "other: " << v << '\n';
            break;
        }
    }
}

int main () {
    for ( int i = 0; i < 4; ++i ) handleValue(i);
    return 0;
}

5. 结构体/联合体/枚举 之后

AfterStruct/AfterUnion/AfterEnumstruct / union / enum 后的 { 是否换行

5.1 效果一

  • AfterStruct: true
  • AfterUnion: true
  • AfterEnum: true
struct S
{
    int x;
    int y;
};

union U1
{
    int   a;
    float b;
};

enum E1
{
    A2,
    B2,
    C2
};

5.2 效果二

  • AfterStruct: false
  • AfterUnion: false
  • AfterEnum: false
struct S {
    int x;
    int y;
};

union U1 {
    int   a;
    float b;
};

enum E1 {
    A2,
    B2,
    C2
};

6. 命名空间 之后

AfterNamespace,控制 namespace{ 是否另起一行

6.1 效果一

  • AfterNamespace: true
namespace Foo
{
    int x = 42;
    namespace Bar
    {
        void f () { x = x + 1; }
    }    // namespace Bar
}    // namespace Foo

// 嵌套命名空间示例
namespace Outer
{
    namespace Inner
    {
        int y = 100;
    }
}    // namespace Outer

// 空命名空间示例
namespace EmptyNS
{
}

6.2 效果二

  • AfterNamespace: false
namespace Foo {
    int x = 42;
    namespace Bar {
        void f () { x = x + 1; }
    }    // namespace Bar
}    // namespace Foo

// 嵌套命名空间示例
namespace Outer {
    namespace Inner {
        int y = 100;
    }
}    // namespace Outer

// 空命名空间示例
namespace EmptyNS {}

7. extern 之后

AfterExternBlock,控制 extern 后的左花括号 { 是否换行

7.1 效果一

  • AfterExternBlock: true
// 一个 extern "C" 块,包含函数声明和 struct
extern "C"
{
    void c_function (int x);
    struct CStruct {
        int a;
    };
}

// 另一个 extern "C" 块,包含空实现(用于观察空块行为)
extern "C"
{
}

// C++ 常规函数,供对比
void cpp_func () {
    // body
}

7.2 效果二

  • AfterExternBlock: false
// 一个 extern "C" 块,包含函数声明和 struct
extern "C" {
void c_function (int x);
struct CStruct {
    int a;
};
}

// 另一个 extern "C" 块,包含空实现(用于观察空块行为)
extern "C" {}

// C++ 常规函数,供对比
void cpp_func () {
    // body
}

8. catch 之前

BeforeCatch,控制 catch 关键字是否放在 try 块结束 } 的下一行(换行)或保留在同一行(不换行)

8.1 效果一

  • BeforeCatch: true
#include <iostream>
#include <stdexcept>

void mayThrow (int x) {
    if ( x == 0 )
        throw std::runtime_error("zero");
    if ( x < 0 )
        throw -1;
}

int main () {
    for ( int v : {0, -1, 1} ) {
        try {
            mayThrow(v);
            std::cout << "ok: " << v << '\n';
        }
        catch ( const std::runtime_error& e ) {
            std::cout << "caught runtime_error: " << e.what() << '\n';
        }
        catch ( ... ) {
            std::cout << "caught other exception\n";
        }
    }
    return 0;
}

8.2 效果二

  • BeforeCatch: false
#include <iostream>
#include <stdexcept>

void mayThrow (int x) {
    if ( x == 0 )
        throw std::runtime_error("zero");
    if ( x < 0 )
        throw -1;
}

int main () {
    for ( int v : {0, -1, 1} ) {
        try {
            mayThrow(v);
            std::cout << "ok: " << v << '\n';
        } catch ( const std::runtime_error& e ) {
            std::cout << "caught runtime_error: " << e.what() << '\n';
        } catch ( ... ) {
            std::cout << "caught other exception\n";
        }
    }
    return 0;
}

9. else 之前

BeforeElse,控制 else 关键字是否放换行

9.1 效果一

  • BeforeElse: true
#include <iostream>

int main () {
    int x = 5;

    if ( x == 0 ) {
        std::cout << "zero\n";
    }
    else if ( x > 0 ) {
        std::cout << "positive\n";
    }
    else {
        std::cout << "negative\n";
    }

    if ( x % 2 == 0 ) {
        std::cout << "even\n";
    }
    else
        std::cout << "odd\n";    // single-statement else

    // nested if
    if ( x > 10 ) {
        if ( x % 5 == 0 ) {
            std::cout << "divisible by 5 and >10\n";
        }
        else {
            std::cout << ">10 but not div by 5\n";
        }
    }
    else if ( x == 10 ) {
        std::cout << "ten\n";
    }
    else {
        std::cout << "<=10\n";
    }

    return 0;
}

9.2 效果二

  • BeforeElse: false
#include <iostream>

int main () {
    int x = 5;

    if ( x == 0 ) {
        std::cout << "zero\n";
    } else if ( x > 0 ) {
        std::cout << "positive\n";
    } else {
        std::cout << "negative\n";
    }

    if ( x % 2 == 0 ) {
        std::cout << "even\n";
    } else
        std::cout << "odd\n";    // single-statement else

    // nested if
    if ( x > 10 ) {
        if ( x % 5 == 0 ) {
            std::cout << "divisible by 5 and >10\n";
        } else {
            std::cout << ">10 but not div by 5\n";
        }
    } else if ( x == 10 ) {
        std::cout << "ten\n";
    } else {
        std::cout << "<=10\n";
    }

    return 0;
}

10. while 之前

BeforeWhile,控制 do { … } while (cond); 中的 while 是否放到闭合大括号的下一行

10.1 效果一

  • BeforeWhile: true
#include <iostream>

int main () {
    int i = 0;

    do {
        std::cout << i << std::endl;
        ++i;
    }
    while ( i < 10 );

    return 0;
}

10.2 效果二

  • BeforeWhile: false
#include <iostream>

int main () {
    int i = 0;

    do {
        std::cout << i << std::endl;
        ++i;
    } while ( i < 10 );

    return 0;
}

11. lambdaBody 之前

BeforeLambdaBody,当设置为 true 时,会把 lambda 的左花括号 { 放到下一行,前提是 lambda 需要换行(或被禁止单行化)。

单独设置 BeforeLambdaBody: true并不强制把所有单行短 lambda 拆成多行,
因为如果 AllowShortLambdasOnASingleLine 允许单行(如 All),短 lambda 常会保留单行。

因此,要把短 lambda 拆成多行,常需同时:

  • AllowShortLambdasOnASingleLine: None,禁止短 lambda 单行化
  • BraceWrapping.BeforeLambdaBody: true,把 { 放到新行

11.1 效果一

  • AllowShortLambdasOnASingleLine: None
  • BeforeLambdaBody: true
#include <algorithm>
#include <iostream>
#include <vector>

int main () {
    std::vector<int> v{3, 1, 4, 1, 5};

    // 1) empty lambda
    auto empty = [] ()
    {
    };

    // 2) short single-statement lambda
    auto inc = [] (int x)
    {
        return x + 1;
    };
    std::cout << "inc(2) = " << inc(2) << '\n';

    // 3) short lambda passed as algorithm parameter
    std::sort(v.begin(), v.end(),
              [] (int a, int b)
              {
                  return a < b;
              });

    // 4) multi-statement lambda
    auto multi = [] (int x)
    {
        int y = x + 1;
        return y * y;
    };
    std::cout << "multi(3) = " << multi(3) << '\n';

    // 5) lambda with capture and comment
    int  offset = 10;
    auto add    = [offset] (int x)
    {    // add offset
        return x + offset;
    };
    std::cout << "add(5) = " << add(5) << '\n';

    return 0;
}

11.2 效果二

  • AllowShortLambdasOnASingleLine: None
  • BeforeLambdaBody: false
#include <algorithm>
#include <iostream>
#include <vector>

int main () {
    std::vector<int> v{3, 1, 4, 1, 5};

    // 1) empty lambda
    auto empty = [] () {
    };

    // 2) short single-statement lambda
    auto inc = [] (int x) {
        return x + 1;
    };
    std::cout << "inc(2) = " << inc(2) << '\n';

    // 3) short lambda passed as algorithm parameter
    std::sort(v.begin(), v.end(), [] (int a, int b) {
        return a < b;
    });

    // 4) multi-statement lambda
    auto multi = [] (int x) {
        int y = x + 1;
        return y * y;
    };
    std::cout << "multi(3) = " << multi(3) << '\n';

    // 5) lambda with capture and comment
    int  offset = 10;
    auto add    = [offset] (int x) {    // add offset
        return x + offset;
    };
    std::cout << "add(5) = " << add(5) << '\n';

    return 0;
}

12. SplitEmptyXx

总共有 3 个选项:

  • SplitEmptyFunction
  • SplitEmptyRecord
  • SplitEmptyNamespace

这些选项控制 “空” 主体(函数 / 记录(class/struct/union)/ namespace)是否拆成多行,即 {} 是否变为 {\n}
注意:最终表现会受 BraceWrapping 中其它子项(如 AfterFunctionAfterClassAfterNamespace)影响,要配合把 { 放到下一行的规则一起使用,才能得到预期的拆分效果。

12.1 效果一

  • AfterStruct: true

  • AfterClass: true

  • AfterFunction: true

  • AfterNamespace: true

  • SplitEmptyFunction: true

  • SplitEmptyRecord: true

  • SplitEmptyNamespace: true

// 空记录(struct/class)
struct EmptyStruct
{
};

class EmptyClass
{
};

// 空函数
// 需要把AllowShortFunctionsOnASingleLine设置为None,才能把空函数拆成多行
void emptyFunction ()
{
}

// 空命名空间
namespace EmptyNS
{
}

12.2 演示二

  • AfterStruct: true

  • AfterClass: true

  • AfterFunction: true

  • AfterNamespace: true

  • SplitEmptyFunction: false

  • SplitEmptyRecord: false

  • SplitEmptyNamespace: false

// 空记录(struct/class)
struct EmptyStruct
{};

class EmptyClass
{};

// 空函数
// 需要把AllowShortFunctionsOnASingleLine设置为None,才能把空函数拆成多行
void emptyFunction ()
{}

// 空命名空间
namespace EmptyNS
{}