I'm playing with new language features and as a result:
win32 console app->empty project
file: main.cpp
#include <memory>
#include <functional>
#include <utility>
void foo(std::unique_ptr<int> pint)
{
}
int wmain( )
{
std::unique_ptr<int> pint(new int(42));
std::bind(foo, std::move(pint));
}
1>main.obj : error LNK2001: unresolved external symbol "public: __thiscall
std::unique_ptr<int,struct std::default_delete<int> >::unique_ptr<int,struct
std::default_delete<int> >(class std::unique_ptr<int,struct
std::default_delete<int> > const &)"
(??0?$unique_ptr@HU?$default_delete@H@std@@@std@@QAE@ABV01@@Z)
by analogy with:
#include <memory>
#include <utility>
void foo(std::unique_ptr<int> pint) { }
int wmain( )
{
std::unique_ptr<int> pint(new int(42));
foo(std::move(pint));
}
I expected that move constructor is called not copy constructor and I also
expected that move
constructor will be called when callee is invoked.
Will it be possible to transfer ownership to callee using bind, unique_ptr,
move combination ?
And does C++1x say anything about this or is it a VC bug or I expect too
much?
Thanks
The functional produced by std::bind stores a copy of pint (which it can do using move constructor). Its operator() would then call foo(copy_of_pint). It doesn't know enough about its parameter to infer that it should use move() in this call. So this is the part that fails.
The (draft) standard requires that parameters of std::bind be CopyConstructible, which unique_ptr isn't. So your program is invalid.
> I expected that move constructor is called not copy constructor and I also
> expected that move
> constructor will be called when callee is invoked.
What led you to expect the latter?
> Will it be possible to transfer ownership to callee using bind, unique_ptr,
> move combination ?
Not as far as I can tell. Why would you need a functional that can be called only once?
> And does C++1x say anything about this
Yes.
> or is it a VC bug
No.
> or I expect too much?
Apparently.
--
With best wishes,
Igor Tandetnik
With sufficient thrust, pigs fly just fine. However, this is not necessarily a good idea. It is hard to be sure where they are going to land, and it could be dangerous sitting under them as they fly overhead. -- RFC 1925
actually std::thread constructor led me to that
std::thread uses similar mechanism as bind, and it will be possible to
transfer ownership using:
std::thread thr(foo, std::move(pint));
where pint is instance of unique_ptr<int>
and I still think that this should be same as:
std::thread thr(std::bind(foo, std::move(pint)));
because there will have another:
Imperfection XXX:
in thread construction for most generic implementation don't use bind
although it may work now it will not work in all cases.
so I was convinced that rules for bind got somehow relaxed, or at least
has unique_ptr specialization.
>> Will it be possible to transfer ownership to callee using bind, unique_ptr,
>> move combination ?
>
> Not as far as I can tell. Why would you need a functional that can be called only once?
>
>> And does C++1x say anything about this
>
> Yes.
>
>> or is it a VC bug
>
> No.
>
>> or I expect too much?
>
> Apparently.
Igor thank you for clearing this
That constructor is explicitly documented to support MoveConstructible arguments. The reason for the difference, I presume, is because thread is known to call its function object exactly once.
> std::thread uses similar mechanism as bind, and it will be possible to
> transfer ownership using:
>
> std::thread thr(foo, std::move(pint));
> where pint is instance of unique_ptr<int>
>
> and I still think that this should be same as:
>
> std::thread thr(std::bind(foo, std::move(pint)));
bind doesn't know that it's going to be called only once.
Although mechanics std::thread constructor and std::bind is similar, now
when you say it, yes contexts and definitely the purposes of std::bind
and std::thread are different. I'm no longer convinced that
specialization of std::bind for std::unique_ptr just for sake of
mimicking same behavior is a good idea.
Thank you again