https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85118

            Bug ID: 85118
           Summary: Error when using std::bind with a generic lambda -
                    "cannot bind 'const volatile char&' to an rvalue of
                    type 'const volatile char'"
           Product: gcc
           Version: 7.3.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: officesamurai at gmail dot com
  Target Milestone: ---

Created attachment 43794
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=43794&action=edit
Preprocessed test code

Seemingly innocent code gives a strange error "cannot bind 'const volatile
char&' to an rvalue of type 'const volatile char'".

The code:
===
#include <functional>

template <typename T>
bool isOneOf(const T& /*t*/)
{
    return false;
}

template <typename T, typename FirstType, typename... Tail>
bool isOneOf(const T& t, const FirstType& firstValue, const Tail&... tail)
{
    return t == firstValue || isOneOf(t, tail...);
}

int main()
{
    const auto isOneOfHelper = [](auto&&... params)
    {
        return isOneOf(std::forward<decltype(params)>(params)...);
    };

    auto isO = std::bind(isOneOfHelper, std::placeholders::_1, 'o');

    isO('o');
}
===

GCC version:
===
$ g++-7.3.0 -v
Using built-in specs.
COLLECT_GCC=g++-7.3.0
COLLECT_LTO_WRAPPER=/home/brd/soft/gcc-7.3.0/libexec/gcc/x86_64-pc-linux-gnu/7.3.0/lto-wrapper
Target: x86_64-pc-linux-gnu
Configured with: ./configure --prefix=/home/brd/soft/gcc-7.3.0
Thread model: posix
gcc version 7.3.0 (GCC)
===

The error:
===
$ g++-7.3.0 ~/tmp/test.cpp -std=c++14 -o test -save-temps
/home/brd/tmp/test.cpp: In instantiation of ‘main()::<lambda(auto:1&& ...)>
[with auto:1 = {char, const volatile char}]’:
/home/brd/tmp/test.cpp:17:51:   required by substitution of ‘template<class ...
auto:1> main()::<lambda(auto:1&& ...)>::operator decltype (((const
main()::<lambda(auto:1&& ...)>*)((const main()::<lambda(auto:1&& ...)>*
const)0))->operator()(static_cast<auto:1&>(main::__lambda0::_FUN::<unnamed>)
...)) (*)(auto:1&& ...)() const [with auto:1 = {char, const volatile char}]’
/home/brd/soft/gcc-7.3.0/include/c++/7.3.0/type_traits:2428: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 =
const volatile main()::<lambda(auto:1&& ...)>&; _Args = {char&&, const volatile
char&}]’
/home/brd/soft/gcc-7.3.0/include/c++/7.3.0/type_traits:2439:55:   required from
‘struct std::__result_of_impl<false, false, const volatile
main()::<lambda(auto:1&& ...)>&, char&&, const volatile char&>’
/home/brd/soft/gcc-7.3.0/include/c++/7.3.0/type_traits:2444:12:   required from
‘struct std::__invoke_result<const volatile main()::<lambda(auto:1&& ...)>&,
char&&, const volatile char&>’
/home/brd/soft/gcc-7.3.0/include/c++/7.3.0/type_traits:2457:12:   required from
‘class std::result_of<const volatile main()::<lambda(auto:1&& ...)>&(char&&,
const volatile char&)>’
/home/brd/soft/gcc-7.3.0/include/c++/7.3.0/functional:511:72:   required by
substitution of ‘template<class _Functor, class ... _Bound_args> template<class
_Fn, class _CallArgs, class ... _BArgs> using _Res_type_impl = typename
std::result_of<_Fn&(std::_Bind<_Functor(_Bound_args ...)>::_Mu_type<_BArgs,
_CallArgs>&& ...)>::type [with _Fn = std::add_cv<main()::<lambda(auto:1&& ...)>
>::type; _CallArgs = std::tuple<char>; _BArgs =
{std::add_cv<std::_Placeholder<1> >::type, std::add_cv<char>::type}; _Functor =
main()::<lambda(auto:1&& ...)>; _Bound_args = {std::_Placeholder<1>, char}]’
/home/brd/soft/gcc-7.3.0/include/c++/7.3.0/functional:524:46:   required by
substitution of ‘template<class _Functor, class ... _Bound_args> template<class
_CallArgs, template<class _CallArgs, template<class> class __cv_quals>
template<class _Functor, class ... _Bound_args> template<class> class
__cv_quals> using _Res_type_cv = std::_Bind<_Functor(_Bound_args
...)>::_Res_type_impl<typename __cv_quals<typename
std::enable_if<(bool)((std::tuple_size<_Tuple>::value + 1)),
_Functor>::type>::type, _CallArgs, typename __cv_quals<_Bound_args>::type ...>
[with _CallArgs = std::tuple<char>; __cv_quals = std::add_cv; _Functor =
main()::<lambda(auto:1&& ...)>; _Bound_args = {std::_Placeholder<1>, char}]’
/home/brd/soft/gcc-7.3.0/include/c++/7.3.0/functional:585:9:   required by
substitution of ‘template<class ... _Args, class _Result> _Result
std::_Bind<main()::<lambda(auto:1&& ...)>(std::_Placeholder<1>,
char)>::operator()<_Args ..., _Result>(_Args&& ...) const volatile [with _Args
= {char}; _Result = <missing>]’
/home/brd/tmp/test.cpp:24:12:   required from here
/home/brd/tmp/test.cpp:19:23: error: no matching function for call to
‘isOneOf(char, const volatile char)’
         return isOneOf(std::forward<decltype(params)>(params)...);
                ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/home/brd/tmp/test.cpp:4:6: note: candidate: template<class T> bool
isOneOf(const T&)
 bool isOneOf(const T& /*t*/)
      ^~~~~~~
/home/brd/tmp/test.cpp:4:6: note:   template argument deduction/substitution
failed:
/home/brd/tmp/test.cpp:19:23: note:   candidate expects 1 argument, 2 provided
         return isOneOf(std::forward<decltype(params)>(params)...);
                ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/home/brd/tmp/test.cpp:10:6: note: candidate: bool isOneOf(const T&, const
FirstType&, const Tail& ...) [with T = char; FirstType = volatile char; Tail =
{}] <near match>
 bool isOneOf(const T& t, const FirstType& firstValue, const Tail&... tail)
      ^~~~~~~
/home/brd/tmp/test.cpp:10:6: note:   conversion of argument 2 would be
ill-formed:
/home/brd/tmp/test.cpp:19:23: error: cannot bind non-const lvalue reference of
type ‘const volatile char&’ to an rvalue of type ‘const volatile char’
         return isOneOf(std::forward<decltype(params)>(params)...);
                ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/home/brd/tmp/test.cpp: In instantiation of ‘main()::<lambda(auto:1&& ...)>
[with auto:1 = {char, volatile char}]’:
/home/brd/tmp/test.cpp:17:51:   required by substitution of ‘template<class ...
auto:1> main()::<lambda(auto:1&& ...)>::operator decltype (((const
main()::<lambda(auto:1&& ...)>*)((const main()::<lambda(auto:1&& ...)>*
const)0))->operator()(static_cast<auto:1&>(main::__lambda0::_FUN::<unnamed>)
...)) (*)(auto:1&& ...)() const [with auto:1 = {char, volatile char}]’
/home/brd/soft/gcc-7.3.0/include/c++/7.3.0/type_traits:2428: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 =
volatile main()::<lambda(auto:1&& ...)>&; _Args = {char&&, volatile char&}]’
/home/brd/soft/gcc-7.3.0/include/c++/7.3.0/type_traits:2439:55:   required from
‘struct std::__result_of_impl<false, false, volatile main()::<lambda(auto:1&&
...)>&, char&&, volatile char&>’
/home/brd/soft/gcc-7.3.0/include/c++/7.3.0/type_traits:2444:12:   required from
‘struct std::__invoke_result<volatile main()::<lambda(auto:1&& ...)>&, char&&,
volatile char&>’
/home/brd/soft/gcc-7.3.0/include/c++/7.3.0/type_traits:2457:12:   required from
‘class std::result_of<volatile main()::<lambda(auto:1&& ...)>&(char&&, volatile
char&)>’
/home/brd/soft/gcc-7.3.0/include/c++/7.3.0/functional:511:72:   required by
substitution of ‘template<class _Functor, class ... _Bound_args> template<class
_Fn, class _CallArgs, class ... _BArgs> using _Res_type_impl = typename
std::result_of<_Fn&(std::_Bind<_Functor(_Bound_args ...)>::_Mu_type<_BArgs,
_CallArgs>&& ...)>::type [with _Fn = std::add_volatile<main()::<lambda(auto:1&&
...)> >::type; _CallArgs = std::tuple<char>; _BArgs =
{std::add_volatile<std::_Placeholder<1> >::type,
std::add_volatile<char>::type}; _Functor = main()::<lambda(auto:1&& ...)>;
_Bound_args = {std::_Placeholder<1>, char}]’
/home/brd/soft/gcc-7.3.0/include/c++/7.3.0/functional:524:46:   required by
substitution of ‘template<class _Functor, class ... _Bound_args> template<class
_CallArgs, template<class _CallArgs, template<class> class __cv_quals>
template<class _Functor, class ... _Bound_args> template<class> class
__cv_quals> using _Res_type_cv = std::_Bind<_Functor(_Bound_args
...)>::_Res_type_impl<typename __cv_quals<typename
std::enable_if<(bool)((std::tuple_size<_Tuple>::value + 1)),
_Functor>::type>::type, _CallArgs, typename __cv_quals<_Bound_args>::type ...>
[with _CallArgs = std::tuple<char>; __cv_quals = std::add_volatile; _Functor =
main()::<lambda(auto:1&& ...)>; _Bound_args = {std::_Placeholder<1>, char}]’
/home/brd/soft/gcc-7.3.0/include/c++/7.3.0/functional:573:9:   required by
substitution of ‘template<class ... _Args, class _Result> _Result
std::_Bind<main()::<lambda(auto:1&& ...)>(std::_Placeholder<1>,
char)>::operator()<_Args ..., _Result>(_Args&& ...) volatile [with _Args =
{char}; _Result = <missing>]’
/home/brd/tmp/test.cpp:24:12:   required from here
/home/brd/tmp/test.cpp:19:23: error: no matching function for call to
‘isOneOf(char, volatile char)’
/home/brd/tmp/test.cpp:4:6: note: candidate: template<class T> bool
isOneOf(const T&)
 bool isOneOf(const T& /*t*/)
      ^~~~~~~
/home/brd/tmp/test.cpp:4:6: note:   template argument deduction/substitution
failed:
/home/brd/tmp/test.cpp:19:23: note:   candidate expects 1 argument, 2 provided
         return isOneOf(std::forward<decltype(params)>(params)...);
                ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/home/brd/tmp/test.cpp:10:6: note: candidate: bool isOneOf(const T&, const
FirstType&, const Tail& ...) [with T = char; FirstType = volatile char; Tail =
{}] <near match>
 bool isOneOf(const T& t, const FirstType& firstValue, const Tail&... tail)
      ^~~~~~~
/home/brd/tmp/test.cpp:10:6: note:   conversion of argument 2 would be
ill-formed:
/home/brd/tmp/test.cpp:19:23: error: cannot bind non-const lvalue reference of
type ‘const volatile char&’ to an rvalue of type ‘volatile char’
         return isOneOf(std::forward<decltype(params)>(params)...);
                ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
===

P.S. I also tried GCC 6.3.0 (got similar error) and 5.2.0 (no errors).

Reply via email to