Насколько я понимаю, операции просмотра библиотеки range-v3 (в настоящее время требуется С++ 17, но чтобы стать официальной частью STL в С++ 20) предоставляют цепные алгоритмы, подобные STL, которые оцениваются лениво. В качестве эксперимента я создал следующий код для оценки первых 4 совершенных чисел:
#include <iostream>
#include <range/v3/all.hpp>
using namespace std;
int main(int argc, char *argv[]) {
auto perfects = ranges::view::ints(1)
| ranges::view::filter([] (int x) {
int psum = 0;
for (int y = 1; y < x; ++y) {
if (x % y == 0) psum += y;
}
return x == psum;})
| ranges::view::take(3);
std::cout << "PERFECT NUMBERS:" << std::endl;
for (int z : perfects) {
std::cout << z << std::endl;
}
std::cout << "DONE." << std::endl;
}
Код начинается с возможного бесконечного диапазона чисел (ranges::view::ints(1)
), но поскольку алгоритм просмотра заканчивается на ranges::view::take(3)
, он должен остановиться после нахождения первых трех чисел, прошедших алгоритм фильтра (алгоритм грубой силы для фильтрации идеальных чисел, намеренно не эффективный). Поскольку первые три совершенных числа --- 6, 28 и 496 --- довольно малы, я ожидаю, что этот код быстро их найдет, выведите «DONE». и прекратить. И это именно то, что происходит:
coliru — 3 совершенных числа работает отлично
Однако, скажем, я хочу напечатать первые 4 совершенных числа, которые все еще довольно малы — 6, 28, 496 и 8128. После вывода 8128 программа не останавливается и в конце концов должна быть завершена; по-видимому, он тщетно пытается вычислить пятое совершенное число, 33550336, которое этот алгоритм грубой силы не может эффективно найти.
coliru – если 4 идеальных числа пытаются получить 5+
Мне это кажется нелогичным. Я бы понял, если бы оба теста провалились (приходя к выводу, что я неправильно понял ленивую оценку алгоритмов представления range-v3), но тот факт, что take(3) завершается успешно и останавливается, в то время как take(4) не кажется мне ошибкой , если я не понимаю вещи.
Я пробовал это с несколькими компиляторами на wandbox, и это кажется постоянным (пробовал clang 6.0.1 и 7.0.0, g++ 8.1.0 и 8.2.0). По крайней мере, на моем локальном компьютере, где я изначально обнаружил проблему, используется версия 0.3.6 range-v3, но я не уверен насчет coliru и wandbox.