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
struct S {
void member_func() {
}
};
template requires (std::invocable) // (1) removing
this requires clause makes this compile
void func(S const &x, F f) {
f(x);
}
template requires (std::invocable)
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)
```
: In instantiation of 'main():: [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 static
std::__result_of_success()((declval<_Args>)()...)),
std::__invoke_other> std::__result_of_other_impl::_S_test(int) [with _Fn =
main()::; _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, 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
struct std::__is_invocable_impl<_Result, _Ret, true, std::__void_t > [with _Result = std::__invoke_result,
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, 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, 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 requires invocable void func(const S&, F) [with F = main()::]'
360 | concept invocable = is_invocable_v<_Fn, _Args...>;
| ^
:21:9: required from here
21 | func(s, [](auto &x) {
| ^
22 | x.member_func();
|
23 | });
| ~~
:22:22: error: passing 'const S' as 'this' argument discards qualifiers
[-fpermissive]
22 | x.member_func();
| ~^~
: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.