Structured Binding Declaration là một tính năng mới trong C++17, cho phép bạn khai báo nhiều biến cùng lúc và gán chúng với các thành phần của một đối tượng. Cú pháp sử dụng từ khóa auto kết hợp với cặp ngoặc vuông [].
Cú pháp cơ bản:
cv-auto+ref [var1, var2, ..., varN] = init_expr;
cv-auto+ref [var1, var2, ..., varN] (init_expr);
cv-auto+ref [var1, var2, ..., varN] {init_expr};
// cv-auto+ref bao gồm: auto, auto const, auto &, auto&&, v.v.
Có hai dạng biến trong structured binding:
- Biến không tham chiếu: Đối tượng khởi tạo được sao chép, và biến sẽ ràng buộc với các thành phần của bản sao đó.
- Biến tham chiếu: Không sao chép đối tượng, biến ràng buộc trực tiếp với các thành phần của đối tượng gốc.
Biểu thức khởi tạo có thể thuộc một trong ba loại sau:
- Mảng: Biến ràng buộc với từng phần tử của mảng.
- Kiểu hỗ trợ tuple_size (như
pair,tuple): Biến ràng buộc với kết quả củaget<i>(e). - Struct có thành viên public: Biến ràng buộc với các thành viên public của struct.
Ví dụ mã nguồn C++17
#include <iostream>
#include <utility>
#include <set>
#include <map>
using namespace std;
struct S {
int a, b, c;
};
map<string, int> get_map() {
return {
{"hello", 1},
{"world", 2},
{"it's", 3},
{"me", 4}
};
}
int main() {
// Gán từ pair
auto [x, y] = pair(2, "3"s);
cout << x << y << endl; // Output: 23
// Gán từ kết quả insert set
set<string> my_set;
if (auto [it, ok] = my_set.insert("Hello"); ok) {
cout << *it << endl; // Output: Hello
}
// Gán từ mảng
int data[] = {1, 2, 3, 4};
const auto& [a1, a2, a3, a4] = data;
cout << a1 << a2 << a3 << a4 << endl; // Output: 1234
// Gán từ struct
S obj = {4, 5, 6};
auto& [p, q, r] = obj;
p = 0; q = 1; r = 2;
cout << obj.a << obj.b << obj.c << endl; // Output: 012
// Gán trong vòng lặp for
for (auto&& [key, val] : get_map()) {
cout << "key=" << key << " val=" << val << endl;
}
// Output:
// key=hello val=1
// key=it's val=3
// key=me val=4
// key=world val=2
}
Phân tích chi tiết
- Dòng 20: Khai báo biến
x(int) vày(string) từpair.xnhận first,ynhận second. - Dòng 24:
itlà iterator,oklà bool từ kết quảinsertcủa set. - Dòng 28:
a1đếna4làconst int&tương ứng 4 phần tử mảng. - Dòng 32:
p,q,rlàint&ràng buộc với các thành viêna,b,ccủa struct. - Dòng 37:
keylàstring&&vàvallàint&từ pair trong map.
Mã tương đương C++14
#include <iostream>
#include <utility>
#include <set>
#include <map>
using namespace std;
struct S {
int a, b, c;
};
map<string, int> get_map() {
return {
{"hello", 1},
{"world", 2},
{"it's", 3},
{"me", 4}
};
}
int main() {
auto kv = make_pair(2, "3"s);
auto& x = kv.first; auto& y = kv.second;
cout << x << y << endl;
set<string> my_set;
set<string>::iterator it;
bool ok;
tie(it, ok) = my_set.insert("Hello");
if (ok) cout << *it << endl;
int data[] = {1, 2, 3, 4};
const auto& a1 = data[0], &a2 = data[1], &a3 = data[2], &a4 = data[3];
cout << a1 << a2 << a3 << a4 << endl;
S obj = {4, 5, 6};
auto& p = obj.a, &q = obj.b, &r = obj.c;
p = 0; q = 1; r = 2;
cout << obj.a << obj.b << obj.c << endl;
for (auto&& kv : get_map()) {
auto&& key = forward<decltype(kv.first)>(kv.first);
auto&& val = forward<decltype(kv.second)>(kv.second);
cout << "key=" << key << " val=" << val << endl;
}
}