Re: [問題] C++17 Structured binding 型別無法理解

看板C_and_CPP (C/C++)作者 (Cattuz)時間6年前 (2019/06/23 21:19), 6年前編輯推噓3(302)
留言5則, 3人參與, 6年前最新討論串2/3 (看更多)
※ 引述《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://www.ptt.cc/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://www.ptt.cc/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

06/23 21:51, 6年前 , 1F
"跟你外圍加的const和ref一點關係都沒有" 嚴格來說是有啦
06/23 21:51, 1F

06/23 21:51, 6年前 , 2F
temp是const, get<0>(temp)會走到有const的overload,
06/23 21:51, 2F

06/23 21:51, 6年前 , 3F
回傳的type也會多一個const, 只是那個const剛好被消掉
06/23 21:51, 3F
對 細節上是還有這一步沒錯XD 感謝指正

06/24 14:14, 6年前 , 4F
專業推
06/24 14:14, 4F
※ 編輯: sarafciel (210.242.163.170 臺灣), 06/24/2019 14:57:14

06/24 22:26, 6年前 , 5F
const int& tt = 5; // 同理把 const 拿掉就編不過了
06/24 22:26, 5F
是的 你得到他了 ※ 編輯: sarafciel (210.242.163.170 臺灣), 06/25/2019 16:11:09
文章代碼(AID): #1T3tn_7Z (C_and_CPP)
文章代碼(AID): #1T3tn_7Z (C_and_CPP)