https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92270
Bug ID: 92270 Summary: Non-const ref treated as const-ref in the compiler. Product: gcc Version: 7.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: jostaberry.jam at gmail dot com Target Milestone: --- GCC rejects this valid code, but it can be compiled without "i = 0;". And as expected, Overload #1 is selected. =================== CODE =================== #include <iostream> #include <type_traits> template <class T> struct test { T value; template <class F> std::enable_if_t<std::is_invocable_v<F&&, T&>> fn(F&& op) & { op(value); } // #1 template <class F> std::enable_if_t<std::is_invocable_v<F&&, T const&>> fn(F&& op) const& { op(value); } // #2 }; template <class T> test(T) -> test<T>; int main() { test instance{1}; instance.fn([](auto& i){ // error: cannot assign to variable 'i' // with const-qualified type 'const int &' i = 0; }); } ================= END CODE ================= ============================================ source>:24:11: error: cannot assign to variable 'i' with const-qualified type 'const int &' i = 0; ~ ^ /opt/compiler-explorer/gcc-8.2.0/lib/gcc/x86_64-linux-gnu/8.2.0/../../../../include/c++/8.2.0/type_traits:2283:7: note: in instantiation of function template specialization 'main()::(anonymous class)::operator()<const int>' requested here std::declval<_Fn>()(std::declval<_Args>()...) ^ /opt/compiler-explorer/gcc-8.2.0/lib/gcc/x86_64-linux-gnu/8.2.0/../../../../include/c++/8.2.0/type_traits:2294:24: note: while substituting deduced template arguments into function template '_S_test' [with _Fn = (lambda at <source>:21:17) &&, _Args = (no value)] typedef decltype(_S_test<_Functor, _ArgTypes...>(0)) type; ^ /opt/compiler-explorer/gcc-8.2.0/lib/gcc/x86_64-linux-gnu/8.2.0/../../../../include/c++/8.2.0/type_traits:2300:14: note: in instantiation of template class 'std::__result_of_impl<false, false, (lambda at <source>:21:17) &&, const int &>' requested here : public __result_of_impl< ^ /opt/compiler-explorer/gcc-8.2.0/lib/gcc/x86_64-linux-gnu/8.2.0/../../../../include/c++/8.2.0/type_traits:2612:65: note: in instantiation of template class 'std::__invoke_result<(lambda at <source>:21:17) &&, const int &>' requested here struct __is_invocable_impl<_Result, _Ret, __void_t<typename _Result::type>> ^ /opt/compiler-explorer/gcc-8.2.0/lib/gcc/x86_64-linux-gnu/8.2.0/../../../../include/c++/8.2.0/type_traits:2696:7: note: during template argument deduction for class template partial specialization '__is_invocable_impl<_Result, _Ret, __void_t<typename _Result::type> >' [with _Result = std::__invoke_result<(lambda at <source>:21:17) &&, const int &>, _Ret = void] : __is_invocable_impl<__invoke_result<_Fn, _ArgTypes...>, void>::type ^ /opt/compiler-explorer/gcc-8.2.0/lib/gcc/x86_64-linux-gnu/8.2.0/../../../../include/c++/8.2.0/type_traits:2696:7: note: in instantiation of template class 'std::__is_invocable_impl<std::__invoke_result<(lambda at <source>:21:17) &&, const int &>, void, void>' requested here /opt/compiler-explorer/gcc-8.2.0/lib/gcc/x86_64-linux-gnu/8.2.0/../../../../include/c++/8.2.0/type_traits:2732:44: note: in instantiation of template class 'std::is_invocable<(lambda at <source>:21:17) &&, const int &>' requested here inline constexpr bool is_invocable_v = is_invocable<_Fn, _Args...>::value; ^ <source>:13:27: note: in instantiation of variable template specialization 'std::is_invocable_v<(lambda at <source>:21:17) &&, const int &>' requested here std::enable_if_t<std::is_invocable_v<F&&, T const&>> ^ <source>:21:14: note: while substituting deduced template arguments into function template 'fn' [with F = (lambda at <source>:21:17)] instance.fn([](auto& i){ ^ <source>:21:26: note: variable 'i' declared const here instance.fn([](auto& i){ ~~~~~~^ 1 error generated. ASM generation compiler returned: 1 <source>:24:11: error: cannot assign to variable 'i' with const-qualified type 'const int &' i = 0; ~ ^ /opt/compiler-explorer/gcc-8.2.0/lib/gcc/x86_64-linux-gnu/8.2.0/../../../../include/c++/8.2.0/type_traits:2283:7: note: in instantiation of function template specialization 'main()::(anonymous class)::operator()<const int>' requested here std::declval<_Fn>()(std::declval<_Args>()...) ^ /opt/compiler-explorer/gcc-8.2.0/lib/gcc/x86_64-linux-gnu/8.2.0/../../../../include/c++/8.2.0/type_traits:2294:24: note: while substituting deduced template arguments into function template '_S_test' [with _Fn = (lambda at <source>:21:17) &&, _Args = (no value)] typedef decltype(_S_test<_Functor, _ArgTypes...>(0)) type; ^ /opt/compiler-explorer/gcc-8.2.0/lib/gcc/x86_64-linux-gnu/8.2.0/../../../../include/c++/8.2.0/type_traits:2300:14: note: in instantiation of template class 'std::__result_of_impl<false, false, (lambda at <source>:21:17) &&, const int &>' requested here : public __result_of_impl< ^ /opt/compiler-explorer/gcc-8.2.0/lib/gcc/x86_64-linux-gnu/8.2.0/../../../../include/c++/8.2.0/type_traits:2612:65: note: in instantiation of template class 'std::__invoke_result<(lambda at <source>:21:17) &&, const int &>' requested here struct __is_invocable_impl<_Result, _Ret, __void_t<typename _Result::type>> ^ /opt/compiler-explorer/gcc-8.2.0/lib/gcc/x86_64-linux-gnu/8.2.0/../../../../include/c++/8.2.0/type_traits:2696:7: note: during template argument deduction for class template partial specialization '__is_invocable_impl<_Result, _Ret, __void_t<typename _Result::type> >' [with _Result = std::__invoke_result<(lambda at <source>:21:17) &&, const int &>, _Ret = void] : __is_invocable_impl<__invoke_result<_Fn, _ArgTypes...>, void>::type ^ /opt/compiler-explorer/gcc-8.2.0/lib/gcc/x86_64-linux-gnu/8.2.0/../../../../include/c++/8.2.0/type_traits:2696:7: note: in instantiation of template class 'std::__is_invocable_impl<std::__invoke_result<(lambda at <source>:21:17) &&, const int &>, void, void>' requested here /opt/compiler-explorer/gcc-8.2.0/lib/gcc/x86_64-linux-gnu/8.2.0/../../../../include/c++/8.2.0/type_traits:2732:44: note: in instantiation of template class 'std::is_invocable<(lambda at <source>:21:17) &&, const int &>' requested here inline constexpr bool is_invocable_v = is_invocable<_Fn, _Args...>::value; ^ <source>:13:27: note: in instantiation of variable template specialization 'std::is_invocable_v<(lambda at <source>:21:17) &&, const int &>' requested here std::enable_if_t<std::is_invocable_v<F&&, T const&>> ^ <source>:21:14: note: while substituting deduced template arguments into function template 'fn' [with F = (lambda at <source>:21:17)] instance.fn([](auto& i){ ^ <source>:21:26: note: variable 'i' declared const here instance.fn([](auto& i){ ~~~~~~^ 1 error generated. Execution build compiler returned: 1 ============================================ https://godbolt.org/z/JvWq8i