https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119284
Bug ID: 119284 Summary: Overload resolution selects wrong overload with `std::invocable` concept and `auto &` in lambda parameter Product: gcc Version: 14.2.1 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: liss.heidr...@uni-paderborn.de Target Milestone: --- In the following code the wrong overload is selected if both the `std::invocable` (1) are required and the parameter of the lambda is `auto &` (2). Specifically, the compiler selects the `const` overload, which causes a compiler error. This happens in GCC-{12,13,14}. ```c++ #include <concepts> struct S { void member_func() { } }; template<typename F> requires (std::invocable<F, S const &>) // (1) removing this requires clause makes this compile void func(S const &x, F f) { f(x); } template<typename F> requires (std::invocable<F, S &>) void func(S &x, F f) { f(x); } int main() { S s; func(s, [](auto &x) { // (2) changing `auto &` to `S &` makes this compile x.member_func(); }); } ``` ## Error Message (from gcc-14) ``` <source>: In instantiation of 'main()::<lambda(auto:1&)> [with auto:1 = const S]': /opt/compiler-explorer/gcc-14.2.0/include/c++/14.2.0/type_traits:2640:26: required by substitution of 'template<class _Fn, class ... _Args> static std::__result_of_success<decltype (declval<_Fn>()((declval<_Args>)()...)), std::__invoke_other> std::__result_of_other_impl::_S_test(int) [with _Fn = main()::<lambda(auto:1&)>; _Args = {const S&}]' 2640 | std::declval<_Fn>()(std::declval<_Args>()...) | ~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~ /opt/compiler-explorer/gcc-14.2.0/include/c++/14.2.0/type_traits:2651:60: required from 'struct std::__result_of_impl<false, false, main()::<lambda(auto:1&)>, const S&>' 2651 | using type = decltype(_S_test<_Functor, _ArgTypes...>(0)); | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~ /opt/compiler-explorer/gcc-14.2.0/include/c++/14.2.0/type_traits:3159:12: recursively required by substitution of 'template<class _Result, class _Ret> struct std::__is_invocable_impl<_Result, _Ret, true, std::__void_t<typename _CTp::type> > [with _Result = std::__invoke_result<main()::<lambda(auto:1&)>, const S&>; _Ret = void]' 3159 | struct is_invocable | ^~~~~~~~~~~~ /opt/compiler-explorer/gcc-14.2.0/include/c++/14.2.0/type_traits:3159:12: required from 'struct std::is_invocable<main()::<lambda(auto:1&)>, const S&>' /opt/compiler-explorer/gcc-14.2.0/include/c++/14.2.0/type_traits:3523:71: required from 'constexpr const bool std::is_invocable_v<main()::<lambda(auto:1&)>, const S&>' 3523 | inline constexpr bool is_invocable_v = is_invocable<_Fn, _Args...>::value; | ^~~~~ /opt/compiler-explorer/gcc-14.2.0/include/c++/14.2.0/concepts:360:25: required by substitution of 'template<class F> requires invocable<F, const S&> void func(const S&, F) [with F = main()::<lambda(auto:1&)>]' 360 | concept invocable = is_invocable_v<_Fn, _Args...>; | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~ <source>:21:9: required from here 21 | func(s, [](auto &x) { | ~~~~^~~~~~~~~~~~~~~~~ 22 | x.member_func(); | ~~~~~~~~~~~~~~~~ 23 | }); | ~~ <source>:22:22: error: passing 'const S' as 'this' argument discards qualifiers [-fpermissive] 22 | x.member_func(); | ~~~~~~~~~~~~~^~ <source>:4:10: note: in call to 'void S::member_func()' 4 | void member_func() { | ^~~~~~~~~~~ Compiler returned: 1 ``` ## Expected Behaviour Since func is called with non-const `S`, the non-const overload should be selected. In the lambda `auto &` should deduce to `S &` and the requires-clause should be satisfied.