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

constexpr algorithms #1683

Closed dvirtz closed 2 years ago

dvirtz commented 2 years ago

I'm trying to continue the work @gnzlbg did in #143, rebasing his changes onto master and fixing compilation issues.

The main changes I had to do were replacing std::ref which is not constexpr in C++14 with ranges::ref and removing goto statements.

Unlike #143, I didn't try to add constexpr support to algorithms which are not constexpr in C++20 like stable_sort and shuffle.

dvirtz commented 2 years ago

To enhance compile time testing I've added STATIC_CHECK and STATIC_CHECK_RETURN macros to simple_test.hpp. A usage example:

constexpr bool test_constexpr()
{
    using IL = std::initializer_list<int>;

    test::array<int, 5> arr{{1, 2, 3, 4, 5}};
    const auto it = ranges::unstable_remove_if(arr, is_even);
    STATIC_CHECK_RETURN(it == arr.begin() + 3);
    STATIC_CHECK_RETURN(
        ranges::equal(ranges::make_subrange(arr.begin(), it), IL{1, 5, 3}));

    return true;
}

int main()
{
    STATIC_CHECK(test_constexpr());

    return test_result();
}

Upon failure the failed line and expression will be printed as part of the compiler output:


/workspaces/range-v3/test/algorithm/unstable_remove_if.cpp:39:5: error: constexpr variable '_' must be initialized by a constant expression
    STATIC_CHECK(test_constexpr());
    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
note: (skipping 1 expansions in backtrace; use -fmacro-backtrace-limit=0 to see all)
/workspaces/range-v3/test/algorithm/../simple_test.hpp:194:24: note: expanded from macro 'STATIC_CHECK_IMPL'
        constexpr auto _ = STATIC_CHECK_LINE(file, line, __VA_ARGS__); \
                       ^   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/workspaces/range-v3/test/algorithm/../simple_test.hpp:168:13: note: subexpression not valid in a constant expression
            throw std::logic_error{message};
            ^
/workspaces/range-v3/test/algorithm/unstable_remove_if.cpp:30:5: note: in call to 'static_check(false, &"> 
ERROR: CHECK failed \"it == arr.begin() + 2\"> /workspaces/range-v3/test/algorithm/unstable_remove_if.cpp(30)"[0])'
    STATIC_CHECK_RETURN(it == arr.begin() + 2);
    ^
note: (skipping 2 expansions in backtrace; use -fmacro-backtrace-limit=0 to see all)
/workspaces/range-v3/test/algorithm/../simple_test.hpp:188:5: note: expanded from macro 'STATIC_CHECK_LINE'
    ::test_impl::static_check(__VA_ARGS__,                     \
    ^
/workspaces/range-v3/test/algorithm/unstable_remove_if.cpp:39:18: note: in call to 'test_constexpr()'
    STATIC_CHECK(test_constexpr());
                 ^
ericniebler commented 2 years ago

Thanks for the huge effort, and for your patience.