作者sarafciel (Cattuz)
看板C_and_CPP
标题Re: [问题] C++17 Structured binding 型别无法理解
时间Sun Jun 23 21:19:56 2019
※ 引述《lovejomi (JOMI)》之铭言:
: 标题: [问题] C++17 Structured binding 型别无法理解
: 时间: Sun Jun 23 03:00:34 2019
:
: 最近会看到一些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....
:
推文讲得很清楚了 map的key就是自带const
auto [k , v] : m 这行在传递的型态实际上是std::pair<const int , int>
std::pair可以被tuple_size当型态参数吃,所以是cppreference里提到的第二种case
会用tuple的方式做绑定,中括号外的cv跟reference不影响k跟v的型态
所以上面两个型态都是const int
: 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& 但实在不好读也很容易误用
1.拿出你的google,搜寻std::tuple source
2.点进去gnu给的std::tuple source ,然後把std::tie挖出来,你就可以看到:
template<typename... _Elements>
inline tuple<_Elements&...>
tie(_Elements&... __args)
{ return tuple<_Elements&...>(__args...); }
注意templates里面的型态参数跟回传的tuple差一个&
所以等号右边的型态就已经是std::tuple<int & , int &>了
这个也是cppreference的case 2,基本可以把等号左边当作是std::tuple
而外围的cv跟reference是在描述这个std::tuple
所以像const auto& [x, y] = std::tie(a, b)这种句子几乎等义於
const std::tuple<T1 , T2> & temp = std::tie(a, b);
T1跟T2取决於std::tie回传的型态
而x跟y分别代表tuple的get<0>跟get<1>,跟你外围加的const和ref一点关系都没有
要验证这件事情也很简单,你右边丢的东西是一个右值
所以你现在把左边的const拿掉来接这个右值看看,我敢跟你担保编译器会报错
:
:
:
:
: 还有很多看不是很懂...
:
: 总觉得找不到可以简单记忆的规则 连VC滑鼠移过去显示的型态也是错的....
:
:
:
: 请问版上有人能通透理解这些规则吗@@
:
:
: 不然我还是觉得写17以前写法
:
: for (const auto& p : map) 我可以明确知道他在写什麽好懂许多
因为你把auto当语法糖看了
或者这样讲好了
auto x = y;
Q:请问这行code在干嘛?
A:这个问题没有人答得出来,我自己都答不出来,
我甚至连这行code编译器给不给过我都不知道,因为我根本没有给y的型态。
也就是说这行程式码是完全依赖於y是什麽型态在做事的,它本身的资讯含量非常的少
所以很多人会说除非你很清楚auto在接的东西会怎麽运作,不然尽量少用它
而就你发问的这几个例子来讲,我想你其实连等号右边在做什麽事恐怕都没有很清楚
那更不用讲cppreference那一页里面那些case by case是在处理什麽东西的了
再来说说语法糖这件事。
auto在c++存在的目的并不是语法糖,尽管他有这个功能没错
auto是为了在写template的时候可以把对型态的依赖更进一步抽掉
以此来做更强的抽象才存在的,而他为了做到这件事的代价就是可读性
所以不要拿语法糖的角度来质疑他的可读性或型态不明确之类的
因为"型态不用明确"这件事正是他的存在意义。
:
: 讨论一下~
:
: 谢谢
:
:
:
:
: --
:
※ 发信站: 批踢踢实业坊(ptt.cc), 来自: 27.242.129.39 (台湾)
: ※ 文章网址: https://webptt.com/cn.aspx?n=bbs/C_and_CPP/M.1561230037.A.5C6.html
: 推 suhorng: 因为 k, v 的 type 要查 map 的 iterator 指向什麽呀 06/23 05:52
: → suhorng: for-range 转成 for + begin/end, 然後 map 的 06/23 05:52
: 推 RishYang: key是const是map的性质 06/23 05:54
: → suhorng: value_type 是 std::pair<const Key, T>, 所以自然由 06/23 05:55
: → suhorng: auto& [k,v] = *it 知道 k 是 const 06/23 05:56
: → RishYang: pair<const K, T> 06/23 05:56
: → RishYang: tuple<Types&...> tie( Types&... args ) 06/23 06:04
: → lovejomi: 晚点理解一下 但意思是我无法马上从code一眼看出型别 这 06/23 12:12
: → lovejomi: 样好吗? 06/23 12:12
: → lovejomi: 而且2. 我写了const 竟然没用,感觉很容易误会 06/23 12:13
: 推 Fenikso: 我觉得这有一半是tie的问题.. 06/23 13:36
: → Fenikso: 2的a是const ref to int, 不是ref to const int 06/23 13:36
: → Fenikso: x 打错 06/23 13:37
: 嘘 hsnuyi: 先搞懂map是啥 06/23 16:16
: 推 suhorng: 我查你贴的连结, 提到 cv-auto 的地方在 array type A 06/23 16:24
: → suhorng: 那里, 所以看来是用到 array 上的时候才看得出来? 06/23 16:28
: → suhorng: 我猜 const 不是加到 [???,???,...] 里面的 identifier 06/23 16:29
: → suhorng: 所以才会乍看之下没有效 06/23 16:29
: → lovejomi: key是const 但我如果是by value copy 他不该保留const 06/23 16:32
: → lovejomi: 吧? 06/23 16:32
: → suhorng: 可是看他 case 2 写的, 不管前面有没有 cv 或不管有没有 06/23 16:43
: → suhorng: &, && 都是 "reference to std::tuple_element<i, E>::ty 06/23 16:43
: → lovejomi: @fenikso: const ref 没这种东西吧?一般语法也写不出in 06/23 16:44
: → lovejomi: t &const foo; 还是这里有什麽高深原理? 06/23 16:44
: → RishYang: map与pair都不是array type 06/23 18:25
: → RishYang: 所以不会copy行为 06/23 18:25
--
※ 发信站: 批踢踢实业坊(ptt.cc), 来自: 123.193.54.11 (台湾)
※ 文章网址: https://webptt.com/cn.aspx?n=bbs/C_and_CPP/M.1561295999.A.1E3.html
※ 编辑: sarafciel (123.193.54.11 台湾), 06/23/2019 21:29:12
※ 编辑: sarafciel (123.193.54.11 台湾), 06/23/2019 21:30:06
1F:推 Fenikso: "跟你外围加的const和ref一点关系都没有" 严格来说是有啦 06/23 21:51
2F:→ Fenikso: temp是const, get<0>(temp)会走到有const的overload, 06/23 21:51
3F:→ Fenikso: 回传的type也会多一个const, 只是那个const刚好被消掉 06/23 21:51
对 细节上是还有这一步没错XD
感谢指正
4F:推 TitanEric: 专业推 06/24 14:14
※ 编辑: sarafciel (210.242.163.170 台湾), 06/24/2019 14:57:14
5F:推 chrisdar: const int& tt = 5; // 同理把 const 拿掉就编不过了 06/24 22:26
是的 你得到他了
※ 编辑: sarafciel (210.242.163.170 台湾), 06/25/2019 16:11:09