Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

vc 2010 beta2 bind unique_ptr move

50 views
Skip to first unread message

nebojsa vujnovic

unread,
Dec 2, 2009, 6:55:00 AM12/2/09
to

Hello,

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

Igor Tandetnik

unread,
Dec 2, 2009, 8:41:05 AM12/2/09
to
nebojsa vujnovic wrote:
> 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)

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

nebojsa vujnovic

unread,
Dec 2, 2009, 4:08:42 PM12/2/09
to
Igor Tandetnik wrote:
> nebojsa vujnovic wrote:
>> 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)
>
> 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?
>

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

Igor Tandetnik

unread,
Dec 2, 2009, 4:58:18 PM12/2/09
to
nebojsa vujnovic <unk...@this.is.invalid> wrote:
> Igor Tandetnik wrote:
>> nebojsa vujnovic wrote:
>>> 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?
>>
>
> actually std::thread constructor led me to that

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.

nebojsa vujnovic

unread,
Dec 2, 2009, 6:28:15 PM12/2/09
to
Igor Tandetnik wrote:
> nebojsa vujnovic <unk...@this.is.invalid> wrote:
>> Igor Tandetnik wrote:
>>> nebojsa vujnovic wrote:
>>>> 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?
>>>
>> actually std::thread constructor led me to that
>
> 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

0 new messages