inout methods on a class are created like foo() & -> void. What is that ampersand doing there? #901
Replies: 11 comments 27 replies
-
This isn't really connected to UFCS. You get the same behavior whether you call with member syntax or non-member syntax.
|
Beta Was this translation helpful? Give feedback.
-
Thanks! This is a good question. As background, please read "Design note: Explicit discard" Consider your example, adding a comment:
If that This highlights the reason the above code is getting the error: It is modifying My thinking is that making this break is a feature, not a bug. Looking at the code above, is it correct that the code modified |
Beta Was this translation helpful? Give feedback.
-
Discarding isn't the same as destroying, so it doesn't affect the lifetime of |
Beta Was this translation helpful? Give feedback.
-
Right, "discard" refers to the value. This terminology (and syntax) does seem to follow the prior art in other languages mentioned in the design note. Note that I didn't have C#'s experience in mind -- this is not C# envy or anything. 😉 I independently arrived at the |
Beta Was this translation helpful? Give feedback.
-
BTW, I've just got to say that, even though ChatGPT does sometimes make mistakes(*), it's really impressive... "magical" as defined by Clarke, given that AFAIK no one, not even the AI designers, really deeply groks how it generates the output it does. Considering that Cpp2 is a small personal project that only existed on the web in the past year, and yet I get this (using ChatGPT 4): The link is the above-linked design note... cool. Update: Here's another... And this is just general-purpose garden-variety ChatGPT... it's not a dedicated Copilot that could have domain-specific training, and as far as I know it's not using any special plugin/gpt. (*) The first time I asked it what cppfront was, it gave a completely correct synopsis except that it said the compiler was written by Bjarne Stroustrup. 😆 In writing this example I tried it again, and this time it got everything correct. |
Beta Was this translation helpful? Give feedback.
-
I have the feeling we're actually mostly in agreement, but this is about a very different thing... To put it in the most simple way; Why does this code compile, but my example does not?
I want my example to behave the same way, I call a non-const method on an object that has plenty of logic on it and I want the destructor to only be called at the end of the scope. Ok, goal:
try 1: try 2: try 3: try 4: try 5: I'm out of creativity; how do I get a normal plain and simple void-returning, non-const method that is a member on a class? I think that is the same question as OP. How do I get a normal simple method I can call without qualifying as "dropping the result on the floor". |
Beta Was this translation helpful? Give feedback.
-
I'd say its correct, and API of
Then, discarding returned value is actually meaninful error. |
Beta Was this translation helpful? Give feedback.
-
This is the code from #900 (comment):
The relation between |
Beta Was this translation helpful? Give feedback.
-
Could perhaps evaluate to a boolean so you can "if (not a.connect()) ;" unless you're thinking there will be extra optional error information in the type?
On 23 December 2023 18:04:52 realgdman ***@***.***> wrote:
I'd say its correct, and API of connect need to be improved. To something like streams or files, where after operation you have to assign returned value and check if connection/subscription was successful.
status := a.connect("bar");
if(status.is_ok()) ...
—
Reply to this email directly, view it on GitHub<#901 (comment)>, or unsubscribe<https://github.com/notifications/unsubscribe-auth/AALUZQL6GYJXCGKQBDBJKWLYK4MMFAVCNFSM6AAAAABA5MCL22VHI2DSMVQWIX3LMV43SRDJONRXK43TNFXW4Q3PNVWWK3TUHM3TSMZVGAYDM>.
You are receiving this because you are subscribed to this thread.Message ID: ***@***.***>
|
Beta Was this translation helpful? Give feedback.
-
I'd argue that the lifetime there is very explicit, you've created an object on the stack and returned from the function, what else would/should a programmer expect? I personally don't want a language with lifetime extension via spooky action at a distance!
On 23 December 2023 18:21:52 Johel Ernesto Guerrero Peña ***@***.***> wrote:
This is the code from #900 (comment)<#900 (comment)>:
QCoreApplication app;
Client client;
client.connect(hostname, post);
return app.exec();
The relation between app and client is somehow implicit, perhaps through global state.
That doesn't play well with the local analysis of lifetimes.
—
Reply to this email directly, view it on GitHub<#901 (comment)>, or unsubscribe<https://github.com/notifications/unsubscribe-auth/AALUZQOSFV3EPBZOTDWJZCLYK4OL3AVCNFSM6AAAAABA5MCL22VHI2DSMVQWIX3LMV43SRDJONRXK43TNFXW4Q3PNVWWK3TUHM3TSMZVGA4TC>.
You are receiving this because you are subscribed to this thread.Message ID: ***@***.***>
|
Beta Was this translation helpful? Give feedback.
-
For people that don't have experience with Qt, it uses asynchronous setup for things like networking. When the async connect succeeds (or hard fails) you get a callback. At some event in the future. As a whole this means that the 'connect' instantly returns and since the 'app.exec()' is running the event-queue any sort of callbacks are (quite deep in the stack) run still in main(). Specifically, the 'client' object is still being used for those callbacks and all the things a client would actually do after the connection actually established. But obviously no compiler could possibly know about any of that via some simple static analisis. For starters, the entire system I just described is provided as a dynamic library. Without debug symbols. The code I linked somewhere in this thread actually calls a server and fetches data to look through it. It runs for about an hour with about a million callbacks being processed on the event queue before all relevant data has been found and it exits using the async method of Qt, calling the static |
Beta Was this translation helpful? Give feedback.
-
As seen in various bugreports, users are having problems getting their head around this one. I would argue it is because there are more usecases that need to be handled differently.
Bugreport #900, #839 and #792 are the ones I found.
Todays state;
cppfont has some cool code to determine last usage of a variable. For things like unique_ptr to implicitly work this has been used to add a std::move and do the thing that people expect.
This creates a problem, however, for instances of self-made classes.
Imagine:
The variable
a
is allocated on-stack. The core language has a very clear set of rules on the lifetime. Which raises the question, when is it ever Ok to generate a 'std::move' wrapper for usage of this variable?If 'connect' would be static, the above code would compile and actually the lifetime of
a
is still going to be till the end of the scope of main (as expected).So why would it be useful to add a std::move to the call of connect() ?
People have stated I can work around this by explicitly discarding the instance of 'a' at the end.
_ = a;
. It does feel like that misses the point, I have no intention of discarding 'a', it is supposed to live till the end of main(). (usecaseMaybe someone can link to the underlying reason for the existance of the std::move that is currently generated, so we can find a way to make all usecases work.
Thanks for reading!
Beta Was this translation helpful? Give feedback.
All reactions