Closed
Description
The following test program compiles with libc++17 and libstdc++, but fails with libc++18:
#include <concepts>
#include <functional>
#include <ranges>
#include <source_location>
#define FWD(x) static_cast<decltype(x)&&>(x)
struct add_fn {
template <std::integral T>
constexpr auto operator()(T lhs, T rhs,
std::source_location loc = std::source_location::current())
const -> T
{
return lhs + rhs;
}
};
inline constexpr auto add = add_fn{};
struct fold_op {
template <typename Rng, typename Func, typename Init>
constexpr auto operator()(Rng&& rng, Func func, Init init) const
{
auto init_ = std::ranges::range_value_t<Rng>(std::move(init));
for (auto&& elem : rng) {
init_ = std::invoke(func, std::move(init_), FWD(elem));
}
return init_;
}
};
inline constexpr auto fold = fold_op{};
auto sum(std::span<int const> arr) -> int
{
return fold(arr, add, 0);
}
https://godbolt.org/z/h47dnM3eP
The error is:
<source>:27:21: error: no matching function for call to 'invoke'
27 | init_ = std::invoke(func, std::move(init_), FWD(elem));
| ^~~~~~~~~~~
<source>:38:16: note: in instantiation of function template specialization 'fold_op::operator()<std::span<const int> &, add_fn, int>' requested here
38 | return fold(arr, add, 0);
| ^
/opt/compiler-explorer/clang-18.1.0/bin/../include/c++/v1/__functional/invoke.h:27:1: note: candidate template ignored: substitution failure [with _Fn = add_fn &, _Args = <__libcpp_remove_reference_t<int &>, const int &>]
27 | invoke(_Fn&& __f, _Args&&... __args) noexcept(is_nothrow_invocable_v<_Fn, _Args...>) {
| ^
1 error generated.
Compiler returned: 1
Removing the source_location
default argument from add_fn::operator()
allows the code to compile as expected.