Bug 48313 - [C++0x] std::bind with template function
Summary: [C++0x] std::bind with template function
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 4.6.0
: P3 normal
Target Milestone: 4.6.1
Assignee: Jason Merrill
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2011-03-28 11:27 UTC by Jörg Richter
Modified: 2011-03-31 12:40 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2011-03-28 20:10:59


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Jörg Richter 2011-03-28 11:27:16 UTC
$ cat > t.cc << EOF
#include <functional>

template<class T> void func( T )
{}

int main( int, char** )
{
  std::bind( func<int>, 0 );
}
EOF

$ g++ t.cc -std=gnu++0x
t.cc: In function 'int main(int, char**)':
t.cc:8:27: error: cannot bind 'void(int)' lvalue to 'void (&&)(int)'
...

This is with GCC 4.6.0.  This works with GCC 4.5.2.
Comment 1 Jonathan Wakely 2011-03-28 12:17:25 UTC
The example should work. I'm travelling today but will check the <functional> code later to see why the F&& constructor is being chosen instead of the const F& one.
Comment 2 Jonathan Wakely 2011-03-28 12:24:23 UTC
The example can be modified to work by passing a pointer, so the template argument isn't deduced as a function type:

  std::bind( &func<int>, 0 );
Comment 3 Jonathan Wakely 2011-03-28 12:43:12 UTC
It's not the _Bind constructor, it's the bind() call itself, this demonstrates the problem:

template<typename _Functor, typename... _ArgTypes>
    inline
    void
    bind(_Functor&& __f, _ArgTypes&&... __args) { }

template<class T> void func( T )
{}

int main( int, char** )
{
    bind( func<int>, 0 );
}


we might just need to overload std::bind for function types

std::bind() in 4.5 was defined differently as it didn't support rvalues properly, so didn't show the problem
Comment 4 Jonathan Wakely 2011-03-28 14:26:35 UTC
slightly further reduced:


template<typename Functor, typename ArgTypes>
    inline void
    bind(Functor&& f, ArgTypes&& a) { }

template<typename T>
void func( T )
{}

int main( int, char** )
{
    bind( func<int>, 0 );
}

this is certainly not a libstdc++ bug (std::bind matches the signature require by the C++0x draft)

I think the parameter is a non-deduced context, because the argument is an overload set containing one or more function templates ([temp.deduct.call p6)

So I think this is actually invalid and G++ is right to reject it.
Comment 5 Jonathan Wakely 2011-03-28 17:02:14 UTC
Actually no, that paragraph doesn't apply because P is a reference type not function type.

Jason should the call to f(h<int>) be accepted here?

template<typename F>
void f(F&&) { }

void g() { }

template<typename T> void h() { }

int main()
{
  f( g );       // OK
  void (&p)() = h<int>;
  f( p );       // OK
  f( h<int> );  // ???
}
Comment 6 Jason Merrill 2011-03-28 20:10:59 UTC
Yes, that's a bug.
Comment 7 Jason Merrill 2011-03-29 00:04:57 UTC
Author: jason
Date: Tue Mar 29 00:04:54 2011
New Revision: 171643

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=171643
Log:
	PR c++/48313
	* pt.c (maybe_adjust_types_for_deduction): Handle T&& deduction
	from overloaded function.

Added:
    trunk/gcc/testsuite/g++.dg/cpp0x/rv-deduce2.C
Modified:
    trunk/gcc/cp/ChangeLog
    trunk/gcc/cp/pt.c
    trunk/gcc/testsuite/ChangeLog
Comment 8 Jason Merrill 2011-03-29 14:25:34 UTC
Author: jason
Date: Tue Mar 29 14:25:22 2011
New Revision: 171669

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=171669
Log:
	PR c++/48313
	* pt.c (maybe_adjust_types_for_deduction): Handle T&& deduction
	from overloaded function.

Added:
    branches/gcc-4_6-branch/gcc/testsuite/g++.dg/cpp0x/rv-deduce2.C
Modified:
    branches/gcc-4_6-branch/gcc/cp/ChangeLog
    branches/gcc-4_6-branch/gcc/cp/pt.c
    branches/gcc-4_6-branch/gcc/testsuite/ChangeLog
Comment 9 Jason Merrill 2011-03-29 14:30:17 UTC
Fixed for 4.6.1.
Comment 10 Jonathan Wakely 2011-03-31 12:40:24 UTC
Thanks for the fix, Jason, I've just encountered the bug myself using boost::thread

I expect others will to, so for the benefit of search engines, the error is

post_event_test.cc:130:47: error: cannot bind 'void()' lvalue to 'void (&&)()'
/home/jwakely/src/boost/boost_1_45_0/boost/thread/detail/thread.hpp:167:9: error:   initializing argument 1 of 'boost::thread::thread(F&&) [with F = void()]'