Почему использование кортежей в C ++ не является более распространенным? - PullRequest
119 голосов
/ 13 мая 2009

Почему никто не использует кортежи в C ++, ни Boost Tuple Library , ни стандартную библиотеку для 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);

Кортежи также значительно облегчают возврат нескольких переменных из функции, что, вероятно, является гораздо более распространенным случаем, чем обмен значениями. Использование ссылок для возврата значений, безусловно, не очень элегантно.

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

Ответы [ 12 ]

122 голосов
/ 13 мая 2009

Циничный ответ таков: многие люди программируют на C ++, но не понимают и / или не используют функциональность более высокого уровня. Иногда это потому, что они не разрешены, но многие просто не пытаются (или даже не понимают).

В качестве примера без наддува: сколько людей используют функциональность, найденную в <algorithm>?

Другими словами, многие программисты на C ++ просто программисты на C, использующие компиляторы C ++, и, возможно, std::vector и std::list. Это одна из причин, почему использование boost::tuple не является более распространенным.

40 голосов
/ 13 мая 2009

Потому что это еще не стандарт. У всего нестандартного есть намного более высокое препятствие. Pieces of Boost стали популярными, потому что программисты требовали их. (hash_map приходит на ум). Но несмотря на то, что кортеж удобен, это не такая непреодолимая и очевидная победа, что люди беспокоятся об этом.

23 голосов
/ 13 мая 2009

Синтаксис кортежа C ++ может быть более многословным, чем хотелось бы большинству людей.

Рассмотрим:

typedef boost::tuple<MyClass1,MyClass2,MyClass3> MyTuple;

Так что, если вы хотите широко использовать кортежи, вы либо повсеместно получаете определения типов кортежей, либо везде раздражающие длинные имена. Я люблю кортежи. Я использую их, когда это необходимо. Но обычно это ограничивается парой ситуаций, таких как индекс N-элемента или использование мультикарт для связывания пар итераторов диапазона. И это обычно в очень ограниченном объеме.

Это все очень уродливо и хакерски выглядит по сравнению с чем-то вроде Haskell или Python. Когда C ++ 0x попадет сюда и мы получим ключевое слово 'auto', кортежи станут выглядеть намного привлекательнее.

Полезность кортежей обратно пропорциональна количеству нажатий клавиш, необходимых для их объявления, упаковки и распаковки.

9 голосов
/ 13 мая 2009

Для меня это привычка, руки вниз: кортежи не решают для меня никаких новых проблем, лишь немногие из них я могу справиться просто отлично. Поменяться ценностями все еще легче по старинке - и, что более важно, я не думаю о том, как поменять «лучше». Это достаточно хорошо, как есть.

Лично я не думаю, что кортежи - это отличное решение для возврата нескольких значений - звучит как работа для struct с.

8 голосов
/ 13 мая 2009

Но что, если вы хотите повернуть три значения?

swap(a,b);
swap(b,c);  // I knew those permutation theory lectures would come in handy.

ОК, поэтому при значениях 4 и т. Д. В конечном итоге n-кортеж становится меньше кода, чем n-1 перестановки. А при свопе по умолчанию выполняется 6 назначений вместо 4, которые вы получили бы, если бы вы внедрили шаблон с тремя циклами самостоятельно, хотя я надеюсь, что компилятор решит это для простых типов.

Вы можете придумать сценарии, в которых свопы громоздки или неуместны, например:

tie(a,b,c) = make_tuple(b*c,a*c,a*b);

немного неудобно распаковывать.

Суть в том, что существуют известные способы решения наиболее распространенных ситуаций, для которых кортежи хороши, и, следовательно, нет особой необходимости срочно заниматься кортежами. Если ничего другого, я не уверен, что:

tie(a,b,c) = make_tuple(b,c,a);

не делает 6 копий, что делает его совершенно неподходящим для некоторых типов (коллекции наиболее очевидны). Не стесняйтесь убеждать меня, что кортежи - хорошая идея для «больших» типов, говоря, что это не так: -)

Для возврата нескольких значений кортежи идеальны, если значения имеют несовместимые типы, но некоторым людям они не нравятся, если вызывающая сторона может получить их в неправильном порядке. Некоторым людям совсем не нравятся множественные возвращаемые значения, и они не хотят поощрять их использование, делая их проще. Некоторые люди просто предпочитают именованные структуры для входных и выходных параметров, и, вероятно, их нельзя убедить бейсбольной битой использовать кортежи. Нет учета вкуса.

7 голосов
/ 25 декабря 2012

Как отмечали многие, кортежи не так полезны, как другие функции.

  1. Обмен и вращение уловок - это просто уловки. Они совершенно сбивают с толку тех, кто их раньше не видел, и, поскольку это почти все, эти уловки - просто плохая практика разработки программного обеспечения.

  2. Возвращение нескольких значений с использованием кортежей намного менее самодокументировано, чем альтернативы - возвращение именованных типов или использование именованных ссылок. Без этого самодокументирования легко перепутать порядок возвращаемых значений, если они взаимно конвертируемы и не будут мудрее.

6 голосов
/ 13 мая 2009

Не каждый может использовать повышение, и TR1 еще не широко доступен.

5 голосов
/ 13 мая 2009

При использовании C ++ во встроенных системах получение библиотек Boost становится сложным. Они соединяются друг с другом, поэтому размер библиотеки увеличивается. Вы возвращаете структуры данных или используете передачу параметров вместо кортежей. При возврате кортежей в Python структура данных имеет порядок, а тип возвращаемых значений просто не явный.

4 голосов
/ 30 декабря 2012

Вы редко видите их, потому что хорошо разработанный код, как правило, не нуждается в них - в дикой природе не так много случаев, когда использование анонимной структуры лучше, чем использование именованной структуры. Поскольку все, что на самом деле представляет кортеж, является анонимной структурой, большинство программистов в большинстве ситуаций просто используют реальную вещь.

Скажем, у нас есть функция "f", в которой возврат кортежа может иметь смысл. Как правило, такие функции, как правило, достаточно сложны, поэтому они могут не работать.

Если «f» МОЖЕТ потерпеть неудачу, вам необходимо вернуть статус - в конце концов, вы не хотите, чтобы вызывающие абоненты проверяли каждый параметр, чтобы обнаружить ошибку. «f», вероятно, вписывается в шаблон:

struct ReturnInts ( int y,z; }
bool f(int x, ReturnInts& vals);

int x = 0;
ReturnInts vals;
if(!f(x, vals)) {
    ..report error..
    ..error handling/return...
}

Это не красиво, но посмотри, какая уродливая альтернатива. Обратите внимание, что мне все еще нужно значение статуса, но код больше не читается и не короче. Это, вероятно, тоже медленнее, так как я несу стоимость 1 копии с кортежем.

std::tuple<int, int, bool> f(int x);
int x = 0;
std::tuple<int, int, bool> result = f(x); // or "auto result = f(x)"
if(!result.get<2>()) {
    ... report error, error handling ...
}

Еще один существенный недостаток скрыт здесь - с помощью ReturnInts я могу добавить изменение «f», изменив «ReturnInts» БЕЗ ИЗМЕНЕНИЯ ИНТЕРФЕЙСА f. Решение для кортежей не предлагает такой критической функции, которая делает его худшим ответом для любого библиотечного кода.

3 голосов
/ 13 мая 2009

Конечно, кортежи могут быть полезны, но, как уже упоминалось, есть некоторые накладные расходы и одно или два препятствия, которые вы должны перепрыгнуть, прежде чем вы сможете их реально использовать.

Если ваша программа постоянно находит места, в которых вам нужно вернуть несколько значений или поменять несколько значений, возможно, стоит пойти по пути кортежа, но в противном случае иногда проще просто сделать вещи классическим способом.

Вообще говоря, не у всех уже установлен Boost, и я, конечно, не стал бы загружать его и настраивать мои каталоги включения для работы с ним только для его кортежных средств. Я думаю, вы обнаружите, что люди, уже использующие Boost, с большей вероятностью обнаружат использование кортежей в своих программах, чем пользователи, не использующие Boost, а мигранты из других языков (вспоминается Python) с большей вероятностью будут просто расстроены отсутствием кортежей в C ++, чем исследовать методы добавления поддержки кортежей.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...