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).