[libc++] std::invoke() substitution failure when using function object with default argument (original) (raw)
The following test program compiles with libc++17 and libstdc++, but fails with libc++18:
#include #include #include #include
#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(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 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.