https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69831
Bug ID: 69831 Summary: Issue with passing a reference_wrapper to a placeholder when using a pointer to member function in bind Product: gcc Version: 5.3.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: sniderdj at umich dot edu Target Milestone: --- Created attachment 37696 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=37696&action=edit the preprocessed file When passing in a reference_wrapper to the result of a call to bind called on a pointer to member function, no overload is resolved, although when the reference wrapper is given to bind initially, everything works as expected. In this short case: #include <functional> #include <algorithm> #include <vector> using namespace std; using namespace std::placeholders; struct foo { foo(){} void func(int) {} }; int main() { vector<reference_wrapper<foo>> v; foo inst; reference_wrapper<foo> rw = inst; auto b1 = bind(&foo::func, rw, 0); // okay b1(); auto b2 = bind(&foo::func, _1, 0); // bad b2(rw); } The first call to bind works fine, as expected, but on the last line, where the second bind object is called with the reference_wrapper, the compiler rejects all possible overloads, even though it appears as at least one should match. command: gcc -v -save-temps -std=c++14 bug.cpp the result of the command: Using built-in specs. COLLECT_GCC=gcc COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/5/lto-wrapper Target: x86_64-linux-gnu Configured with: ../src/configure -v --with-pkgversion='Ubuntu 5.3.0-3ubuntu1~14.04' --with-bugurl=file:///usr/share/doc/gcc-5/README.Bugs --enable-languages=c,ada,c++,java,go,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-5 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=gcc4-compatible --disable-libstdcxx-dual-abi --enable-gnu-unique-object --disable-vtable-verify --enable-libmpx --enable-plugin --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-5-amd64/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-5-amd64 --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-5-amd64 --with-arch-directory=amd64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu Thread model: posix gcc version 5.3.0 20151204 (Ubuntu 5.3.0-3ubuntu1~14.04) COLLECT_GCC_OPTIONS='-v' '-save-temps' '-std=c++14' '-mtune=generic' '-march=x86-64' /usr/lib/gcc/x86_64-linux-gnu/5/cc1plus -E -quiet -v -imultiarch x86_64-linux-gnu -D_GNU_SOURCE bug.cpp -mtune=generic -march=x86-64 -std=c++14 -fpch-preprocess -fstack-protector -Wformat -Wformat-security -o bug.ii ignoring duplicate directory "/usr/include/x86_64-linux-gnu/c++/5" ignoring nonexistent directory "/usr/local/include/x86_64-linux-gnu" ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/5/../../../../x86_64-linux-gnu/include" #include "..." search starts here: #include <...> search starts here: /usr/include/c++/5 /usr/include/x86_64-linux-gnu/c++/5 /usr/include/c++/5/backward /usr/lib/gcc/x86_64-linux-gnu/5/include /usr/local/include /usr/lib/gcc/x86_64-linux-gnu/5/include-fixed /usr/include/x86_64-linux-gnu /usr/include End of search list. COLLECT_GCC_OPTIONS='-v' '-save-temps' '-std=c++14' '-mtune=generic' '-march=x86-64' /usr/lib/gcc/x86_64-linux-gnu/5/cc1plus -fpreprocessed bug.ii -quiet -dumpbase bug.cpp -mtune=generic -march=x86-64 -auxbase bug -std=c++14 -version -fstack-protector -Wformat -Wformat-security -o bug.s GNU C++14 (Ubuntu 5.3.0-3ubuntu1~14.04) version 5.3.0 20151204 (x86_64-linux-gnu) compiled by GNU C version 5.3.0 20151204, GMP version 5.1.3, MPFR version 3.1.3, MPC version 1.0.1 GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072 GNU C++14 (Ubuntu 5.3.0-3ubuntu1~14.04) version 5.3.0 20151204 (x86_64-linux-gnu) compiled by GNU C version 5.3.0 20151204, GMP version 5.1.3, MPFR version 3.1.3, MPC version 1.0.1 GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072 Compiler executable checksum: bbf79e63f589fea28823afe8bbe74c79 bug.cpp: In function ‘int main()’: bug.cpp:15:8: error: no match for call to ‘(std::_Bind<std::_Mem_fn<void (foo::*)(int)>(std::_Placeholder<1>, int)>) (std::reference_wrapper<foo>&)’ b2(rw); ^ In file included from bug.cpp:1:0: /usr/include/c++/5/functional:1129:2: note: candidate: template<class ... _Args, class _Result> _Result std::_Bind<_Functor(_Bound_args ...)>::operator()(_Args&& ...) [with _Args = {_Args ...}; _Result = _Result; _Functor = std::_Mem_fn<void (foo::*)(int)>; _Bound_args = {std::_Placeholder<1>, int}] operator()(_Args&&... __args) ^ /usr/include/c++/5/functional:1129:2: note: template argument deduction/substitution failed: /usr/include/c++/5/functional:1125:38: error: call of ‘(std::_Mem_fn<void (foo::*)(int)>) (std::reference_wrapper<foo>&, int&)’ is ambiguous = decltype( std::declval<_Functor>()( ^ In file included from bug.cpp:1:0: /usr/include/c++/5/functional:582:2: note: candidate: std::_Mem_fn_base<_MemFunPtr, __is_mem_fn>::result_type std::_Mem_fn_base<_MemFunPtr, __is_mem_fn>::operator()(std::_Mem_fn_base<_MemFunPtr, __is_mem_fn>::_Class&, _Args&& ...) const [with _Args = {int&}; _Req = void; _MemFunPtr = void (foo::*)(int); bool __is_mem_fn = true; std::_Mem_fn_base<_MemFunPtr, __is_mem_fn>::result_type = void; std::_Mem_fn_base<_MemFunPtr, __is_mem_fn>::_Class = foo] operator()(_Class& __object, _Args&&... __args) const ^ /usr/include/c++/5/functional:607:2: note: candidate: std::_Mem_fn_base<_MemFunPtr, __is_mem_fn>::result_type std::_Mem_fn_base<_MemFunPtr, __is_mem_fn>::operator()(_Tp&&, _Args&& ...) const [with _Tp = std::reference_wrapper<foo>&; _Args = {int&}; _Req = void; _MemFunPtr = void (foo::*)(int); bool __is_mem_fn = true; std::_Mem_fn_base<_MemFunPtr, __is_mem_fn>::result_type = void] operator()(_Tp&& __object, _Args&&... __args) const ^ /usr/include/c++/5/functional:618:2: note: candidate: std::_Mem_fn_base<_MemFunPtr, __is_mem_fn>::result_type std::_Mem_fn_base<_MemFunPtr, __is_mem_fn>::operator()(std::reference_wrapper<_Tp>, _Args&& ...) const [with _Tp = foo; _Args = {int&}; _Req = void; _MemFunPtr = void (foo::*)(int); bool __is_mem_fn = true; std::_Mem_fn_base<_MemFunPtr, __is_mem_fn>::result_type = void] operator()(reference_wrapper<_Tp> __ref, _Args&&... __args) const ^ In file included from bug.cpp:1:0: /usr/include/c++/5/functional:1143:2: note: candidate: template<class ... _Args, class _Result> _Result std::_Bind<_Functor(_Bound_args ...)>::operator()(_Args&& ...) const [with _Args = {_Args ...}; _Result = _Result; _Functor = std::_Mem_fn<void (foo::*)(int)>; _Bound_args = {std::_Placeholder<1>, int}] operator()(_Args&&... __args) const ^ /usr/include/c++/5/functional:1143:2: note: template argument deduction/substitution failed: /usr/include/c++/5/functional:1139:52: error: call of ‘(const std::_Mem_fn<void (foo::*)(int)>) (std::reference_wrapper<foo>&, const int&)’ is ambiguous typename add_const<_Functor>::type>::type>()( ^ In file included from bug.cpp:1:0: /usr/include/c++/5/functional:582:2: note: candidate: std::_Mem_fn_base<_MemFunPtr, __is_mem_fn>::result_type std::_Mem_fn_base<_MemFunPtr, __is_mem_fn>::operator()(std::_Mem_fn_base<_MemFunPtr, __is_mem_fn>::_Class&, _Args&& ...) const [with _Args = {const int&}; _Req = void; _MemFunPtr = void (foo::*)(int); bool __is_mem_fn = true; std::_Mem_fn_base<_MemFunPtr, __is_mem_fn>::result_type = void; std::_Mem_fn_base<_MemFunPtr, __is_mem_fn>::_Class = foo] operator()(_Class& __object, _Args&&... __args) const ^ /usr/include/c++/5/functional:607:2: note: candidate: std::_Mem_fn_base<_MemFunPtr, __is_mem_fn>::result_type std::_Mem_fn_base<_MemFunPtr, __is_mem_fn>::operator()(_Tp&&, _Args&& ...) const [with _Tp = std::reference_wrapper<foo>&; _Args = {const int&}; _Req = void; _MemFunPtr = void (foo::*)(int); bool __is_mem_fn = true; std::_Mem_fn_base<_MemFunPtr, __is_mem_fn>::result_type = void] operator()(_Tp&& __object, _Args&&... __args) const ^ /usr/include/c++/5/functional:618:2: note: candidate: std::_Mem_fn_base<_MemFunPtr, __is_mem_fn>::result_type std::_Mem_fn_base<_MemFunPtr, __is_mem_fn>::operator()(std::reference_wrapper<_Tp>, _Args&& ...) const [with _Tp = foo; _Args = {const int&}; _Req = void; _MemFunPtr = void (foo::*)(int); bool __is_mem_fn = true; std::_Mem_fn_base<_MemFunPtr, __is_mem_fn>::result_type = void] operator()(reference_wrapper<_Tp> __ref, _Args&&... __args) const ^ In file included from bug.cpp:1:0: /usr/include/c++/5/functional:1157:2: note: candidate: template<class ... _Args, class _Result> _Result std::_Bind<_Functor(_Bound_args ...)>::operator()(_Args&& ...) volatile [with _Args = {_Args ...}; _Result = _Result; _Functor = std::_Mem_fn<void (foo::*)(int)>; _Bound_args = {std::_Placeholder<1>, int}] operator()(_Args&&... __args) volatile ^ /usr/include/c++/5/functional:1157:2: note: template argument deduction/substitution failed: /usr/include/c++/5/functional:1153:69: error: no match for call to ‘(volatile std::_Mem_fn<void (foo::*)(int)>) (std::reference_wrapper<foo>&, volatile int&)’ typename add_volatile<_Functor>::type>::type>()( ^ In file included from bug.cpp:1:0: /usr/include/c++/5/functional:582:2: note: candidate: std::_Mem_fn_base<_MemFunPtr, __is_mem_fn>::result_type std::_Mem_fn_base<_MemFunPtr, __is_mem_fn>::operator()(std::_Mem_fn_base<_MemFunPtr, __is_mem_fn>::_Class&, _Args&& ...) const [with _Args = {volatile int&}; _Req = void; _MemFunPtr = void (foo::*)(int); bool __is_mem_fn = true; std::_Mem_fn_base<_MemFunPtr, __is_mem_fn>::result_type = void; std::_Mem_fn_base<_MemFunPtr, __is_mem_fn>::_Class = foo] <near match> operator()(_Class& __object, _Args&&... __args) const ^ /usr/include/c++/5/functional:582:2: note: passing ‘volatile std::_Mem_fn<void (foo::*)(int)>*’ as ‘this’ argument discards qualifiers /usr/include/c++/5/functional:589:2: note: candidate: template<class ... _Args, class _Req> std::_Mem_fn_base<_MemFunPtr, __is_mem_fn>::result_type std::_Mem_fn_base<_MemFunPtr, __is_mem_fn>::operator()(std::_Mem_fn_base<_MemFunPtr, __is_mem_fn>::_Class&&, _Args&& ...) const [with _Args = {_Args ...}; _Req = _Req; _MemFunPtr = void (foo::*)(int); bool __is_mem_fn = true] operator()(_Class&& __object, _Args&&... __args) const ^ /usr/include/c++/5/functional:589:2: note: template argument deduction/substitution failed: In file included from bug.cpp:1:0: /usr/include/c++/5/functional:1153:69: note: cannot convert ‘std::_Mu<std::_Placeholder<1>, false, true>().std::_Mu<_Arg, false, true>::operator()<std::tuple<std::reference_wrapper<foo>&> >((*(const volatile std::_Placeholder<1>*)std::declval<volatile std::_Placeholder<1>&>()), (* & std::declval<std::tuple<std::reference_wrapper<foo>&>&>()))’ (type ‘std::reference_wrapper<foo>’) to type ‘std::_Mem_fn_base<void (foo::*)(int), true>::_Class&& {aka foo&&}’ typename add_volatile<_Functor>::type>::type>()( ^ In file included from bug.cpp:1:0: /usr/include/c++/5/functional:599:2: note: candidate: template<class ... _Args, class _Req> std::_Mem_fn_base<_MemFunPtr, __is_mem_fn>::result_type std::_Mem_fn_base<_MemFunPtr, __is_mem_fn>::operator()(std::_Mem_fn_base<_MemFunPtr, __is_mem_fn>::_Class*, _Args&& ...) const [with _Args = {_Args ...}; _Req = _Req; _MemFunPtr = void (foo::*)(int); bool __is_mem_fn = true] operator()(_Class* __object, _Args&&... __args) const ^ /usr/include/c++/5/functional:599:2: note: template argument deduction/substitution failed: In file included from bug.cpp:1:0: /usr/include/c++/5/functional:1153:69: note: cannot convert ‘std::_Mu<std::_Placeholder<1>, false, true>().std::_Mu<_Arg, false, true>::operator()<std::tuple<std::reference_wrapper<foo>&> >((*(const volatile std::_Placeholder<1>*)std::declval<volatile std::_Placeholder<1>&>()), (* & std::declval<std::tuple<std::reference_wrapper<foo>&>&>()))’ (type ‘std::reference_wrapper<foo>’) to type ‘std::_Mem_fn_base<void (foo::*)(int), true>::_Class* {aka foo*}’ typename add_volatile<_Functor>::type>::type>()( ^ In file included from bug.cpp:1:0: /usr/include/c++/5/functional:607:2: note: candidate: std::_Mem_fn_base<_MemFunPtr, __is_mem_fn>::result_type std::_Mem_fn_base<_MemFunPtr, __is_mem_fn>::operator()(_Tp&&, _Args&& ...) const [with _Tp = std::reference_wrapper<foo>&; _Args = {volatile int&}; _Req = void; _MemFunPtr = void (foo::*)(int); bool __is_mem_fn = true; std::_Mem_fn_base<_MemFunPtr, __is_mem_fn>::result_type = void] <near match> operator()(_Tp&& __object, _Args&&... __args) const ^ /usr/include/c++/5/functional:607:2: note: passing ‘volatile std::_Mem_fn<void (foo::*)(int)>*’ as ‘this’ argument discards qualifiers /usr/include/c++/5/functional:618:2: note: candidate: std::_Mem_fn_base<_MemFunPtr, __is_mem_fn>::result_type std::_Mem_fn_base<_MemFunPtr, __is_mem_fn>::operator()(std::reference_wrapper<_Tp>, _Args&& ...) const [with _Tp = foo; _Args = {volatile int&}; _Req = void; _MemFunPtr = void (foo::*)(int); bool __is_mem_fn = true; std::_Mem_fn_base<_MemFunPtr, __is_mem_fn>::result_type = void] <near match> operator()(reference_wrapper<_Tp> __ref, _Args&&... __args) const ^ /usr/include/c++/5/functional:618:2: note: passing ‘volatile std::_Mem_fn<void (foo::*)(int)>*’ as ‘this’ argument discards qualifiers In file included from bug.cpp:1:0: /usr/include/c++/5/functional:1171:2: note: candidate: template<class ... _Args, class _Result> _Result std::_Bind<_Functor(_Bound_args ...)>::operator()(_Args&& ...) const volatile [with _Args = {_Args ...}; _Result = _Result; _Functor = std::_Mem_fn<void (foo::*)(int)>; _Bound_args = {std::_Placeholder<1>, int}] operator()(_Args&&... __args) const volatile ^ /usr/include/c++/5/functional:1171:2: note: template argument deduction/substitution failed: /usr/include/c++/5/functional:1167:63: error: no match for call to ‘(const volatile std::_Mem_fn<void (foo::*)(int)>) (std::reference_wrapper<foo>&, const volatile int&)’ typename add_cv<_Functor>::type>::type>()( ^ In file included from bug.cpp:1:0: /usr/include/c++/5/functional:582:2: note: candidate: std::_Mem_fn_base<_MemFunPtr, __is_mem_fn>::result_type std::_Mem_fn_base<_MemFunPtr, __is_mem_fn>::operator()(std::_Mem_fn_base<_MemFunPtr, __is_mem_fn>::_Class&, _Args&& ...) const [with _Args = {const volatile int&}; _Req = void; _MemFunPtr = void (foo::*)(int); bool __is_mem_fn = true; std::_Mem_fn_base<_MemFunPtr, __is_mem_fn>::result_type = void; std::_Mem_fn_base<_MemFunPtr, __is_mem_fn>::_Class = foo] <near match> operator()(_Class& __object, _Args&&... __args) const ^ /usr/include/c++/5/functional:582:2: note: passing ‘const volatile std::_Mem_fn<void (foo::*)(int)>*’ as ‘this’ argument discards qualifiers /usr/include/c++/5/functional:589:2: note: candidate: template<class ... _Args, class _Req> std::_Mem_fn_base<_MemFunPtr, __is_mem_fn>::result_type std::_Mem_fn_base<_MemFunPtr, __is_mem_fn>::operator()(std::_Mem_fn_base<_MemFunPtr, __is_mem_fn>::_Class&&, _Args&& ...) const [with _Args = {_Args ...}; _Req = _Req; _MemFunPtr = void (foo::*)(int); bool __is_mem_fn = true] operator()(_Class&& __object, _Args&&... __args) const ^ /usr/include/c++/5/functional:589:2: note: template argument deduction/substitution failed: In file included from bug.cpp:1:0: /usr/include/c++/5/functional:1167:63: note: cannot convert ‘std::_Mu<std::_Placeholder<1>, false, true>().std::_Mu<_Arg, false, true>::operator()<std::tuple<std::reference_wrapper<foo>&> >((* & std::declval<const volatile std::_Placeholder<1>&>()), (* & std::declval<std::tuple<std::reference_wrapper<foo>&>&>()))’ (type ‘std::reference_wrapper<foo>’) to type ‘std::_Mem_fn_base<void (foo::*)(int), true>::_Class&& {aka foo&&}’ typename add_cv<_Functor>::type>::type>()( ^ In file included from bug.cpp:1:0: /usr/include/c++/5/functional:599:2: note: candidate: template<class ... _Args, class _Req> std::_Mem_fn_base<_MemFunPtr, __is_mem_fn>::result_type std::_Mem_fn_base<_MemFunPtr, __is_mem_fn>::operator()(std::_Mem_fn_base<_MemFunPtr, __is_mem_fn>::_Class*, _Args&& ...) const [with _Args = {_Args ...}; _Req = _Req; _MemFunPtr = void (foo::*)(int); bool __is_mem_fn = true] operator()(_Class* __object, _Args&&... __args) const ^ /usr/include/c++/5/functional:599:2: note: template argument deduction/substitution failed: In file included from bug.cpp:1:0: /usr/include/c++/5/functional:1167:63: note: cannot convert ‘std::_Mu<std::_Placeholder<1>, false, true>().std::_Mu<_Arg, false, true>::operator()<std::tuple<std::reference_wrapper<foo>&> >((* & std::declval<const volatile std::_Placeholder<1>&>()), (* & std::declval<std::tuple<std::reference_wrapper<foo>&>&>()))’ (type ‘std::reference_wrapper<foo>’) to type ‘std::_Mem_fn_base<void (foo::*)(int), true>::_Class* {aka foo*}’ typename add_cv<_Functor>::type>::type>()( ^ In file included from bug.cpp:1:0: /usr/include/c++/5/functional:607:2: note: candidate: std::_Mem_fn_base<_MemFunPtr, __is_mem_fn>::result_type std::_Mem_fn_base<_MemFunPtr, __is_mem_fn>::operator()(_Tp&&, _Args&& ...) const [with _Tp = std::reference_wrapper<foo>&; _Args = {const volatile int&}; _Req = void; _MemFunPtr = void (foo::*)(int); bool __is_mem_fn = true; std::_Mem_fn_base<_MemFunPtr, __is_mem_fn>::result_type = void] <near match> operator()(_Tp&& __object, _Args&&... __args) const ^ /usr/include/c++/5/functional:607:2: note: passing ‘const volatile std::_Mem_fn<void (foo::*)(int)>*’ as ‘this’ argument discards qualifiers /usr/include/c++/5/functional:618:2: note: candidate: std::_Mem_fn_base<_MemFunPtr, __is_mem_fn>::result_type std::_Mem_fn_base<_MemFunPtr, __is_mem_fn>::operator()(std::reference_wrapper<_Tp>, _Args&& ...) const [with _Tp = foo; _Args = {const volatile int&}; _Req = void; _MemFunPtr = void (foo::*)(int); bool __is_mem_fn = true; std::_Mem_fn_base<_MemFunPtr, __is_mem_fn>::result_type = void] <near match> operator()(reference_wrapper<_Tp> __ref, _Args&&... __args) const ^ /usr/include/c++/5/functional:618:2: note: passing ‘const volatile std::_Mem_fn<void (foo::*)(int)>*’ as ‘this’ argument discards qualifiers