1

Given a function like

void MyFunction(std::unique_ptr<int> arg);

it is not possible (MSVC 2012) to create a functor like

std::function<void(std::unique_ptr<int>)> f = std::bind(&MyFunction, std::placeholders::_1);

The problem is not the bind - using auto f = std::bind(...) works. Also, using a shared_ptr also works

  • Why is unique_ptr disallowed?
  • Is this a MSVC problem or general C++11 restriction?
  • Is there a work-around without changing the function definition?
R. Martinho Fernandes
  • 228,013
  • 71
  • 433
  • 510
Zero
  • 11,593
  • 9
  • 52
  • 70
  • Note this is not the same as `std::bind(&MyFunction, std::unique_ptr())` which has been addressed, for example, http://stackoverflow.com/questions/9955714/does-stdbind-work-with-move-only-types-in-general-and-stdunique-ptr-in-part – Zero Jun 17 '13 at 05:59
  • What do you mean by _"It is not possible to create a functor"_? Your code compiles for me perfectly. [Example](http://coliru.stacked-crooked.com/view?id=fc07eb6c07adb3b78b1b8546706c066c-df8dcf008f5684150551e8d7e183dfe4). – awesoon Jun 17 '13 at 06:12
  • Question updated with compiler info, are you using gcc? – Zero Jun 17 '13 at 06:15
  • 1
    Both g++ and clang++. Could you post a compiler errors, please? – awesoon Jun 17 '13 at 06:17
  • A million lines of template errors, most nested being: `VC\include\functional(1152): error C2248: 'std::unique_ptr<_Ty>::unique_ptr' : cannot access private member declared in class 'std::unique_ptr<_Ty>` - so it appears a copy is being attempted somewhere, I wouldn't have thought that would be necessary in this case. If you have it working in g++ this would appear to be MS specific, not surprising given the varying levels of support for C++11 – Zero Jun 17 '13 at 06:20

2 Answers2

3

The code below compiles fine using gcc 4.8. You will notice that if "g" is not called with move (that converts the lvalue to an rvalue), the code fails to compile. As mentioned earlier, the bind succeeds because the failure only happens when operator()( ... ) is called, because of the fact that unique_ptr is not copyable. The call "f" is permissible, as shared_ptr has a copy constructor.

#include <functional>
#include <memory>


void foo1( std::shared_ptr<int> ){}
void foo2( std::unique_ptr<int> ){}

int main() 
{
    using namespace std::placeholders;

    std::function<void(std::shared_ptr<int>)> f = std::bind( foo1, _1 );
    std::function<void(std::unique_ptr<int>)> g = std::bind( foo2, _1 );

    std::unique_ptr<int> i( new int(5) );
    g( move( i ) ); //Requires the move

    std::shared_ptr<int> j( new int(5) );
    f( j ); //Works fine without the move
    return 0;
}
Werner Erasmus
  • 3,988
  • 17
  • 31
0

A workaround is to have

void MyFunction(std::unique_ptr<int>& arg)

but that doesn't work if you can't change the function definition.

Zero
  • 11,593
  • 9
  • 52
  • 70