Skip to content

Commit cce628d

Browse files
committed
book: rewrite structured bindings 'why-first' (style demo)
Demonstrate the proposed motivation-driven rewrite style on one feature: lead with why the reader needs it and the problem it solves, explain the mechanism, contrast with the prior approach (std::tie), and show a concrete use case (map iteration). Also trials a per-section 'since C++NN' marker. This is a style sample for sign-off before applying the pattern across the book.
1 parent a8f82b0 commit cce628d

2 files changed

Lines changed: 38 additions & 13 deletions

File tree

book/en-us/02-usability.md

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -333,18 +333,11 @@ Foo foo2 {3, 4};
333333
334334
### Structured binding
335335
336-
Structured bindings provide functionality similar to the multiple return values
337-
provided in other languages. In the chapter on containers,
338-
we will learn that C++11 has added a `std::tuple` container for
339-
constructing a tuple that encloses multiple return values. But the flaw
340-
is that C++11/14 does not provide a simple way to get and define
341-
the elements in the tuple from the tuple,
342-
although we can unpack the tuple using `std::tie`
343-
But we still have to be very clear about how many objects this tuple contains,
344-
what type of each object is, very troublesome.
336+
*(since C++17)*
345337
346-
C++17 completes this setting,
347-
and the structured bindings let us write code like this:
338+
**Why do we need it?** Functions frequently need to "return several values at once" — for example, a computed result together with a status flag. In traditional C++ we either define a dedicated struct for this, or pack the values into a `std::tuple` and return that; but getting the values back out is clumsy. Unpacking with `std::tie` forces us to **declare every variable in advance** and to **know exactly** how many elements the tuple holds and the type of each — and any mismatch is an error.
339+
340+
**What problem does it solve?** C++17's **structured bindings** let us, in a single line, "unpack" a tuple, a `std::pair`, a raw array, or a struct with public data members, and bind the pieces directly to a set of **named** variables, with the types deduced by the compiler:
348341
349342
```cpp
350343
#include <iostream>
@@ -361,6 +354,21 @@ int main() {
361354
}
362355
```
363356

357+
**Why is this better than `std::tie`?** Structured bindings need no prior declaration and no spelled-out types, and they work not only on tuples but also on raw arrays and aggregate structs — making "multiple return values" read as naturally as in other modern languages.
358+
359+
**A typical use case**: iterating an associative container becomes especially clean, binding each key/value pair to meaningful names instead of writing `it->first` / `it->second`:
360+
361+
```cpp
362+
#include <iostream>
363+
#include <map>
364+
#include <string>
365+
366+
std::map<std::string, int> scores{{"alice", 90}, {"bob", 80}};
367+
for (const auto& [name, score] : scores) {
368+
std::cout << name << ": " << score << '\n';
369+
}
370+
```
371+
364372
The `auto` type derivation is described in the
365373
[auto type inference](#auto) section.
366374

book/zh-cn/02-usability.md

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -278,9 +278,11 @@ Foo foo2 {3, 4};
278278
279279
### 结构化绑定
280280
281-
结构化绑定提供了类似其他语言中提供的多返回值的功能。在容器一章中,我们会学到 C++11 新增了 `std::tuple` 容器用于构造一个元组,进而囊括多个返回值。但缺陷是,C++11/14 并没有提供一种简单的方法直接从元组中拿到并定义元组中的元素,尽管我们可以使用 `std::tie` 对元组进行拆包,但我们依然必须非常清楚这个元组包含多少个对象,各个对象是什么类型,非常麻烦。
281+
*(C++17 引入)*
282282
283-
C++17 完善了这一设定,给出的结构化绑定可以让我们写出这样的代码:
283+
**为什么需要它?** 函数经常需要「一次返回多个值」——例如同时返回计算结果与一个状态标志。在传统 C++ 中,我们要么为此专门定义一个结构体,要么用 `std::tuple` 把它们打包返回;但把这些值再取出来却相当笨拙:用 `std::tie` 拆包时,必须**事先声明**好每一个变量,还要**准确知道**元组里有几个元素、各自是什么类型,稍有出入便会出错。
284+
285+
**它解决了什么问题?** C++17 的**结构化绑定 (structured bindings)** 让我们能用一行代码,把一个元组、`std::pair`、原生数组或公开数据成员的结构体「拆开」,并直接绑定到一组**有名字**的变量上,类型则交由编译器推导:
284286
285287
```cpp
286288
#include <iostream>
@@ -297,6 +299,21 @@ int main() {
297299
}
298300
```
299301

302+
**相比 `std::tie` 好在哪里?** 结构化绑定无需事先声明变量、无需手写类型,并且不仅适用于元组,对原生数组和聚合结构体同样有效——这让「多返回值」的代码读起来就像其他现代语言一样自然。
303+
304+
**典型用例**:遍历关联容器时尤为优雅,可以把键值对直接绑定为有意义的名字,而不再写 `it->first` / `it->second`
305+
306+
```cpp
307+
#include <iostream>
308+
#include <map>
309+
#include <string>
310+
311+
std::map<std::string, int> scores{{"alice", 90}, {"bob", 80}};
312+
for (const auto& [name, score] : scores) {
313+
std::cout << name << ": " << score << '\n';
314+
}
315+
```
316+
300317
关于 `auto` 类型推导会在 [auto 类型推导](#auto)一节中进行介绍。
301318
302319
## 2.3 类型推导

0 commit comments

Comments
 (0)