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

作者: poyenc (髮箍)   2019-06-26 02:57:20
※ 引述《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
作者: sarafciel (Cattuz)   2019-06-26 08:45:00

Links booklink

Contact Us: admin [ a t ] ucptt.com