<div dir="ltr"><br><br><div class="gmail_quote"><div dir="ltr">On Thu, Jul 13, 2017 at 2:24 AM Matthew Urquhart via cfe-dev <<a href="mailto:cfe-dev@lists.llvm.org">cfe-dev@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">Hi Csaba,<div><br></div><div>Thanks very much for the reply - makes sense. I was originally having trouble with strings, but switched to ints for a shorter "minimal case."</div><div><br></div><div>In this case since the lambda returns an `int`, it's now `std::function<int()>` not `std::function<const int&()>` which on the surface seems it should be a mismatching type.</div></div></blockquote><div><br>So this is where the kicker/punchline is - a lambda isn't a std::function, a lambda is just its own type with an op() overload.<br><br>std::function wraps any /compatible/ callable.<br><br>So basically if you have some callable object 'f' and this is valid:<br><br>  T1 g(T2 t2, <and so on>) {<br>    return f(std::forward<T2>(t2), <and so on>);<br>  }<br> <br>then 'f' is implicitly convertible to std::function<T1(T2, <and so on>)><br><br>What that means in reality is that, yes, because this is valid (yet buggy):<br><br>  int f();<br>  const int &g() {<br>    return f();</div><div>  }<br><br>so is this:<br><br>  std::function<const int&()> g = f;<br><br>You can get similar kinds of issues with parameters too:<br><br>  void f(bool);<br>  std::function<void(T*)> g = f; //valid but perhaps surprising (f(true) if g(non-null), f(false) if g(null-pointer))<br><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div><br></div><div>Minimal case updated for strings below. Strangely, it works correctly on macOS but invokes undefined behaviour on ubuntu.</div><div><br></div><div>Cheers,</div><div>Matt</div><div><br></div><div>





<p class="m_5235544207348789212inbox-inbox-p1"><span class="m_5235544207348789212inbox-inbox-s1">#include </span><span class="m_5235544207348789212inbox-inbox-s2"><functional></span></p>
<p class="m_5235544207348789212inbox-inbox-p1"><span class="m_5235544207348789212inbox-inbox-s1">#include </span><span class="m_5235544207348789212inbox-inbox-s2"><iostream></span></p>
<p class="m_5235544207348789212inbox-inbox-p2"><span class="m_5235544207348789212inbox-inbox-s2">#include </span><span class="m_5235544207348789212inbox-inbox-s3"><sstream></span></p>
<p class="m_5235544207348789212inbox-inbox-p3"><span class="m_5235544207348789212inbox-inbox-s2"></span><br></p>
<p class="m_5235544207348789212inbox-inbox-p4"><span class="m_5235544207348789212inbox-inbox-s4">void</span><span class="m_5235544207348789212inbox-inbox-s2"> print_stuff(std::function<</span><span class="m_5235544207348789212inbox-inbox-s4">const</span><span class="m_5235544207348789212inbox-inbox-s2"> std::string&()> f) {</span></p></div></div><div dir="ltr"><div>
<p class="m_5235544207348789212inbox-inbox-p4"><span class="m_5235544207348789212inbox-inbox-s2"><span class="m_5235544207348789212inbox-inbox-Apple-converted-space">    </span>std::cout << </span><span class="m_5235544207348789212inbox-inbox-s3">"stuff is: "</span><span class="m_5235544207348789212inbox-inbox-s2"> << f() << std::endl;</span></p>
<p class="m_5235544207348789212inbox-inbox-p4"><span class="m_5235544207348789212inbox-inbox-s2">}</span></p>
<p class="m_5235544207348789212inbox-inbox-p3"><span class="m_5235544207348789212inbox-inbox-s2"></span><br></p>
<p class="m_5235544207348789212inbox-inbox-p4"><span class="m_5235544207348789212inbox-inbox-s4">int</span><span class="m_5235544207348789212inbox-inbox-s2"> main(</span><span class="m_5235544207348789212inbox-inbox-s4">int</span><span class="m_5235544207348789212inbox-inbox-s2"> argc, </span><span class="m_5235544207348789212inbox-inbox-s4">char</span><span class="m_5235544207348789212inbox-inbox-s2"> *argv[]) {</span></p>
</div></div><div dir="ltr"><div><p class="m_5235544207348789212inbox-inbox-p4"><span class="m_5235544207348789212inbox-inbox-s2"><span class="m_5235544207348789212inbox-inbox-Apple-converted-space">    </span>print_stuff([&]() {</span></p>
<p class="m_5235544207348789212inbox-inbox-p4"><span class="m_5235544207348789212inbox-inbox-s2"><span class="m_5235544207348789212inbox-inbox-Apple-converted-space">        </span>std::stringstream ss;</span></p>
<p class="m_5235544207348789212inbox-inbox-p4"><span class="m_5235544207348789212inbox-inbox-s2"><span class="m_5235544207348789212inbox-inbox-Apple-converted-space">        </span>ss << argc;</span></p>
<p class="m_5235544207348789212inbox-inbox-p4"><span class="m_5235544207348789212inbox-inbox-s2"><span class="m_5235544207348789212inbox-inbox-Apple-converted-space">        </span></span><span class="m_5235544207348789212inbox-inbox-s4">return</span><span class="m_5235544207348789212inbox-inbox-s2"> ss.str();</span></p>
<p class="m_5235544207348789212inbox-inbox-p4"><span class="m_5235544207348789212inbox-inbox-s2"><span class="m_5235544207348789212inbox-inbox-Apple-converted-space">    </span>});</span></p>
<p class="m_5235544207348789212inbox-inbox-p4"><span class="m_5235544207348789212inbox-inbox-s2">}</span></p></div></div><br><div class="gmail_quote"><div dir="ltr">On Thu, Jul 13, 2017 at 5:08 PM Csaba Raduly <<a href="mailto:rcsaba@gmail.com" target="_blank">rcsaba@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hi Matthew,<br>
<br>
When you don't specify a return type for the lambda, the compiler<br>
deduces 'int', not 'int&'.<br>
<br>
auto deduced     = []()         { int i = 123; return i; };<br>
auto spelled_out = []() -> int& { int i = 123; return i; };<br>
<br>
int d = deduced;<br>
int s = spelled_out;<br>
<br>
This doesn't compile of course, but the error messages are the useful info:<br>
<br>
$ g++-8 -std=c++11 is_it_ref.cpp<br>
is_it_ref.cpp: In lambda function:<br>
is_it_ref.cpp:2:39: warning: reference to local variable ‘i’ returned<br>
[-Wreturn-local-addr]<br>
 auto spelled_out = []() -> int& { int i = 123; return i; };<br>
                                       ^<br>
is_it_ref.cpp: At global scope:<br>
is_it_ref.cpp:4:9: error: invalid user-defined conversion from<br>
‘<lambda()>’ to ‘int’ [-fpermissive]<br>
 int d = deduced;<br>
         ^~~~~~~<br>
is_it_ref.cpp:1:23: note: candidate is: ‘<lambda()>::operator int<br>
(*)()() const’ <near match><br>
 auto deduced     = []()         { int i = 123; return i; };<br>
                       ^<br>
is_it_ref.cpp:1:23: note:   no known conversion from ‘int (*)()’ to ‘int’<br>
is_it_ref.cpp:5:9: error: invalid user-defined conversion from<br>
‘<lambda()>’ to ‘int’ [-fpermissive]<br>
 int s = spelled_out;<br>
         ^~~~~~~~~~~<br>
is_it_ref.cpp:2:31: note: candidate is: ‘<lambda()>::operator int&<br>
(*)()() const’ <near match><br>
 auto spelled_out = []() -> int& { int i = 123; return i; };<br>
                               ^<br>
is_it_ref.cpp:2:31: note:   no known conversion from ‘int& (*)()’ to ‘int’<br>
<br>
<br>
On Thu, Jul 13, 2017 at 6:55 AM, Matthew Urquhart via cfe-dev<br>
<<a href="mailto:cfe-dev@lists.llvm.org" target="_blank">cfe-dev@lists.llvm.org</a>> wrote:<br>
> Hiya,<br>
><br>
> I ran into this (presumably) undefined behaviour today, and wonder if it's a<br>
> bug or expected. My app was coded similarly and ran correctly on macOS/LLVM<br>
> version 8.1.0 (clang-802.0.38) but not Ubuntu14.04/gcc-4.7.3-12ubuntu1<br>
><br>
> In the case of this code, it's invalid since the lambda returns a reference<br>
> to a temp object. My bad, I'll fix it. Seems the compiler could've warned me<br>
> though :)<br>
><br>
> Compiler warns when explicitly specifying the return type of the lambda<br>
> using `->` operator, but not when implicit. Is this expected or a bug?<br>
><br>
> Thanks in advance,<br>
> Matt<br>
><br>
> // Minimal test case:<br>
><br>
> #include <functional><br>
><br>
> #include <iostream><br>
><br>
><br>
> void print_stuff(std::function<const int&()> f) {<br>
><br>
>     std::cout << "stuff is: " << f() << std::endl;<br>
><br>
> }<br>
><br>
><br>
> int main(int argc, char *argv[]) {<br>
><br>
>     print_stuff([]() {<br>
><br>
>         int i = 123;<br>
><br>
>         return i;<br>
><br>
>     });<br>
><br>
> }<br>
><br>
><br>
> _______________________________________________<br>
> cfe-dev mailing list<br>
> <a href="mailto:cfe-dev@lists.llvm.org" target="_blank">cfe-dev@lists.llvm.org</a><br>
> <a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev</a><br>
><br>
<br>
<br>
<br>
--<br>
GCS a+ e++ d- C++ ULS$ L+$ !E- W++ P+++$ w++$ tv+ b++ DI D++ 5++<br>
The Tao of math: The numbers you can count are not the real numbers.<br>
Life is complex, with real and imaginary parts.<br>
"Ok, it boots. Which means it must be bug-free and perfect. " -- Linus Torvalds<br>
"People disagree with me. I just ignore them." -- Linus Torvalds<br>
</blockquote></div>
_______________________________________________<br>
cfe-dev mailing list<br>
<a href="mailto:cfe-dev@lists.llvm.org" target="_blank">cfe-dev@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev</a><br>
</blockquote></div></div>