Search

std::bind with std::reference_wrapper<T> argument doesn't work on function object with template operator() by Sven Groot

Closed
as Fixed Help for as Fixed

1
0
Sign in
to vote
Type: Bug
ID: 688731
Opened: 9/15/2011 10:13:32 PM
Access Restriction: Public
Moderator Decision: Sent to Engineering Team for consideration
0
Workaround(s)
0
User(s) can reproduce this bug
In order to pass arguments by reference to the std::bind function, you use std::reference_wrapper<T>, typically by invoking std::ref.

However, if std::bind is used on a function object whose operator() is itself a template function, that template will be instantiated with std::reference_wrapper<T> rather than T itself, which is incorrect behavior.

For example, the following code does not compile:

#include <iostream>
#include <functional>
using namespace std;

struct Foo
{
typedef void result_type;

template<typename T>
void operator()(T &n)
{
    n = 5;
}
};

int main()
{
int n = 0;
Foo f;
auto func = bind(f, ref(n));

func();
cout << n << endl;

return 0;
}

This code does compile and work correctly on g++ 4.6.1, or if std::bind/std::ref is replaced with boost::bind/boost::ref.

A real-world example where this is a problem is the Boost.Random library. For example, the following does not work on VC++ (but does on g++):

boost::mt19337 engine;
boost::uniform_int<> distribution(0, 10);
auto func = std::bind(distribution, std::ref(engine));
Details (expand)

Visual Studio/Team Foundation Server/.NET Framework Tooling version

Visual Studio 2010 SP1

Steps to reproduce

Create a new Visual C++ project, and use the code sample attached to this bug report. Attempt to compile it.

Product Language

English

Operating System

Windows 7

Operating System Language

English

Actual results

The code sample fails to compile with the following error message:

1>------ Build started: Project: cpptest, Configuration: Debug x64 ------
1> test.cpp
1>test.cpp(13): error C2679: binary '=' : no operator found which takes a right-hand operand of type 'int' (or there is no acceptable conversion)
1>         C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\xrefwrap(435): could be 'std::tr1::reference_wrapper<_Ty> &std::tr1::reference_wrapper<_Ty>::operator =(const std::tr1::reference_wrapper<_Ty> &)'
1>         with
1>         [
1>             _Ty=int
1>         ]
1>         while trying to match the argument list '(std::tr1::reference_wrapper<_Ty>, int)'
1>         with
1>         [
1>             _Ty=int
1>         ]
1>         C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\xxcallobj(13) : see reference to function template instantiation 'void Foo::operator ()<_Arg>(T &)' being compiled
1>         with
1>         [
1>             _Arg=std::tr1::reference_wrapper<int>,
1>             T=std::tr1::reference_wrapper<int>
1>         ]
1>         C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\xxbind1(292) : see reference to function template instantiation '_Ret std::tr1::_Callable_obj<_Ty,_Indirect>::_ApplyX<_Ret,_Arg&>(_Arg0)' being compiled
1>         with
1>         [
1>             _Ret=_Rx,
1>             _Ty=Foo,
1>             _Indirect=false,
1>             _Arg=std::tr1::reference_wrapper<int>,
1>             _Arg0=std::tr1::reference_wrapper<int> &
1>         ]
1>         C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\xxbind0(31) : see reference to function template instantiation '_Ret std::tr1::_Bind1<_Callable,_Arg0>::_ApplyX<_Rx,std::tr1::_Nil&,std::tr1::_Nil&,std::tr1::_Nil&,std::tr1::_Nil&,std::tr1::_Nil&,std::tr1::_Nil&,std::tr1::_Nil&,std::tr1::_Nil&,std::tr1::_Nil&,std::tr1::_Nil&>(_Barg0,_Barg1,_Barg2,_Barg3,_Barg4,_Barg5,_Barg6,_Barg7,_Barg8,_Barg9)' being compiled
1>         with
1>         [
1>             _Ret=_Rx,
1>             _Callable=std::tr1::_Callable_obj<Foo,false>,
1>             _Arg0=std::tr1::reference_wrapper<int>,
1>             _Barg0=std::tr1::_Nil &,
1>             _Barg1=std::tr1::_Nil &,
1>             _Barg2=std::tr1::_Nil &,
1>             _Barg3=std::tr1::_Nil &,
1>             _Barg4=std::tr1::_Nil &,
1>             _Barg5=std::tr1::_Nil &,
1>             _Barg6=std::tr1::_Nil &,
1>             _Barg7=std::tr1::_Nil &,
1>             _Barg8=std::tr1::_Nil &,
1>             _Barg9=std::tr1::_Nil &
1>         ]
1>         C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\xxbind0(27) : while compiling class template member function 'void std::tr1::_Bind_base<_Ret,_BindN>::operator ()(void)'
1>         with
1>         [
1>             _Ret=std::tr1::_Notforced,
1>             _BindN=std::tr1::_Bind1<std::tr1::_Callable_obj<Foo,false>,std::tr1::reference_wrapper<int>>
1>         ]
1>         C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\functional(408) : see reference to class template instantiation 'std::tr1::_Bind_base<_Ret,_BindN>' being compiled
1>         with
1>         [
1>             _Ret=std::tr1::_Notforced,
1>             _BindN=std::tr1::_Bind1<std::tr1::_Callable_obj<Foo,false>,std::tr1::reference_wrapper<int>>
1>         ]
1>         test.cpp(21) : see reference to class template instantiation 'std::tr1::_Bind_fty<_Fty,_Ret,_BindN>' being compiled
1>         with
1>         [
1>             _Fty=Foo,
1>             _Ret=std::tr1::_Notforced,
1>             _BindN=std::tr1::_Bind1<std::tr1::_Callable_obj<Foo,false>,std::tr1::reference_wrapper<int>>
1>         ]
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

Expected results

I expected the code to compile successfully, with the template parameter for Foo::operator() bound to int. The program should print "5" when running, indicating that the parameter was properly passed by reference.

An example of how the code is supposed to function can be found here: http://www.ideone.com/gWyb0
File Attachments
File Name Submitted By Submitted On File Size  
test.cpp 9/15/2011 302 bytes
Sign in to post a comment.
Posted by Microsoft on 9/21/2011 at 8:03 PM
Hi,

Thanks for reporting this bug. Yep, we've already fixed it in VC11.

If you have any further questions, feel free to E-mail me at stl@microsoft.com .

Stephan T. Lavavej
Visual C++ Libraries Developer
Posted by Sven Groot on 9/18/2011 at 6:23 PM
I just tested this on the Visual Studio 11 Developer Preview and was unable to reproduce. It appears this issue has already been fixed. I apologize for wasting your time. :)
Posted by MS-Moderator09 [Feedback Moderator] on 9/16/2011 at 2:26 AM
Thank you for submitting feedback on Visual Studio 2010 and .NET Framework. Your issue has been routed to the appropriate VS development team for review. We will contact you if we require any additional information.
Posted by MS-Moderator01 on 9/15/2011 at 10:43 PM
Thank you for your feedback, we are currently reviewing the issue you have submitted. If this issue is urgent, please contact support directly(http://support.microsoft.com)
Sign in to post a workaround.