У boost есть тип данных для заданных операций, который проще, чем STL?

Я нахожу, что метод C ++ STL делает простые операции с множеством, довольно неуклюжими в использовании. Например, чтобы найти разницу между двумя наборами:

std::set newUserIds; set_difference(currentUserIds.begin(), currentUserIds.end(), mPreviousUserIds.begin(), mPreviousUserIds.end(), std::inserter(newUserIds, newUserIds.end())); std::set missingUserIds; set_difference(mPreviousUserIds.begin(), mPreviousUserIds.end(), currentUserIds.begin(), currentUserIds.end(), std::inserter(missingUserIds, missingUserIds.end())); mPreviousUserIds = currentUserIds; 

Повышает ли предложение альтернативный набор classов, который сводит приведенный выше пример к чему-то вроде этого:

 set_type newUserIds = currentUserIds.difference(mPreviousUserIds); set_type missingUserIds = mPreviousUserIds.difference(currentUserIds); 

(Аналогично QSet в Qt, который переопределяет operator- таким образом.)

См. Алгоритмы установки диапазона усиления . Однако они все еще ожидают выходного iteratorа.

Неа. Но я вот как это очистить.

Во-первых, перепишите функции на основе iteratorа как функции на основе диапазона. Это уменьшает ваш шаблон.

Во-вторых, им нужно вернуть конструкторы контейнеров, а не принимать iteratorы вставки: это дает вам эффективный синтаксис присваивания.

В-третьих, и, возможно, слишком далеко, напишите их как названные операторы.

Конечным результатом является то, что вы получаете:

 set s = a *intersect* b; set s2 = c -difference- s; set s3 = a *_union_* (b *intersect* s -difference- s2); 

… после написания лодочного кода шаблона в другом месте.

Насколько я знаю, boost делает шаг 1.

Но каждый из этих трех этапов должен значительно уменьшить ваш шаблон.

Контейнерный строитель:

 template struct container_builder { Functor f; template::value>::type> operator Container() const { Container retval; using std::back_inserter; f( back_inserter(retval) ); return retval; } container_builder(Functor const& f_):f(f_) {} }; 

который требует записи is_back_insertable (довольно стандартный SFINAE).

Вы завершаете функционал, основанный на ранжировании (или на основе iteratorа), который принимает back_insert_iterator в качестве последнего аргумента и использует std::bind для привязки входных параметров, оставляя последний доступным. Затем передайте это container_builder и верните его.

container_builder затем может быть неявно применен к любому контейнеру, который принимает std::back_inserter (или имеет свой собственный ADL back_inserter ), и move семантики на каждом контейнере std делает конструкцию-then-return довольно эффективной.

Вот моя дюжина строк с именем operator library:

 namespace named_operator { templatestruct make_operator{make_operator(){}}; template struct half_apply { T&& lhs; }; template half_apply operator*( Lhs&& lhs, make_operator ) { return {std::forward(lhs)}; } template auto operator*( half_apply&& lhs, Rhs&& rhs ) -> decltype( named_invoke( std::forward(lhs.lhs), Op{}, std::forward(rhs) ) ) { return named_invoke( std::forward(lhs.lhs), Op{}, std::forward(rhs) ); } } 

живой пример, использующий его для реализации vector *concat* vector . Он поддерживает только один оператор, но его простота проста. Для серьезного использования я бы посоветовал иметь функцию times которая по умолчанию вызывает invoke для *blah* , add for +blah+ который делает то же самое, и т. Д. может напрямую вызывать invoke .

Затем клиентский программист может перегрузить специфическую для оператора перегрузку, и он работает, или общий invoke .

Вот аналогичная библиотека, используемая для реализации *then* на обеих возвращающих функции и фьючерсах.

Вот примитив *in* :

 namespace my_op { struct in_t:named_operator::make_operator{}; in_t in; template bool named_invoke( E const& e, in_t, C const& container ) { using std::begin; using std::end; return std::find( begin(container), end(container), e ) != end(container); } } using my_op::in; 

живой пример .

Нет, и я думаю, что у этого никогда не было такого, это общий принцип в C ++, который, когда вы можете иметь функцию, не являющуюся членом, чтобы выполнять работу, никогда не делает эту функцию членом. так что это не может быть так, но может быть Boost :: Range помочь вам.

  • сравнение iteratorов из разных контейнеров
  • Зачем использовать начальные и конечные функции не-членов в C ++ 11?
  • Как обновить существующий элемент std :: set?
  • Написание собственного контейнера STL
  • На картах STL лучше использовать map :: insert, чем ?
  • Удаление STL не работает должным образом?
  • Почему вывод аргумента шаблона отключен с помощью std :: forward?
  • Есть ли какой-либо реальный риск для получения из контейнеров STL C ++?
  • Какие недостатки C ++ следует избегать?
  • Как удалить элементы из контейнеров STL?
  • максимальное значение int
  • Давайте будем гением компьютера.