mirror of
https://github.com/Light-City/CPlusPlusThings.git
synced 2026-10-28 19:04:45 +08:00
- const README: rewrite the space-saving claim per issue #5 follow-ups (constant-expression const vs #define immediates; which const qualify as constant expressions) - const README: fix the class-section diagnosis per issue #338 (overload resolution picks the const overload; the restriction only surfaces once that overload is removed) - sizeof README: virtual-inheritance result is compiler-dependent (GCC merges vbptr+vfptr -> 16, MSVC keeps them separate -> 32) #246 - static README: new section on internal linkage / access restriction with anonymous-namespace comparison #142 - 10-day practice: full problem list table + fixed day links #136 - new design_pattern/singleton/singleton_default.hpp: reusable thread-safe CRTP singleton template, compile+concurrency tested #303
This commit is contained in:
117
site_extras/modern-cpp-cpp17-structured-bindings.md
Normal file
117
site_extras/modern-cpp-cpp17-structured-bindings.md
Normal file
@@ -0,0 +1,117 @@
|
||||
> 来自 [C++那些事网站](https://light-city.github.io/stories_things/modern-cpp/cpp17/structured-bindings/) 的文章,由站点同步脚本导出。
|
||||
|
||||
# C++17 结构化绑定
|
||||
|
||||
在聊结构化绑定之前,有几个面试问题,看看你会不会?
|
||||
|
||||
- 如何使用结构化绑定访问自定义类的私有成员?
|
||||
|
||||
- 如何使用结构化绑定修改自定义类的成员呢?
|
||||
|
||||
这几个题目估计没几个人能答上来,题目与答案网上也都没有,基于这些问题,我们引出本文的内容:如何为自定义类型支持结构化绑定,里面有哪些坑?
|
||||
|
||||
**注:懒人版,答案与代码已放星球。**
|
||||
|
||||
为了让本文的内容更加丝滑,从示例出发。
|
||||
|
||||
## 1.自定义类型
|
||||
|
||||
如果给定一个类:
|
||||
|
||||
```cpp
|
||||
struct Foo {
|
||||
Foo(int64_t id, std::string data) : id_(id), data_(std::move(data)) {}
|
||||
void Print() { std::cout << "id = " << id_ << ", data = " << data_ << std::endl; }
|
||||
|
||||
private:
|
||||
int64_t id_;
|
||||
std::string data_;
|
||||
};
|
||||
```
|
||||
|
||||
要让下面这个代码运行起来:
|
||||
|
||||
```cpp
|
||||
int main() {
|
||||
Foo f{12, "hello world"};
|
||||
const auto& [id, data] = f;
|
||||
std::cout << "id = " << id << ", data = " << data << std::endl;
|
||||
f.Print();
|
||||
}
|
||||
```
|
||||
|
||||
如果直接运行会编译:
|
||||
|
||||
```cpp
|
||||
cannot decompose inaccessible member 'Foo::id_' of 'const Foo'
|
||||
42 | const auto& [id, data] = f;
|
||||
```
|
||||
|
||||
那么怎么做呢?
|
||||
|
||||
## 2.支持结构化绑定
|
||||
|
||||
这个问题我们使用两个步骤:
|
||||
|
||||
1.特化 `std::tuple_size` 和 `std::tuple_element`
|
||||
|
||||
```cpp
|
||||
namespace std {
|
||||
template <>
|
||||
struct tuple_size<Foo> : std::integral_constant<std::size_t, 2> {};
|
||||
|
||||
template <>
|
||||
struct tuple_element<0, Foo> {
|
||||
using type = int64_t;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct tuple_element<1, Foo> {
|
||||
using type = std::string;
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
2.为上面的结构体添加友元get函数,然后实现即可:
|
||||
|
||||
```cpp
|
||||
template <std::size_t Index>
|
||||
decltype(auto) get(const Foo& f);
|
||||
|
||||
template <>
|
||||
decltype(auto) get<0>(const Foo& f) {
|
||||
return f.id_;
|
||||
}
|
||||
|
||||
template <>
|
||||
decltype(auto) get<1>(const Foo& f) {
|
||||
return f.data_;
|
||||
}
|
||||
```
|
||||
|
||||
此时便可以正常的工作了,得到输出:
|
||||
|
||||
```cpp
|
||||
id = 12, data = hello world
|
||||
id = 12, data = hello world
|
||||
```
|
||||
|
||||
最后,抛出几个问题:
|
||||
|
||||
- 上面提供的是只读访问,如果在访问的时候修改const auto &会发生什么?
|
||||
|
||||
例如:
|
||||
|
||||
```cpp
|
||||
auto& [id, data] = f;
|
||||
```
|
||||
|
||||
- 如何支持对类成员的修改访问?
|
||||
|
||||
即,让这个语句能够正常运行
|
||||
|
||||
```cpp
|
||||
auto& [id, data] = f;
|
||||
```
|
||||
|
||||
好了,本节完,欢迎留言区交流。
|
||||
Reference in New Issue
Block a user