7. 规则详解(4) 大括号换行(Braces)
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标签 之后
AfterCaseLabel,case 标签后的 { 是否换行
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/AfterEnum,struct / 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 中其它子项(如 AfterFunction、AfterClass、AfterNamespace)影响,要配合把 { 放到下一行的规则一起使用,才能得到预期的拆分效果。
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
{}







