<html>
    <head>
      <base href="https://bugs.llvm.org/">
    </head>
    <body><table border="1" cellspacing="0" cellpadding="8">
        <tr>
          <th>Bug ID</th>
          <td><a class="bz_bug_link 
          bz_status_NEW "
   title="NEW - Non-const ref treated as const-ref in the compiler."
   href="https://bugs.llvm.org/show_bug.cgi?id=43842">43842</a>
          </td>
        </tr>

        <tr>
          <th>Summary</th>
          <td>Non-const ref treated as const-ref in the compiler.
          </td>
        </tr>

        <tr>
          <th>Product</th>
          <td>clang
          </td>
        </tr>

        <tr>
          <th>Version</th>
          <td>7.0
          </td>
        </tr>

        <tr>
          <th>Hardware</th>
          <td>PC
          </td>
        </tr>

        <tr>
          <th>OS</th>
          <td>Linux
          </td>
        </tr>

        <tr>
          <th>Status</th>
          <td>NEW
          </td>
        </tr>

        <tr>
          <th>Severity</th>
          <td>normal
          </td>
        </tr>

        <tr>
          <th>Priority</th>
          <td>P
          </td>
        </tr>

        <tr>
          <th>Component</th>
          <td>C++17
          </td>
        </tr>

        <tr>
          <th>Assignee</th>
          <td>unassignedclangbugs@nondot.org
          </td>
        </tr>

        <tr>
          <th>Reporter</th>
          <td>jostaberry.jam@gmail.com
          </td>
        </tr>

        <tr>
          <th>CC</th>
          <td>blitzrakete@gmail.com, erik.pilkington@gmail.com, llvm-bugs@lists.llvm.org, richard-llvm@metafoo.co.uk
          </td>
        </tr></table>
      <p>
        <div>
        <pre>Clang 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
============================================

<a href="https://godbolt.org/z/qR70hS">https://godbolt.org/z/qR70hS</a></pre>
        </div>
      </p>


      <hr>
      <span>You are receiving this mail because:</span>

      <ul>
          <li>You are on the CC list for the bug.</li>
      </ul>
    </body>
</html>