2013-12-16 4 views
5

Мой вопрос частично мотивирован this question.Возможно ли составить алгоритмы STL без промежуточного контейнера

Есть ли способ составить алгоритмы STL или пользовательские алгоритмы без промежуточного контейнера? Ответ может использовать инструмент от boost, но предполагается, что составленные алгоритмы выполнены пользователем или из STL.

Так что boost::adaptors::reversed не учитывается, поскольку алгоритм реверсирования находится в режиме повышения.

+0

Какое предположение об использовании пользовательских алгоритмов или STL исключает данный ответ? – polkadotcadaver

+0

@PaulDraper Не сказал, что когда я написал комментарий :) – polkadotcadaver

+0

«Мой вопрос частично мотивирован этим вопросом». - как это * частично мотивировано *, а не дубликат? –

ответ

7

No.

Скажем f и g алгоритмы STL.

Предположим, что вы хотите f(g(x)) (я пытаюсь передать идею здесь ...).

Невозможно обойти промежуточный контейнер, так как результат g(x) должен быть контейнером.

Если вы собираетесь избегать промежуточных контейнеров, то вы должны использовать алгоритмы, которые могут «проверять» или взаимодействовать с другими алгоритмами, такими как Boost.Range adaptors (например, boost::adaptors::reversed).

Например, f является «сортировкой» и g является «обратным». Адаптеры Boost могли понять, что обратный шаг - это не-op и пропустить его. Алгоритмы STL не могли этого сделать, поскольку нет никакой возможности для этой информации сделать это.

+0

Итак, нет адаптера адаптера, который может превратить 'std :: reversed' в своего рода« boost :: adapters :: reversed »? Я бы не захотел переписать оболочку для каждого независимого алгоритма, который у меня может быть. – Polymer

+0

@ Полимер, я не уверен в переписывании обертки; Я думаю, вы бы написали алгоритм с поддержкой 'boost :: adaptors'. Но ответ «да», вы не можете «скрывать» (?) 'Std :: reverseed' для' boost :: adapters :: reverseed' –

+0

Convert - лучшее слово, спасибо. – Polymer

1

Да для алгоритмов, совместимых с итераторами ввода и вывода.

Для хранения состояния выполнения требуется нить, или что-то подобное.

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

Многие <algorithms> не соответствуют вышеуказанным ограничениям. Но те, кто это делает, должны документировать свои требования. transform подходит, я не могу думать о других с головы.

+0

Это действительно интересный ответ. Позвольте мне посмотреть, понимаю ли я. У вас есть итератор отложенного исполнения, мы будем называть 'defIter'. Его конструктор принимает алгоритм (с интерфейсом, принимающим входные итераторы). Мы пишем алгоритм, принимающий '[inA, inB)' и выводящий на '[outA, outB)' где 'inA, inB' - итераторы ввода, а' outA, outB' - выходные итераторы. «Скомпилированный» код будет выглядеть примерно так: first_algorithm (inA, inB, defIter {second_algorithm, outA, outB}) '. 'second_algorithm' будет читать из входных итераторов, которые вернут выполнение обратно в' first_algorithm'. – Polymer

+0

@Полимер, это звучит в основном правильно. Если у вас было какое-то расширение сопрограммы C++, вы могли бы даже сделать это в одном потоке, так как отсутствие буферизации означает, что мы однопоточно: потоки просто существуют, чтобы мы * остановили * обработку 'second_algorithm' в месте где он действительно не собирается останавливаться (при чтении с его ввода). Обратите внимание, что 'defIter' будет выводиться на один итератор вывода, а не 2. – Yakk

+0

Ваше право, оно будет выводиться только на один итератор! Прежде чем попытаться реализовать этот итератор, есть ли что-нибудь в boost или какой-то другой библиотеке, которая обеспечивает что-то вроде этого? – Polymer

Смежные вопросы