Последнее обновление:2026-10-12
Структурированные привязки в C++17¶
Прежде чем говорить о структурированных привязках, вот несколько интервью-вопросов — проверьте, сможете ли вы на них ответить?
-
Как получить доступ к закрытым членам собственного класса с помощью структурированных привязок?
-
Как изменить члены собственного класса с помощью структурированных привязок?
Вряд ли многие смогут ответить на эти вопросы, и ни вопросов, ни ответов в интернете нет. Отталкиваясь от них, мы придём к теме этой статьи: как поддержать структурированные привязки для собственных типов и какие здесь есть подводные камни?
Примечание: для ленивых — ответы и код уже выложены в сообществе (知识星球).
Чтобы изложение было более плавным, начнём с примера.
1.Собственный тип¶
Пусть дан класс:
struct Foo {
Foo(int64_t id, std::string data) : id_(id), data_(std::move(data)) {}
void Print() { std::cout << "id = " << id_ << ", data = " << data_ << std::endl; }
private:
int64_t id_;
std::string data_;
};
Нужно, чтобы следующий код заработал:
int main() {
Foo f{12, "hello world"};
const auto& [id, data] = f;
std::cout << "id = " << id << ", data = " << data << std::endl;
f.Print();
}
При прямой компиляции получим:
Как же быть?
2.Поддержка структурированных привязок¶
Эту задачу решим в два шага:
1.Специализируем std::tuple_size и std::tuple_element
namespace std {
template <>
struct tuple_size<Foo> : std::integral_constant<std::size_t, 2> {};
template <>
struct tuple_element<0, Foo> {
using type = int64_t;
};
template <>
struct tuple_element<1, Foo> {
using type = std::string;
};
}
2.Добавим к приведённой выше структуре дружественные функции get и реализуем их:
template <std::size_t Index>
decltype(auto) get(const Foo& f);
template <>
decltype(auto) get<0>(const Foo& f) {
return f.id_;
}
template <>
decltype(auto) get<1>(const Foo& f) {
return f.data_;
}
Теперь всё работает корректно и мы получаем вывод:
Напоследок несколько вопросов:
- Выше показан доступ только для чтения; что произойдёт, если при доступе попытаться модифицировать через const auto &?
Например:
- Как поддержать доступ с изменением членов класса?
То есть, чтобы этот оператор мог нормально работать:
Ну вот и всё, на этом раздел закончен — обсуждайте в комментариях.
Похожие темы¶
- Атрибут [[nodiscard]] в C++17 | C++那些事
- std::string_view в C++17 | C++那些事
- PMR-ресурсы памяти в C++17 | C++那些事
- Семнадцать расширенных возможностей C++17 | C++那些事
- Выведение аргументов шаблона класса CTAD в C++17 | C++那些事
- C++17 optional_ref | C++那些事
- std::variant в C++17 | C++那些事
- Выведение auto в шаблонах C++17 | C++那些事
- Шаблоны переменных в C++17 | C++那些事