Michael, In lld, we have places that used nested a ErrorOr<std::unique_ptr<xx>> and I often hit compiler errors that require breaking up expressions to work around. Do you have suggestions on how to code the following simple examples to not error? Can some of these be fixed in ErrorOr.h? Or am I totally not getting something? -Nick struct Foo { void doit(); }; std::unique_ptr<Foo> factoryU() { std::unique_ptr<Foo> f(new Foo); return f; // works as expected } ErrorOr<Foo*> factoryE() { ErrorOr<Foo*> f = new Foo; return f; // works as expected } ErrorOr<std::unique_ptr<Foo>> factoryEU() { std::unique_ptr<Foo> f(new Foo); return f; // ERROR: call to implicitly-deleted copy constructor of 'std::__1::unique_ptr<Foo, std::__1::default_delete<Foo> >’ } void sinkU(std::unique_ptr<Foo> f) { f->doit(); // works as expected } void sinkE(ErrorOr<Foo*> f) { f->doit(); // ERROR: member reference base type 'typename remove_reference<Foo *>::type' (aka 'Foo *') is not a structure or union' } void sinkEU(ErrorOr<std::unique_ptr<Foo>> f) { f->doit(); // ERROR: no member named 'doit' in 'std::__1::unique_ptr<Foo, std::__1::default_delete<Foo> >' } -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20131121/19949222/attachment.html>
On 11/21/2013 5:57 PM, Nick Kledzik wrote:> std::unique_ptr<Foo> factoryU() { > std::unique_ptr<Foo> f(new Foo); > return f; // works as expected > } > > ErrorOr<Foo*> factoryE() { > ErrorOr<Foo*> f = new Foo; > return f; // works as expected > } > > ErrorOr<std::unique_ptr<Foo>> factoryEU() { > std::unique_ptr<Foo> f(new Foo); > return f; // ERROR: call to implicitly-deleted copy constructor of 'std::__1::unique_ptr<Foo, std::__1::default_delete<Foo> >’ > }I think return std::move(f) would fix this, isnt it ?> > void sinkU(std::unique_ptr<Foo> f) { > f->doit(); // works as expected > } > > void sinkE(ErrorOr<Foo*> f) { > f->doit(); // ERROR: member reference base type 'typename remove_reference<Foo *>::type' (aka 'Foo *') is not a structure or union' > } > > void sinkEU(ErrorOr<std::unique_ptr<Foo>> f) { > f->doit(); // ERROR: no member named 'doit' in 'std::__1::unique_ptr<Foo, std::__1::default_delete<Foo> >' > }if (error_code(f)) return; (*f)->doit() Thanks Shankar Easwaran -- Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by the Linux Foundation
On Thu, Nov 21, 2013 at 3:57 PM, Nick Kledzik <kledzik at apple.com> wrote:> Michael, > > In lld, we have places that used nested a ErrorOr<std::unique_ptr<xx>> and > I often hit compiler errors that require breaking up expressions to work > around. Do you have suggestions on how to code the following simple > examples to not error? Can some of these be fixed in ErrorOr.h? Or am I > totally not getting something? > > -Nick > > > struct Foo { void doit(); }; > > > std::unique_ptr<Foo> factoryU() { > std::unique_ptr<Foo> f(new Foo); > return f; // works as expected > } > > ErrorOr<Foo*> factoryE() { > ErrorOr<Foo*> f = new Foo; > return f; // works as expected > } > > ErrorOr<std::unique_ptr<Foo>> factoryEU() { > std::unique_ptr<Foo> f(new Foo); > return f; // ERROR: call to implicitly-deleted copy constructor of > 'std::__1::unique_ptr<Foo, std::__1::default_delete<Foo> >’ >While a local variable inside a function is implicitly moved when returned, that only happens when the return expression is the local variable and the same type. In this case you have an implicit conversion that would work like any other conversion of an lvalue. So you have to write return std::move(f); unfortunately. (or you could be more explicit/verbose and say return ErrorOr<...>(std::move(f)); )> } > > > void sinkU(std::unique_ptr<Foo> f) { > f->doit(); // works as expected > } > > void sinkE(ErrorOr<Foo*> f) { > f->doit(); // ERROR: member reference base type 'typename > remove_reference<Foo *>::type' (aka 'Foo *') is not a structure or union' >It's questionable whether this should work. ErrorOr<T> models a pointer to T. So if you had ErrorOr<Foo> f you'd expect to be able to do f->doit(), but if it's an ErrorOr<Foo*>, jsut like if it were a Foo**, you'd expect to have to use (*f)->doit().> } > > void sinkEU(ErrorOr<std::unique_ptr<Foo>> f) { > f->doit(); // ERROR: no member named 'doit' in > 'std::__1::unique_ptr<Foo, std::__1::default_delete<Foo> >' >Same here.> } > > > > _______________________________________________ > LLVM Developers mailing list > LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev > >-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20131121/56ab8a70/attachment.html>
On Nov 21, 2013, at 4:07 PM, David Blaikie <dblaikie at gmail.com> wrote:> > > > On Thu, Nov 21, 2013 at 3:57 PM, Nick Kledzik <kledzik at apple.com> wrote: > Michael, > > In lld, we have places that used nested a ErrorOr<std::unique_ptr<xx>> and I often hit compiler errors that require breaking up expressions to work around. Do you have suggestions on how to code the following simple examples to not error? Can some of these be fixed in ErrorOr.h? Or am I totally not getting something? > > -Nick > > > struct Foo { void doit(); }; > > > std::unique_ptr<Foo> factoryU() { > std::unique_ptr<Foo> f(new Foo); > return f; // works as expected > } > > ErrorOr<Foo*> factoryE() { > ErrorOr<Foo*> f = new Foo; > return f; // works as expected > } > > ErrorOr<std::unique_ptr<Foo>> factoryEU() { > std::unique_ptr<Foo> f(new Foo); > return f; // ERROR: call to implicitly-deleted copy constructor of 'std::__1::unique_ptr<Foo, std::__1::default_delete<Foo> >’ > > While a local variable inside a function is implicitly moved when returned, that only happens when the return expression is the local variable and the same type. In this case you have an implicit conversion that would work like any other conversion of an lvalue. > > So you have to write return std::move(f); unfortunately. (or you could be more explicit/verbose and say return ErrorOr<...>(std::move(f)); )Is there no way to promote the return value automatically? If you make the local variable be of type Error<std::unique_ptr<Foo>>, you run into the errors that you can’t access its methods (below).> > } > > > void sinkU(std::unique_ptr<Foo> f) { > f->doit(); // works as expected > } > > void sinkE(ErrorOr<Foo*> f) { > f->doit(); // ERROR: member reference base type 'typename remove_reference<Foo *>::type' (aka 'Foo *') is not a structure or union' > > It's questionable whether this should work. ErrorOr<T> models a pointer to T. So if you had ErrorOr<Foo> f you'd expect to be able to do f->doit(), but if it's an ErrorOr<Foo*>, jsut like if it were a Foo**, you'd expect to have to use (*f)->doit().If ErrorOr<T> models a pointer to T, then ErrorOr<std::unique_ptr<Foo>> would be modeling a pointer to a std::unique_ptr<Foo>. But unique_ptr<> already adds a pointer to the type. I thought that ErrorOr<T> did not add a pointer, but rather implemented operator->() to access the underlying type. Is there some way to do partial specialization of ErrorOr<std::unique_ptr<T>> to make -> see through both ErrorOr and unique_ptr? My overall point is that unique_ptr<> is cool. ErrorOr<> is cool. But when you combine the two, the cool transparency disappears ;-( -Nick> > } > > void sinkEU(ErrorOr<std::unique_ptr<Foo>> f) { > f->doit(); // ERROR: no member named 'doit' in 'std::__1::unique_ptr<Foo, std::__1::default_delete<Foo> >' > > Same here. > > } > > > > _______________________________________________ > LLVM Developers mailing list > LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev > >-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20131121/785d1420/attachment.html>