2016-10-25 5 views
5

При чтении this резюме C++ 17 конечных функций, я был немного удивлен разделе о структурированных привязок (курсив мой):Структурированные связывание заменить брани станд :: TIE

структурированные привязок

До сих пор существовал известный трюк, чтобы злоупотреблять std :: tie, чтобы напрямую назначать кортеж или пару различным переменным, вместо того чтобы иметь дело с типом результата вручную. Это был взлом, а также переменные должны были существовать, теперь вы можете объявить переменные и инициализировать их в одной строке:

auto [a, b, c] = getvalues ​​();

Скобки необходимы, getvalues ​​возвращает кортеж. std :: pair не упоминается в предложении, поэтому неясно, работает ли это с парой, которая возвращается STL в некоторых методах вставки.

Я предполагаю, что они относятся к этому виду использования std::bind

int a,b,c; 
std::tie(a,b,c) = std::make_tuple(1,2,3); 

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

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

+1

Заключительные запятые в этом цитируемом тексте невыносимы! –

ответ

15

я могу поставить его просто так:

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

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 явно "станд :: строка"

  • Верстка , Например .:
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(...); 
+0

Что это была бы подпись 'function_returning_multiple_values ​​()'? –

+0

@EmeraldWeapon: Он вернет некоторый объект, на котором работает структурированное связывание. Для примера 'std :: tie' он будет возвращать типы' std :: tuple'. –

+0

Хорошо, так что все еще не будет никакого истинного множественного возвращаемого значения в C++ 17? –

0

std::tie сама по себе имеет другую функциональность.

Он был предназначен для создания кортежа со ссылками на переменные

Создает кортеж Lvalue ссылок на его аргументы или экземпляры станда :: игнорировать.

Это полезно для создания кортежей «на лету» без необходимости копировать переменные, потому что они являются ссылками. Я просто беру пример от 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 просто упоминаются как «записка»

станд :: Галстук может быть использован для распаковки зОго :: пары, потому что станд :: кортеж имеет преобразующее задание из пар

Таким образом, в C++ 11 не был официальным способом прямого назначения значений, но std::tie может использоваться как это, но, возможно, никогда не предназначался для использования таким образом.

Таким образом, они представили новое «структурированное связывание».

Должен ли использоваться std::tie таким образом или «взломать» может быть личное мнение, я думаю, люди, которые представили std::tie, знают лучше всего для этого. Но рассматривая, как структурированный тип привязки заменяет std::tie в этом случае, они придумали решение, которое, по их мнению, будет лучше.

+0

Boost.Tuple показывает [разложение кортежа как основной пример для 'boost :: tie'] (http://www.boost.org/doc/libs/1_61_0/libs/tuple/doc/tuple_users_guide.html#tiers). В самом деле, это * единственный пример * для использования 'boost :: tie'. –

+0

@NicolBolas Ну, это было о 'std :: tie' и еще больше, почему это считается« взломом »в упомянутой статье. Это объясняет, почему люди так думают. Я также помещал «хак» в кавычки, чтобы указать, что это не может рассматриваться как хак, но некоторые могут видеть это как намерение. Я отредактирую это, хотя на ответ. – Hayt