Полезные новации С++17. Структурированное связывание.
Вы часто работаете с кортежами?
Если нет - то, возможно, будете - прочитав нижеследующее. Не только кортежи предполагают возвращение множества значений из функции, но они также имеют специальную языковую поддержку, делающую код более легким и понятным.
Например (std::tie example):
std::set<S> mySet; S value{42, "Test", 3.14}; std::set<S>::iterator iter; bool inserted; // unpacks the return val of insert into iter and inserted std::tie(iter, inserted) = mySet.insert(value); if (inserted) std::cout << "Value was inserted\n";
Заметьте, что вам необходимо сначала объявить iter и inserted. Затем, можно использовать std::tie для создания кортежа. Переопределённый оператор присваивания кортежа может принимать пару (pair<>) значений.
С С++17:
std::set<S> mySet; S value{42, "Test", 3.14}; auto [iter, inserted] = mySet.insert(value);
И всё! Дело в волшебных квадратных скобках!
Полный рабочий код:
#include <cstdlib>
#include <iostream>
#include <set>
#include <string>
#include <iterator>
#include <tuple>
// { autofold
struct S {
int n;
std::string s;
float d;
bool operator<(const S& rhs) const
{
// compares n to rhs.n,
// then s to rhs.s,
// then d to rhs.d
return std::tie(n, s, d) < std::tie(rhs.n, rhs.s, rhs.d);
}
};
// }
int main()
{
std::set<S> mySet;
// pre C++17:
{
S value{42, "Test", 3.14};
std::set<S>::iterator iter;
bool inserted;
// unpacks the return val of insert into iter and inserted
std::tie(iter, inserted) = mySet.insert(value);
if (inserted)
std::cout << "Value was inserted\n";
}
// with C++17:
{
S value{100, "abc", 100.0};
const auto [iter, inserted] = mySet.insert(value);
if (inserted)
std::cout << "Value(" << iter->n << ", " << iter->s << ", ...) was inserted" << "\n";
}
}
Структурированное связывание не ограничено кортежами, мы имеем три варианта:
1) Инициализатор является массивом:
// works with arrays: double myArray[3] = { 1.0, 2.0, 3.0 }; auto [a, b, c] = myArray;
2) Инициализатор поддерживает std::tuple_size<> и предоставляет функцию get<N>().
auto [a, b] = myPair; // binds myPair.first/second
Другими словами, вы можете предоставить поддержку для ваших классов через добавление реализации интерфейса get<N>().
3) Тип инициализатора содержит только нестатические, открытые члены:
struct S { int x1 : 2; volatile double y1; }; S f(); const auto [ x, y ] = f();
Наиболее интересна поддержка циклов:
std::map myMap; for (const auto & [k,v] : myMap) { // k - key // v - value }
Пример:
#include <iostream>
#include <map>
#include <string>
int main()
{
const std::map<std::string, std::string> capitals{
{ "Poland", "Warsaw" },
{ "USA", "Washington" },
{ "France", "Paris" },
{ "UK", "London" },
{ "Germany", "Berlin" }
};
for (auto[key, value] : capitals)
{
std::cout << "key : " << key << ", value : " << value << std::endl;
}
return 0;
}
Поддержка:
GCC: 7.0, Clang: 4.0, MSVC: in VS 2017.3.
Подробности:
http://cpp-today.blogspot.ru/2017/03/structured-binding-c17-inside.html
https://skebanga.github.io/structured-bindings/
Если нет - то, возможно, будете - прочитав нижеследующее. Не только кортежи предполагают возвращение множества значений из функции, но они также имеют специальную языковую поддержку, делающую код более легким и понятным.
Например (std::tie example):
std::set<S> mySet; S value{42, "Test", 3.14}; std::set<S>::iterator iter; bool inserted; // unpacks the return val of insert into iter and inserted std::tie(iter, inserted) = mySet.insert(value); if (inserted) std::cout << "Value was inserted\n";
Заметьте, что вам необходимо сначала объявить iter и inserted. Затем, можно использовать std::tie для создания кортежа. Переопределённый оператор присваивания кортежа может принимать пару (pair<>) значений.
С С++17:
std::set<S> mySet; S value{42, "Test", 3.14}; auto [iter, inserted] = mySet.insert(value);
И всё! Дело в волшебных квадратных скобках!
Полный рабочий код:
#include <cstdlib>
#include <iostream>
#include <set>
#include <string>
#include <iterator>
#include <tuple>
// { autofold
struct S {
int n;
std::string s;
float d;
bool operator<(const S& rhs) const
{
// compares n to rhs.n,
// then s to rhs.s,
// then d to rhs.d
return std::tie(n, s, d) < std::tie(rhs.n, rhs.s, rhs.d);
}
};
// }
int main()
{
std::set<S> mySet;
// pre C++17:
{
S value{42, "Test", 3.14};
std::set<S>::iterator iter;
bool inserted;
// unpacks the return val of insert into iter and inserted
std::tie(iter, inserted) = mySet.insert(value);
if (inserted)
std::cout << "Value was inserted\n";
}
// with C++17:
{
S value{100, "abc", 100.0};
const auto [iter, inserted] = mySet.insert(value);
if (inserted)
std::cout << "Value(" << iter->n << ", " << iter->s << ", ...) was inserted" << "\n";
}
}
Структурированное связывание не ограничено кортежами, мы имеем три варианта:
1) Инициализатор является массивом:
// works with arrays: double myArray[3] = { 1.0, 2.0, 3.0 }; auto [a, b, c] = myArray;
2) Инициализатор поддерживает std::tuple_size<> и предоставляет функцию get<N>().
auto [a, b] = myPair; // binds myPair.first/second
Другими словами, вы можете предоставить поддержку для ваших классов через добавление реализации интерфейса get<N>().
3) Тип инициализатора содержит только нестатические, открытые члены:
struct S { int x1 : 2; volatile double y1; }; S f(); const auto [ x, y ] = f();
Наиболее интересна поддержка циклов:
std::map myMap; for (const auto & [k,v] : myMap) { // k - key // v - value }
Пример:
#include <iostream>
#include <map>
#include <string>
int main()
{
const std::map<std::string, std::string> capitals{
{ "Poland", "Warsaw" },
{ "USA", "Washington" },
{ "France", "Paris" },
{ "UK", "London" },
{ "Germany", "Berlin" }
};
for (auto[key, value] : capitals)
{
std::cout << "key : " << key << ", value : " << value << std::endl;
}
return 0;
}
Поддержка:
GCC: 7.0, Clang: 4.0, MSVC: in VS 2017.3.
Подробности:
http://cpp-today.blogspot.ru/2017/03/structured-binding-c17-inside.html
https://skebanga.github.io/structured-bindings/
Комментарии
Отправить комментарий