Re: Example of the perils of binding rvalues to const ref
On Thursday, 18 September 2014 at 00:53:40 UTC, Andrei Alexandrescu wrote: On 9/17/14, 12:28 PM, IgorStepanov wrote: I want to place Foo(1) to buckets[nn].key without postblit call. Compiler can't help me now, however, I think, It can do it without language change. File an enhancement request with explanations and sample code, the works. This will be good. Thanks! -- Andrei I think it's this one: https://issues.dlang.org/show_bug.cgi?id=12684 Kind of required when you requested emplace from rvalues: https://issues.dlang.org/show_bug.cgi?id=12628
Re: Example of the perils of binding rvalues to const ref
On Thursday, 18 September 2014 at 00:53:40 UTC, Andrei Alexandrescu wrote: On 9/17/14, 12:28 PM, IgorStepanov wrote: I want to place Foo(1) to buckets[nn].key without postblit call. Compiler can't help me now, however, I think, It can do it without language change. File an enhancement request with explanations and sample code, the works. This will be good. Thanks! -- Andrei Done: https://issues.dlang.org/show_bug.cgi?id=13492
Re: Example of the perils of binding rvalues to const ref
On Thursday, 18 September 2014 at 10:50:31 UTC, monarch_dodra wrote: On Thursday, 18 September 2014 at 00:53:40 UTC, Andrei Alexandrescu wrote: On 9/17/14, 12:28 PM, IgorStepanov wrote: I want to place Foo(1) to buckets[nn].key without postblit call. Compiler can't help me now, however, I think, It can do it without language change. File an enhancement request with explanations and sample code, the works. This will be good. Thanks! -- Andrei I think it's this one: https://issues.dlang.org/show_bug.cgi?id=12684 Kind of required when you requested emplace from rvalues: https://issues.dlang.org/show_bug.cgi?id=12628 Yes, your 12684 issue is a case of new 13492. I've tried to classify the problem and describe a danger cases.
Re: Example of the perils of binding rvalues to const ref
On Tuesday, 16 September 2014 at 15:30:49 UTC, Andrei Alexandrescu wrote: The function get_url() returns an rvalue, which in turn gets bound to a reference to const and implicitly passed to string_view's constructor. The obtained view refers to a dead string. When I saw this idiom used in D, I asked the same question: how long the temporary should survive? Does it work more reliably in D? It would be ok if it survives till the end of the scope, optimization opportunities lost this way should be small enough.
Re: Example of the perils of binding rvalues to const ref
On Tuesday, 16 September 2014 at 15:30:49 UTC, Andrei Alexandrescu wrote: http://www.slideshare.net/yandex/rust-c C++ code: std::string get_url() { return http://yandex.ru;; } string_view get_scheme_from_url(string_view url) { unsigned colon = url.find(':'); return url.substr(0, colon); } int main() { auto scheme = get_scheme_from_url(get_url()); std::cout scheme \n; return 0; } string_view has an implicit constructor from const string (see basic_string_view(const basic_stringcharT, traits, Allocator str) noexcept; in https://isocpp.org/files/papers/N3762.html). The function get_url() returns an rvalue, which in turn gets bound to a Forgive me my ignorance but get_url() returns a std::string (on the stack), so its address can be token. And iirc the explainer Scott Meyers explained once iff you can take its address its not a rvalue its a lvalue. So isn't the get_scheme_from_url() not simply holding a const ref to temporary? (which most compiler warn about) ...Or am I missing the point? reference to const and implicitly passed to string_view's constructor. The obtained view refers to a dead string. Andrei
Re: Example of the perils of binding rvalues to const ref
On Wednesday, 17 September 2014 at 08:52:58 UTC, Arjan wrote: On Tuesday, 16 September 2014 at 15:30:49 UTC, Andrei Alexandrescu wrote: http://www.slideshare.net/yandex/rust-c C++ code: std::string get_url() { return http://yandex.ru;; } string_view get_scheme_from_url(string_view url) { unsigned colon = url.find(':'); return url.substr(0, colon); } int main() { auto scheme = get_scheme_from_url(get_url()); std::cout scheme \n; return 0; } string_view has an implicit constructor from const string (see basic_string_view(const basic_stringcharT, traits, Allocator str) noexcept; in https://isocpp.org/files/papers/N3762.html). The function get_url() returns an rvalue, which in turn gets bound to a Forgive me my ignorance but get_url() returns a std::string (on the stack), so its address can be token. And iirc the explainer Scott Meyers explained once iff you can take its address its not a rvalue its a lvalue. So isn't the get_scheme_from_url() not simply holding a const ref to temporary? (which most compiler warn about) ...Or am I missing the point? reference to const and implicitly passed to string_view's constructor. The obtained view refers to a dead string. Andrei
Re: Example of the perils of binding rvalues to const ref
On Wednesday, 17 September 2014 at 08:57:36 UTC, Szymon Gatner wrote: On Wednesday, 17 September 2014 at 08:52:58 UTC, Arjan wrote: On Tuesday, 16 September 2014 at 15:30:49 UTC, Andrei Alexandrescu wrote: http://www.slideshare.net/yandex/rust-c C++ code: std::string get_url() { return http://yandex.ru;; } string_view get_scheme_from_url(string_view url) { unsigned colon = url.find(':'); return url.substr(0, colon); } int main() { auto scheme = get_scheme_from_url(get_url()); std::cout scheme \n; return 0; } string_view has an implicit constructor from const string (see basic_string_view(const basic_stringcharT, traits, Allocator str) noexcept; in https://isocpp.org/files/papers/N3762.html). The function get_url() returns an rvalue, which in turn gets bound to a Forgive me my ignorance but get_url() returns a std::string (on the stack), so its address can be token. And iirc the explainer Scott Meyers explained once iff you can take its address its not a rvalue its a lvalue. So isn't the get_scheme_from_url() not simply holding a const ref to temporary? (which most compiler warn about) ...Or am I missing the point? reference to const and implicitly passed to string_view's constructor. The obtained view refers to a dead string. Andrei [ Sorry for double posting, i must have double clicked on reply button accidentally. ] std::string returned from get_url() is a temporary and hence a rvalue. In fact it's address cannot be taken. It is often helpful to think of lvalues as things that can appear on the left side of assignment expression.
Re: Example of the perils of binding rvalues to const ref
BTW. About r-values: void fun(S s) { fun2(s); //pass s by value. } Now, compiler inserts postblit call before func2 call and dtor before end of fun. However, it is able to doesn't it, because after fun2 call, s isn't used. Thus, we can implement last postblit optimization: If compiler want to insert postblit, and object is't used after this postblit, compiler is able to doesn't generate postblit and last dtor calls. Is there limitation of this optimization? It may 90 percent to solve a r-value ref task.
Re: Example of the perils of binding rvalues to const ref
On Tuesday, 16 September 2014 at 15:30:49 UTC, Andrei Alexandrescu wrote: http://www.slideshare.net/yandex/rust-c C++ code: std::string get_url() { return http://yandex.ru;; } string_view get_scheme_from_url(string_view url) { unsigned colon = url.find(':'); return url.substr(0, colon); } int main() { auto scheme = get_scheme_from_url(get_url()); std::cout scheme \n; return 0; } string_view has an implicit constructor from const string (see basic_string_view(const basic_stringcharT, traits, Allocator str) noexcept; in https://isocpp.org/files/papers/N3762.html). The function get_url() returns an rvalue, which in turn gets bound to a reference to const and implicitly passed to string_view's constructor. The obtained view refers to a dead string. Andrei I would say the problem with this code is not so much in this usage example but in the implementation of string_view. Given string_view aims to be a non-owning reference to a string, it should prevent such assignments, which is pretty straights forward to ensure in C++11. Just delete the corresponding constructor: string_view( std::string ) = delete; This example, as stated in subsequent answers to your post, is no different from returning a const reference to a temporary. In this example, it just happens to be nicely hidden in the string_view implementation instead of being explicit: std::string const get_url( ) { return foo; } This has always been a no-no, and C++11 at least now adds the possibility to refuse such code via deleted functions. O.
Re: Example of the perils of binding rvalues to const ref
On 9/17/14, 2:01 AM, Szymon Gatner wrote: std::string returned from get_url() is a temporary and hence a rvalue. In fact it's address cannot be taken. It can in C++, after bound (implicitly!) to a const . That was the joke. That's why I'm opposed to adding the same conversion to D without restriction. -- Andrei
Re: Example of the perils of binding rvalues to const ref
On 9/17/14, 3:03 AM, IgorStepanov wrote: BTW. About r-values: void fun(S s) { fun2(s); //pass s by value. } Now, compiler inserts postblit call before func2 call and dtor before end of fun. Is the call to dtor part of fun(), or part of fun()'s call sequence? I've always meant to look at that. LMK if you know for sure. However, it is able to doesn't it, because after fun2 call, s isn't used. Thus, we can implement last postblit optimization: If compiler want to insert postblit, and object is't used after this postblit, compiler is able to doesn't generate postblit and last dtor calls. Is there limitation of this optimization? It may 90 percent to solve a r-value ref task. I think rvalues are already not postblitted into functions. Indeed more postblits can be optimized away for variables are are last used in a function call. Andrei
Re: Example of the perils of binding rvalues to const ref
On Wednesday, 17 September 2014 at 15:03:12 UTC, Andrei Alexandrescu wrote: On 9/17/14, 3:03 AM, IgorStepanov wrote: BTW. About r-values: void fun(S s) { fun2(s); //pass s by value. } Now, compiler inserts postblit call before func2 call and dtor before end of fun. Is the call to dtor part of fun(), or part of fun()'s call sequence? I've always meant to look at that. LMK if you know for sure. Dtor call is a part of fun(). I've written test code... struct Foo { this(int i) { } this(this) { } ~this() { } } void calledFunc(Foo probe) { } void main() { calledFunc(Foo(42)); } ... add a trace output into Statement_toIR::visit(ExpStatement *s) ... printf(ExpStatement::toIR(), exp = %s in %s\n, s-exp ? s-exp-toChars() : , irs-symbol ? irs-symbol-toChars() : NULL); ... and got: ExpStatement::toIR(), exp = probe.~this() in calledFunc However, it is able to doesn't it, because after fun2 call, s isn't used. Thus, we can implement last postblit optimization: If compiler want to insert postblit, and object is't used after this postblit, compiler is able to doesn't generate postblit and last dtor calls. Is there limitation of this optimization? It may 90 percent to solve a r-value ref task. I think rvalues are already not postblitted into functions. Indeed more postblits can be optimized away for variables are are last used in a function call. Andrei Yes, rvalues aren't posblitted. However I want and I can't deliver without postblits rvalue from first call (of constructor or factory function) through intermediate calls to the final place of stay. struct AA(Key, Value) { this(T...)(T args) { buckets.length = T.length; foreach (i; Step2Tuple!(T.length)) { alias key = args[i]; alias value = args[i+1]; size_t key_hash = hashOf(key); size_t idx = key_hash % T.length; auto e = new Entry(key_hash, key, value, impl.buckets[idx]); buckets[idx] = e; } } ... private static struct Entry { size_t hash; Key key; Value value; Entry* next; } Entry*[] buckets; } AA!(Key, Value) aaLiteral(Key, Value, T...)(auto ref T args) { return AA!(Key, Value)(args); } //somewhere in user code: auto aa = aaLiteral!(Foo, int)(Foo(1), 1, Foo(2), 2); //postblits aren't called. I want to place Foo(1) to buckets[nn].key without postblit call. Compiler can't help me now, however, I think, It can do it without language change.
Re: Example of the perils of binding rvalues to const ref
On 9/17/14, 12:28 PM, IgorStepanov wrote: I want to place Foo(1) to buckets[nn].key without postblit call. Compiler can't help me now, however, I think, It can do it without language change. File an enhancement request with explanations and sample code, the works. This will be good. Thanks! -- Andrei
Example of the perils of binding rvalues to const ref
http://www.slideshare.net/yandex/rust-c C++ code: std::string get_url() { return http://yandex.ru;; } string_view get_scheme_from_url(string_view url) { unsigned colon = url.find(':'); return url.substr(0, colon); } int main() { auto scheme = get_scheme_from_url(get_url()); std::cout scheme \n; return 0; } string_view has an implicit constructor from const string (see basic_string_view(const basic_stringcharT, traits, Allocator str) noexcept; in https://isocpp.org/files/papers/N3762.html). The function get_url() returns an rvalue, which in turn gets bound to a reference to const and implicitly passed to string_view's constructor. The obtained view refers to a dead string. Andrei
Re: Example of the perils of binding rvalues to const ref
On Tuesday, 16 September 2014 at 15:30:49 UTC, Andrei Alexandrescu wrote: http://www.slideshare.net/yandex/rust-c C++ code: std::string get_url() { return http://yandex.ru;; } string_view get_scheme_from_url(string_view url) { unsigned colon = url.find(':'); return url.substr(0, colon); } int main() { auto scheme = get_scheme_from_url(get_url()); std::cout scheme \n; return 0; } string_view has an implicit constructor from const string (see basic_string_view(const basic_stringcharT, traits, Allocator str) noexcept; in https://isocpp.org/files/papers/N3762.html). The function get_url() returns an rvalue, which in turn gets bound to a reference to const and implicitly passed to string_view's constructor. The obtained view refers to a dead string. Andrei Arguably, the issue is not const ref binding to an rvalue itself, but rather taking (and *holding*) the address of a parameter that is passed by const ref. If you want to *hold* that reference, it should be explicitly passed by pointer. That and having the whole thing neatly packaged in an implicit constructor. If you are doing something that dangerous, at the very least, make it explicit. I mean, the example might as well just be: std::string_view get_scheme() { std::string myString = get_url(); return myString; //Boom } Exact same undefined result, without binding to rvalues. I prefered your smoking gun of: const int a = max(1, 2); But again, the part of the issue here is the passing of references. If we made auto ref to mean pass either an existing object, or binds to an rvalue (at call site, not via template overload) and in the implementation, made the passed in argument considered a local variable as if passed by value you may not escape, then I'm pretty sure we can have our cake and eat it. Proper escape analysis would help too.
Re: Example of the perils of binding rvalues to const ref
On Tuesday, 16 September 2014 at 15:30:49 UTC, Andrei Alexandrescu wrote: http://www.slideshare.net/yandex/rust-c C++ code: std::string get_url() { return http://yandex.ru;; } string_view get_scheme_from_url(string_view url) { unsigned colon = url.find(':'); return url.substr(0, colon); } int main() { auto scheme = get_scheme_from_url(get_url()); std::cout scheme \n; return 0; } string_view has an implicit constructor from const string (see basic_string_view(const basic_stringcharT, traits, Allocator str) noexcept; in https://isocpp.org/files/papers/N3762.html). The function get_url() returns an rvalue, which in turn gets bound to a reference to const and implicitly passed to string_view's constructor. The obtained view refers to a dead string. That's a design mistake on someone's part. It shouldn't be legal to construct a view of an implicitly created temporary. Or at least not to escape it. As a more straightforward example of the same problem, I ran into a similar issue when creating constructor functions for a slice class I use for my own work. Those functions can't accept a const ref to a std::string, because you can end up with this: slicechar const wrap(std::string const s) { return slicechar const(s.c_str(), s.length()); } slicechar const s = wrap(abc); // s now aliases a discarded temporary I had to choose my overloads very carefully to avoid these issues. In short, these problems crop up the moment you start aliasing objects in C++. To be honest, I'm amazed that the STL contains something like string_view. What kind of guarantees is it supposed to provide?
Re: Example of the perils of binding rvalues to const ref
On 9/16/14, 11:26 AM, monarch_dodra wrote: Arguably, the issue is not const ref binding to an rvalue itself, but rather taking (and *holding*) the address of a parameter that is passed by const ref It doesn't do that. It holds pointer/length to the slice, which is different and distinct from the pointer to the string. -- Andrei