В чтении этот Краткий обзор финальных возможностей c ++ 17 Я был немного удивлен разделом о структурированных привязках (выделено мое):
структурированные привязки
До сих пор был известен трюк с использованием std :: tie для непосредственного присвоения кортежа или пары различным переменным, вместо того, чтобы иметь дело с типом результата вручную. Это был взлом, а также переменные должны были существовать, теперь вы можете объявить переменные и инициализировать их в одну строку:
auto [a, b, c] = getvalues ();
Скобки нужны, getvalues возвращает кортеж. std :: pair не упоминается в предложении, поэтому неясно, работает ли это с парой, которая возвращается STL в некоторых методах вставки.
Я предполагаю, что они относятся к такого рода использованию std::tie
int a,b,c;
std::tie(a,b,c) = std::make_tuple(1,2,3);
который я считал рекомендуемой практикой.
Может кто-нибудь предложить объяснение, почему они ссылаются на приведенный выше пример как взломать?
Я могу сказать это просто так:
На языке, где функции могут возвращать только одну переменную
int a,b,c;
std::tie(a,b,c) = function_returning_multiple_values();
это взлом для:
auto [a, b, c] = function_returning_multiple_values();
так же, как в гипотетическом мире, где C ++ допускает только один параметр для функций
int p1, p2, p3;
p1 = ...;
p2 = ...;
p3 = ...;
function_taking_multiple_params(std::tie_params(p1, p2, p3));
будет взломать для:
function_taking_multiple_params(p1, p2, p3)
Вы настолько привыкли к ограничению C ++, что функция может возвращать не более одного объекта, но на самом деле это просто искусственное ограничение языка, так же как ограничение для принятия не более одного параметра будет искусственным ограничением языка.
std::tie
библиотека взломать отсутствующую языковую функцию И у него есть некоторые недостатки:
Являются ли структурированные привязки всем, чем они могли быть? Нет, но в большинстве случаев это все, что нам нужно.
Чего не хватает?
auto [a, std::string b, c] = foo();
где a
а также c
иметь тип выведен и b
явно «std :: string»
auto [a, [b1, b2], c] = foo();
откуда второй возвращаемый объект foo
это tuple
как объект.
std::tuple
все вместе):auto foo() -> [int, int]
вместо
auto foo() -> std::tuple<int, int>
auto foo() -> [int& key, int& value]
… хорошо … разве это не было бы хорошо
auto minmax_element(It begin, It end) -> [It min_it, It max_it];
auto [min = *min_it, max = *max_it] = minmax_element(...);
std::tie
сам по себе имеет другой функционал.
Он был предназначен для создания кортежа со ссылками на переменные
Создает кортеж из lvalue ссылок на его аргументы или экземпляры std :: ignore.
Это полезно для создания кортежей на лету без необходимости копировать переменные, потому что они являются ссылками. Я просто беру пример с cppreference для использования.
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 a,b,c;
std::tie(a,b,c) = std::make_tuple(1,2,3);
Он присваивает значения возвращаемого кортежа тому, который содержит ссылки в себе.
Это даже на cpprefence только что упоминается как «заметка»
std :: tie можно использовать для распаковки std :: pair, потому что std :: tuple имеет присваиваемое преобразование из пар
Таким образом, в C ++ 11 не был официальным способом прямого назначения значений, но std::tie
может быть использован как это, но, возможно, никогда не был предназначен для использования таким образом.
Поэтому они ввели новую «структурированную привязку».
Будь то std::tie
предполагалось использовать таким образом, или это «взлом» может быть личным мнением, я думаю, что люди, которые представили std::tie
лучше знать для этого. Но, учитывая, как структурированный вид обязывает заменить std::tie
в этом случае они нашли решение, которое они считают лучшим.