<div dir="ltr"><br><div class="gmail_extra"><br><br><div class="gmail_quote">On Thu, Nov 21, 2013 at 4:33 PM, Nick Kledzik <span dir="ltr"><<a href="mailto:kledzik@apple.com" target="_blank">kledzik@apple.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word"><br><div><div class="im"><div>On Nov 21, 2013, at 4:07 PM, David Blaikie <<a href="mailto:dblaikie@gmail.com" target="_blank">dblaikie@gmail.com</a>> wrote:</div>
<br><blockquote type="cite"><div dir="ltr"><br><div class="gmail_extra"><br><br><div class="gmail_quote">On Thu, Nov 21, 2013 at 3:57 PM, Nick Kledzik <span dir="ltr"><<a href="mailto:kledzik@apple.com" target="_blank">kledzik@apple.com</a>></span> wrote:<br>

<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div style="word-wrap:break-word"><div>Michael,</div><div>
<br></div>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?<div>

<br></div><div>-Nick<br><div><br></div><div><br><font face="Monaco" size="1">struct Foo { void doit(); };<br><br><br>std::unique_ptr<Foo> factoryU() {<br>  std::unique_ptr<Foo> f(new Foo);<br>  return f;  // works as expected<br>

}<br><br>ErrorOr<Foo*> factoryE() {<br>  ErrorOr<Foo*> f = new Foo;<br>  return f;  // works as expected<br>}<br><br>ErrorOr<std::unique_ptr<Foo>> factoryEU() {<br>  std::unique_ptr<Foo> f(new Foo);<br>

  return f; // ERROR: call to implicitly-deleted copy constructor of 'std::__1::unique_ptr<Foo, std::__1::default_delete<Foo> >’<br></font></div></div></div></blockquote><div><br></div><div>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.<br>

<br>So you have to write return std::move(f); unfortunately. (or you could be more explicit/verbose and say return ErrorOr<...>(std::move(f)); )</div></div></div></div></blockquote></div><div>Is there no way to promote the return value automatically? </div>
</div></div></blockquote><div><br></div><div>None that I know of. There's just one special case in the language - where you directly return a local variable and that variable is of the return type (no implicit conversions, etc). Might be something that could be improved (CC'd Richard Smith in case he can comment on future work in the C++ standard space).</div>
<div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word"><div><div> 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).</div>
<div class="im"><div><br></div><br><blockquote type="cite"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">

<div style="word-wrap:break-word"><font face="Monaco" size="1">}<br><br><br>void sinkU(std::unique_ptr<Foo> f) {<br>  f->doit();  // works as expected<br>}<br><br>void sinkE(ErrorOr<Foo*> f) {<br>
  f->doit(); // ERROR: member reference base type 'typename remove_reference<Foo *>::type' (aka 'Foo *') is not a structure or union'<br></font></div></blockquote><div><br>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().</div>
</div></div></div></blockquote></div><div>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. </div>
</div></div></blockquote><div><br></div><div>I don't really understand this last comment. Perhaps it's because I did a poor job explaining, I'm not sure.<br><br>Let's say I have some type Foo with a member function bar.<br>
<br>If I have a raw T* 't', then I would expect to write "t->bar()" (or "(*t).bar()") to call bar.<br><br>If I have an ErrorOr<T> 'e', then ErrorOr provides operator* and operator-> to access the underlying T. So I would write "e->bar()" or "(*e).bar()". ErroOr acts as though it's a pointer to T.<br>
<br>If I had a T** 't', then I would expect to write "(*t)->bar()" or "(**t).bar()".<br><br>So by analogy, if I have an ErrorOr<T*> I would expect to write "(*e)->bar()" or "(**e).bar()".<br>
<br>Now replace T* with unique_ptr<T> in the above examples and everything remains the same. ErrorOr<unique_ptr<T>> is like a pointer to a pointer to T.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div style="word-wrap:break-word"><div><div> </div><div><br></div><div>Is there some way to do partial specialization of ErrorOr<std::unique_ptr<T>> to make -> see through both ErrorOr and unique_ptr?</div>
</div></div></blockquote><div><br></div><div>We could, but it would be confusing, because then "e->bar()" wouldn't be the same as "(*e).bar()" (you'd still have to write "(**e).bar()" or "(*e)->bar()").</div>
<div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word"><div><div><br></div><div>My overall point is that unique_ptr<> is cool.  ErrorOr<> is cool.  But when you combine the two, the cool transparency disappears ;-(</div>
</div></div></blockquote><div><br></div><div>I disagree that "the cool transparency disappears". unique_ptr<T> models a pointer to T (by exposing op*/op-> to access the underlying object), ErroOr<T> models a pointer to T (by exposing op*/op-> to access the underlying object). So ErrorOr<unique_ptr<T>> models a pointer to pointer to T and thus requires two dereferences.<br>
<br>But yes, broadly it is kind of annoying - personally I have fantasy ideas of overloading operator '.', having a unique_ptr that was never-null and thus didn't model a pointer (and overloaded operator '.' for access to the underlying object) and then composing this unique_ref with ErrorOr would just add one level of pointery-ness, not two. <br>
<br>- Dave</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word"><div><span class="HOEnZb"><font color="#888888"><div><br>
</div><div>-Nick</div></font></span><div class="im"><div><br></div><br><blockquote type="cite"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">
<div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word"><font face="Monaco" size="1">}<br><br>void sinkEU(ErrorOr<std::unique_ptr<Foo>> f) {<br>

  f->doit(); // ERROR: no member named 'doit' in 'std::__1::unique_ptr<Foo, std::__1::default_delete<Foo> >'<br></font></div></blockquote><div><br></div><div>Same here.</div><div>
 </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word"><font face="Monaco" size="1">}<br><br></font><br></div><br>
_______________________________________________<br>
LLVM Developers mailing list<br>
<a href="mailto:LLVMdev@cs.uiuc.edu" target="_blank">LLVMdev@cs.uiuc.edu</a>         <a href="http://llvm.cs.uiuc.edu/" target="_blank">http://llvm.cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev</a><br>
<br></blockquote></div><br></div></div>
</blockquote></div></div><br></div></blockquote></div><br></div></div>