作者poyenc (发箍)
看板C_and_CPP
标题Re: [问题] C++17 Structured binding 型别无法理解
时间Wed Jun 26 02:57:20 2019
※ 引述《lovejomi (JOMI)》之铭言:
: 最近会看到一些c++17语法 想说来研究一下
: https://en.cppreference.com/w/cpp/language/structured_binding
: 网路上介绍的文章许多 但都完全只是"介绍" 我实际上遇到一些怪异的型别推导结果
: 完全无法归纳规则 可能变成 知道可以用 但不敢乱用....
: 也许cppref 有介绍的很完整但我实在是看不太懂他表达的
: 举几个例子
: 1. 这属於网页上的case几?我不知道....
: std::map<int, int> m;
: for (auto& [k, v] : m) {
: k = 123;
: }
: k 是const& 变成不能改 ??? why....
: 好那我
: std::map<int, int> m;
: for (auto [k, v] : m) {
: k = 123;
: }
: k是const int....哪来的const....
: 2.
: int a = 1, b = 2;
: const auto& [x, y] = std::tie(a, b);
: x = 5566;
: 一脸就是const! 但竟然x是 int&.....可以改 why....+2
: 好那我
: auto [z, w] = std::tie(a, b);
: z = 123;
: 我什麽都不加....乍看就是int
: z竟然是int&....我不小心改到了a.....
: 这我可能还可以理解 他会去decltype(z) 结果是int& 但实在不好读也很容易误用
最好的语言学习资源是提案, 我们来参考原提案的最新修订版
P0144R2
[P0144R2] Structured bindings
https://bit.ly/2ZNT6kJ
看提案可以了解这个语言特性被设计来解决什麽问题, 使用的方法以
及可能会遇到的问题等. 先来讲最简单的案例: 只有用到
auto 来绑
定的情形:
auto [x,y,z] = f();
需要注意的是这里的
auto 用法和非 structured binding 的物件定
义不同, 是用来绑定等号右边的叙述, 如果右边是 std::tuple 则适
用以下规则:
auto __a = expression;
tuple_element<
0,
decltype(
E)>::type& x = get<
0>(__a);
tuple_element<
1,
decltype(
E)>::type& y = get<
1>(__a);
tuple_element<
2,
decltype(
E)>::type& z = get<
2>(__a);
E 是该叙述的型别, 你要接 std::tie() 的结果之前最好先查一下它
的回传型别:
template<
class... Types >
tuple<Types&...> tie( Types&... args )
noexcept;
原本的叙述经过代换会变成:
tuple<
int&,
int&> __a = std::tie(a, b);
tuple_element<
0, tuple<
int&,
int&>>::type
& z = get<
0>(__a);
tuple_element<
1, tuple<
int&,
int&>>::type
& w = get<
1>(__a);
再查一下 tuple_element 的 member type 作进一步代换:
tuple<
int&,
int&> __a = std::tie(a, b);
int& z = get<
0>(__a);
int& w = get<
1>(__a);
最後决定 z/w 型别为
int& 的地方是最外层的 & 而不是
tuple_element 的 member type, 以及刚好可以用 ref to lvalue
来绑定 get 的结果.
以上就是 structured binding 对於 std::tuple 的简单解说. 再
来是此特性的进阶应用:
撰写支援 structured binding 的自订型
别. 从
P0144R2 中间你可以看到:
tuple_element<#,
decltype(E)>
get<#>(expression)
叙述里都没有加前缀 std:: 修饰符, 这代表
标准允许使用者将此两
个元件定义在自己的命名空间里, 甚至 get 还可以作为 friend
member function. 所以当我们想为自己的型别提供某种程度的抽象
化, 又不愿意将资料成员 access level 都标记为 public 时, 就可
以利用这个设计:
https://wandbox.org/permlink/uETqTeLuT4zyim2t
--
P1389R0: Guidelines for Teaching C++ to Beginners
https://bit.ly/2GvDWKb
SG20 Education and Recommended Videos for Teaching C++
https://www.cjdb.com.au/sg20-and-videos
--
※ 发信站: 批踢踢实业坊(ptt.cc), 来自: 123.193.76.216 (台湾)
※ 文章网址: https://webptt.com/cn.aspx?n=bbs/C_and_CPP/M.1561489047.A.1E0.html
1F:推 sarafciel: 推 06/26 08:45
※ 编辑: poyenc (61.216.75.43 台湾), 06/26/2019 15:21:02