Почему кажется, что никто не использует кортежи в C ++, будь то библиотека Boost Tuple или стандартная библиотека для TR1? Я читал много кода C ++ и очень редко вижу использование кортежей, но я часто вижу много мест, где кортежи решают многие проблемы (обычно возвращая несколько значений из функций).
Кортежи позволяют делать такие классные вещи, как это:
tie(a,b) = make_tuple(b,a); //swap a and b
Это определенно лучше, чем это:
temp=a;
a=b;
b=temp;
Конечно, вы всегда можете сделать это:
swap(a,b);
Но что, если вы хотите повернуть три значения? Вы можете сделать это с помощью кортежей:
tie(a,b,c) = make_tuple(b,c,a);
Кортежи также значительно упрощают возврат нескольких переменных из функции, что, вероятно, является гораздо более распространенным случаем, чем замена значений. Использование ссылок для возвращаемых значений, конечно, не очень элегантно.
Есть ли у кортежей какие-то большие недостатки, о которых я не думаю? Если нет, то почему они используются редко? Они медленнее? Или просто люди к ним не привыкли? Использование кортежей - хорошая идея?
a = a ^ b; b = a ^ b; a = a ^ b;
Ответы:
Потому что это еще не стандарт. Все, что нестандартно, имеет гораздо более высокие препятствия. Pieces of Boost стали популярными, потому что программисты требовали их. (на ум приходит hash_map). Но хотя кортеж удобен, это не такая уж очевидная победа, чтобы люди с ним возились.
источник
Циничный ответ заключается в том, что многие люди программируют на C ++, но не понимают и / или не используют функциональность более высокого уровня. Иногда это потому, что им не разрешают, но многие просто не пытаются (или даже не понимают).
В качестве примера без повышения: сколько людей используют функции, найденные в
<algorithm>
?Другими словами, многие программисты на C ++ просто программисты на C, использующие компиляторы C ++ и, возможно,
std::vector
иstd::list
. Это одна из причин, по которой использованиеboost::tuple
не более распространено.источник
Синтаксис кортежей C ++ может быть немного более подробным, чем хотелось бы большинству людей.
Рассматривать:
Поэтому, если вы хотите широко использовать кортежи, вы либо получите определения типов кортежей повсюду, либо повсюду получите досадно длинные имена типов. Мне нравятся кортежи. Использую при необходимости. Но обычно это ограничивается парой ситуаций, например, N-элементным индексом или при использовании мультиотображений для связывания пар итераторов диапазона. И это обычно в очень ограниченном объеме.
Все это очень уродливо и взломано по сравнению с чем-то вроде Haskell или Python. Когда здесь появится C ++ 0x и мы получим ключевые слова auto, кортежи станут выглядеть намного привлекательнее.
Полезность кортежей обратно пропорциональна количеству нажатий клавиш, необходимых для их объявления, упаковки и распаковки.
источник
Для меня это привычка: кортежи не решают для меня никаких новых проблем, только с некоторыми я уже могу справиться отлично. Менять местами значения по-прежнему проще по старинке - и, что более важно, я действительно не думаю о том, как поменять местами «лучше». Это достаточно хорошо, как есть.
Лично я не думаю, что кортежи - отличное решение для возврата нескольких значений - звучит как работа для
struct
s.источник
Но что, если вы хотите повернуть три значения?
Хорошо, поэтому с 4 и т.д. значениями в конечном итоге n-кортеж станет меньше кода, чем n-1 свопы. А со свопом по умолчанию это 6 присваиваний вместо 4, которые были бы у вас, если бы вы сами реализовали трехцикловый шаблон, хотя я надеюсь, что компилятор решит это для простых типов.
Вы можете придумать сценарии, в которых свопы будут громоздкими или неуместными, например:
немного неудобно распаковывать.
Дело в том, что существуют известные способы решения наиболее распространенных ситуаций, для которых подходят кортежи, и, следовательно, нет особой срочности при использовании кортежей. По крайней мере, я не уверен, что:
не делает 6 копий, что делает его совершенно непригодным для некоторых типов (наиболее очевидны коллекции). Не стесняйтесь убедить меня, что кортежи - хорошая идея для "больших" типов, сказав, что это не так :-)
Для возврата нескольких значений кортежи идеальны, если значения имеют несовместимые типы, но некоторым они не нравятся, если вызывающий объект может получить их в неправильном порядке. Некоторым людям вообще не нравятся множественные возвращаемые значения, и они не хотят поощрять их использование, делая их проще. Некоторые люди просто предпочитают именованные структуры для входных и выходных параметров, и, вероятно, их невозможно убедить с помощью бейсбольной биты использовать кортежи. О вкусах не спорят.
источник
Как отмечали многие, кортежи не так полезны, как другие функции.
Замена и вращение уловок - всего лишь уловки. Они совершенно сбивают с толку тех, кто не видел их раньше, и, поскольку это почти все, эти уловки - просто плохая практика разработки программного обеспечения.
Возврат нескольких значений с использованием кортежей гораздо менее самодокументируется, чем альтернативы - возврат именованных типов или использование именованных ссылок. Без этого самодокументирования легко спутать порядок возвращаемых значений, если они взаимно конвертируемы, и не поумнешь.
источник
Не все могут использовать ускорение, а TR1 еще не широко доступен.
источник
При использовании C ++ во встроенных системах получение библиотек Boost становится сложным. Они соединяются друг с другом, поэтому размер библиотеки растет. Вы возвращаете структуры данных или используете передачу параметров вместо кортежей. При возврате кортежей в Python структура данных находится в порядке и типе возвращаемых значений, это просто не явно.
источник
Вы редко их видите, потому что хорошо спроектированному коду они обычно не нужны - не так уж много случаев, когда использование анонимной структуры лучше использования именованной. Поскольку все, что на самом деле представляет кортеж, - это анонимная структура, большинство кодеров в большинстве ситуаций просто используют настоящие вещи.
Скажем, у нас есть функция «f», в которой может иметь смысл возврат кортежа. Как правило, такие функции достаточно сложны и могут выйти из строя.
Если «f» МОЖЕТ выйти из строя, вам понадобится возврат статуса - в конце концов, вы не хотите, чтобы вызывающие абоненты проверяли каждый параметр для обнаружения сбоя. "f", вероятно, вписывается в шаблон:
Это некрасиво, но посмотрите, насколько уродлива альтернатива. Обратите внимание, что мне все еще нужно значение статуса, но код более не читается и не короче. Вероятно, это тоже медленнее, поскольку я беру на себя 1 копию с кортежем.
Здесь скрывается еще один существенный недостаток - с помощью «ReturnInts» я могу добавить return alter «f», изменив «ReturnInts» БЕЗ ИЗМЕНЕНИЯ ИНТЕРФЕЙСА «f». Решение с кортежем не предлагает этой важной функции, что делает его худшим вариантом для любого библиотечного кода.
источник
using std::tuple;
и просто используяtuple
в коде.tuple
делает код менее читаемым, не более. В настоящее время в большинстве программных кодов содержится очень большое количество символов - видя,std::tuple
можно понять, что это такое.Конечно, кортежи могут быть полезны, но, как уже упоминалось, есть некоторые накладные расходы и пара препятствий, которые вам нужно преодолеть, прежде чем вы сможете их действительно использовать.
Если ваша программа постоянно находит места, где вам нужно вернуть несколько значений или поменять местами несколько значений, возможно, стоит пойти по пути кортежа, но в противном случае иногда проще сделать что-то классическим способом.
Вообще говоря, не у всех уже установлен Boost, и я, конечно, не стал бы загружать его и настраивать свои каталоги include для работы с ним только для его кортежей. Я думаю, вы обнаружите, что люди, уже использующие Boost, с большей вероятностью найдут использование кортежей в своих программах, чем пользователи, не использующие Boost, а мигранты с других языков (на ум приходит Python) с большей вероятностью просто расстроятся из-за отсутствия кортежей в C ++, чем изучать методы добавления поддержки кортежей.
источник
Поскольку хранилище данных
std::tuple
имеет худшие характеристики какstruct
для массива, так и для массива; весь доступ основан на n-й позиции, но невозможно выполнить итерацию сtuple
использованиемfor
цикла.Итак, если элементы в
tuple
концептуально являются массивом, я буду использовать массив, а если элементы концептуально не являются массивом, структура (которая имеет именованные элементы) более удобна в обслуживании. (a.lastname
более объяснительно, чемstd::get<1>(a)
).Это оставляет преобразование, упомянутое OP, как единственный жизнеспособный вариант использования кортежей.
источник
У меня такое ощущение, что многие используют Boost.Any и Boost.Variant (с некоторой инженерией) вместо Boost.Tuple.
источник