ericniebler / range-v3

Range library for C++14/17/20, basis for C++20's std::ranges
Other
4.06k stars 437 forks source link

chunk_view terminates program with throwing begin() #1693

Open gordondow opened 2 years ago

gordondow commented 2 years ago

In spite of the try/catch clause, the following program terminates abnormally with an uncaught exception:

#include <exception>
#include <iostream>
#include <sstream>

#include <range/v3/algorithm/for_each.hpp>
#include <range/v3/view/chunk.hpp>

struct my_input_container
{
    std::istream_iterator<char> begin()
    {
        throw std::runtime_error("");
    }

    std::istream_iterator<char> end()
    {
        return {};
    }
};

int main(int argc, const char * argv[])
{
    try
    {
        my_input_container zzz;
        auto rng = zzz
            | ranges::views::chunk(2);
        ranges::for_each(rng, [](auto&& rng){});
    }
    catch(...)
    {
        std::cout << "exception occurred.";
    }
}

The crash (termination with uncaught exception) occurs because of this code in view/chunk.hpp:

constexpr outer_cursor begin_cursor() noexcept
{
    it_cache_ = ranges::begin(base_);
    return outer_cursor{this};
}

The call to ranges::begin() (in this case) throws an exception, but begin_cursor is marked noexcept, so the program terminates. I think this should be:

constexpr outer_cursor begin_cursor() noexcept(noexcept(ranges::begin(base_)))
{
    it_cache_ = ranges::begin(base_);
    return outer_cursor{this};
}