Структурированная привязка для замены std :: tie abuse

В чтении этот Краткий обзор финальных возможностей 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);

который я считал рекомендуемой практикой.

Может кто-нибудь предложить объяснение, почему они ссылаются на приведенный выше пример как взломать?

6

Решение

Я могу сказать это просто так:

На языке, где функции могут возвращать только одну переменную

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(...);
22

Другие решения

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 в этом случае они нашли решение, которое они считают лучшим.

1

По вопросам рекламы [email protected]