(Примечание: tuple
и tie
может быть взято из Boost или C ++ 11.)
При написании небольших структур только с двумя элементами я иногда склоняюсь к выбору a std::pair
, поскольку все важные вещи уже сделаны для этого типа данных, например, operator<
для строгого-слабого упорядочения .
Минусами являются бесполезные имена переменных. Даже если бы я сам это создал typedef
, через 2 дня я не вспомню, что first
и что second
именно было, особенно если они оба одного типа. Ситуация становится еще хуже для более чем двух участников, поскольку вложение - pair
отстой.
Другой вариант для этого -tuple
либо из Boost, либо из C ++ 11, но на самом деле это не выглядит лучше и понятнее. Поэтому я сам возвращаюсь к написанию структур, включая все необходимые операторы сравнения.
Поскольку в особенности это operator<
может быть довольно громоздко, я подумал о том, чтобы обойти весь этот беспорядок, просто полагаясь на операции, определенные для tuple
:
Пример operator<
, например, для строгого-слабого упорядочивания:
bool operator<(MyStruct const& lhs, MyStruct const& rhs){
return std::tie(lhs.one_member, lhs.another, lhs.yet_more) <
std::tie(rhs.one_member, rhs.another, rhs.yet_more);
}
( tie
Делает tuple
из T&
ссылок из переданных аргументов.)
Изменить : предложение @DeadMG о частном наследовании от tuple
не является плохим, но у него есть некоторые недостатки:
- Если операторы автономные (возможно, друзья), мне нужно наследовать публично
- С кастингом мои функции / операторы (в
operator=
частности) можно легко обойти - С помощью
tie
решения я могу исключить некоторых участников, если они не имеют значения для заказа.
Есть ли в этой реализации недостатки, которые мне нужно учитывать?
tie
не может быть применена к членам битового поля.tie(...)
вызовы будут дублироваться в различных операторах (=, ==, <и т. Д.), Вы можете написать частный встроенный метод,make_tuple(...)
чтобы инкапсулировать его, а затем вызывать его из различных других мест, напримерreturn lhs.make_tuple() < rhs.make_tuple();
(хотя возвращаемый тип из этот метод было бы забавно объявить!)auto tied() const{ return std::tie(the, members, here); }
Ответы:
Это, безусловно, упростит написание правильного оператора, чем его самостоятельно. Я бы посоветовал рассмотреть другой подход только в том случае, если профилирование показывает, что операция сравнения занимает много времени в вашем приложении. В противном случае простота обслуживания должна перевесить любые возможные проблемы с производительностью.
источник
tuple<>
«soperator<
будет медленнее , чем рукописные один.Я столкнулся с этой же проблемой, и в моем решении используются вариативные шаблоны С ++ 11. Вот код:
Часть .h:
И .cpp для базового случая без аргументов:
Теперь ваш пример становится:
источник
На мой взгляд, вы по-прежнему не
std::tuple
решаете ту же проблему, что и решает, а именно, вы должны знать как количество, так и имя каждой переменной-члена, вы дважды дублируете ее в функции. Вы можете выбратьprivate
наследование.Этот подход для начала немного беспорядок, но вы только сохраняете переменные и имена в одном месте, а не в каждом месте для каждого оператора, который хотите перегрузить.
источник
T& one_member(){ return std::get<0>(*this); }
etc? Но разве мне не нужно было бы предоставлять такой метод для каждого «члена», который у меня есть, включая перегрузки для константной и неконстантной версии?Если вы планируете использовать более одной перегрузки оператора или несколько методов из кортежа, я бы рекомендовал сделать кортеж членом класса или производным от кортежа. В противном случае то, что вы делаете, - это намного больше работы. При выборе между этими двумя, один важный вопрос , чтобы ответить: Вы хотите , чтобы ваш класс будет кортеж? В противном случае я бы рекомендовал содержать кортеж и ограничить интерфейс с помощью делегирования.
Вы можете создать средства доступа для «переименования» членов кортежа.
источник
operator<
помощьюstd::tie
разумного?» Я не понимаю, как этот ответ соотносится с этим вопросом.