@@oriyadid for backward compatibility it will probably not be fixed. but hoppefully you will have a new Wnrvo coming soon.
@sqlexpАй бұрын
It requires something like data-member RVO, where the Lifetime object is constructed in place at the Lifetime member of std::optional/std::expected, but those types will need to provide some standard declaration (maybe a concept) to mark the designated data member and some special constructor that assumes the designated data member is initialized when the constructor is called. That data member needs to be destroyed last if an exception is thrown during data member initialization in that constructor.
@sqlexpАй бұрын
Some additional support will be needed if the data member is in a union.
@N....5 ай бұрын
6:19 you can just write `std::in_place`, no need to write the extra `_t{}`
@josephnyu5 ай бұрын
I think Jason missed a point, for functions returning expected it is very likely to have branching, and in that case RVO will use move constructor most of the time anyway. The same can be said for optional (indeed if your code always return a Lifetime then the return type should be Lieftime and not optional)
@LesleyLai5 ай бұрын
This makes me appreciate Rust's "move by default." While annoying in other areas, that semantics means the compiler can optimize this kind of code well and we don't need to think about this issue
@kuhluhOG5 ай бұрын
with the difference that the value gets moved (e.g. 10:05)
@niklkelbon36625 ай бұрын
)) rust has no RVO and copy elision, values will be moved (memcpy) every time. So, C++ better here
@joestevenson55685 ай бұрын
@@niklkelbon3662C++ is only better here is written perfectly. Rust - as usual - has vastly superior default behav
@TRex2665 ай бұрын
@@niklkelbon3662right, but for something like a string memcpy is not really an issue..? You only copy the pointer, not the buffer
@tiagocerqueira94595 ай бұрын
@@niklkelbon3662 llvm does RVO, but the language and Mir can't guarantee that
@axelBr15 ай бұрын
Self taught C++ in early 2000s, and have started to use it again, after work took me away from it. Have recently heard of RVO and have just started incorporating std::optional into a project I'm working on, as being able to say that there is no value to return is really helpful. And then I saw this.
@Evan490BC5 ай бұрын
Run away while you can!
@DominicDW85 ай бұрын
Well, don't be too sad. It's oftentimes worth using the "inefficient" way to get more readable code. The "issue" shown in the video is certainly quite interesting, but also quite certainly not a deal breaker for performance in the vast majority of use cases.
@DamianReloaded5 ай бұрын
This seems like something the compiler could optimize for.
@japedr5 ай бұрын
Except when it cannot... as shown in the video. Any class without a trivial destructor is affected by this, and that includes all classes with a vector or a string as a member.
@Yxcell4 ай бұрын
@@japedr But isn't the reason why Jason's code with the extra constructor/destructor calls couldn't be optimized out was due to the fact that the all called print() ? When I checked out the Compiler Explorer instance that Jason linked in the GitHub page for this episode, I removed the body of the print() function and the resulting assembly became that of a barebones program. I'm kind of a noob at C++ so I might be missing something here.
@MantasXVIII4 ай бұрын
@@japedryeah but haven't you heard? The compiler knows better than you. Premature optimization is the root of all evil.... And other such nonsense from people who've worked on a serious project
@AtomicAndi4 ай бұрын
seems like it optimizes (prematurely) for an empty optional!?
@Muzzleflash19904 ай бұрын
It does optimize it all. But it ofc not remove the observable side effect of printing.
@VoluneAneline5 ай бұрын
I suspect a lot of people will write "return std::unexpected{"oh no!"};" and that will prevent RVO anyway (at least when I tried). I guess we will (again?) rely on tooling to fix these issues. If the compiler cannot optimize in the first place for most cases.
@gwendolynhunt24934 ай бұрын
Thanks Jason, now I have a couple hundred APIs in several libs I need to revisit. Really, an excellent YT. You do good work.
@mjKlaim5 ай бұрын
Good to know, thanks for pointing this!
@dookshi4 ай бұрын
Haha, I regret no episode of yours! In fact, you did such a good job explaining RVO so far that I did not find anything you did not already cover implicitly. You just made it explicit now. Excellent series!
@MatthewWalker04 ай бұрын
I have thought about this a few times. And, every time I imagined what the "fewer moves" code would look look, it seemed like a premature optimization making the code less readable; it looked more like C89 code with the variables and return value declared at the beginning of the blocks. Much cleaner to just put a couple `if (bad) return std::nullopt` around.
@erikgrundy4 ай бұрын
I know C++, kind of, but haven't actually used it in any real applications, so I don't really experience the issues I sometimes see talked about, like this one. So for those more experienced than me: how often do these sorts of things end up mattering? A lot of online C++ content loves to talk about small ways of squeezing a little bit more performance out of your code. These sorts of micro-optimisations don't strike me as the thing that will make the difference between your code being acceptably fast or not. E.g. the specific problem presented in this video. I would think that the majority of the classes you write in an application don't have anything fancy going on in their various constructors, assignment operators, and destructors. So I wouldn't think that this would make an enormous difference. Would it make your application faster? Probably. But I would think that the things to target when it comes to optimisation would be less granular. I'm happy to be wrong, so feel free to challenge my assumptions. I'm genuinely looking for an answer for why the C++ community seems focused on optimisation to such a degree.
@stevenfranzen21614 ай бұрын
I think this is just inherent to C++ as a language where you can almost always avoid paying costs like execution time and/or memory usage, if they aren't strictly needed. You're entirely right that this kind of thing will not typically matter to a specific application, but on the other hand, as a library writer you don't want to force unnecessary pessimisations on your users. And as a language designer you want to make it easy for library writers and other users to avoid those. I think that's at the core of Jason's criticism here. Although I don' t teach programming, the only thing I would ever teach about optimisation is that you just have to profile your code if performance is a concern. Especially with C++, it's almost impossible to predict what an optimising compiler will produce, so it's better to observe general guidelines for readable, maintainable code and avoid premature optimisation.
@JanFlunher4 ай бұрын
Definitely not as good as some people commenting under these videos, but having used C++ in personal projects and work...I don't think you think about the bigger picture. The underlying object could represent anything and be called from anywhere. Once this function is called in a loop in some hot path, the performance impact is non-negligible. I remember refactoring some code and overlooking that I passed a copy of a vector to some lambda by mistake; or something similar. Rookie mistake. Didn't realise it until I benchmarked and found out that the code is like 5x slower. Might sound like a lot, but if it takes 50ms instead of 10ms, you probably won't notice until you actually benchmark it. Returning a copy from optional/variant/... like shown in the video could have the same impact. Moving instead of RVO might not be that big of a problem, but still - it's unnecessary. I'd say that the feeling that the C/C++ community is more focused on optimisation is because that's just the kind of stuff that's mostly written in C/C++. There isn't much of a reason to use it for other stuff; or rather there are better languages/tools (that might just be a wrapper over some C/C++ libraries and therefore the "hot paths" being performant anyway - so why make your life difficult?).
@erikgrundy4 ай бұрын
@@JanFlunher but you only discovered your error when benchmarking, which i think is the right time. i don't dispute that this *could* have a performance problem, and indeed i think it's not unreasonable to use the faster version in all cases - it's not notably less readable. my observation is more generally about the c++ community, who (in my observation) will often claim that you should always prefer x to y in all cases, without considering that y may be more maintainable, readable, etc. c++ is used in lots of high performance scenarios. but it's also used in places where code readability and correct abstractions are important. this was one of the core principles of c++. and yet i see people reject an idea that improves readability solely on the idea that it *might* worsen performance. you can only know that by testing it, rather than assuming that it will make your code unbearably slow.
@JanFlunher4 ай бұрын
@@erikgrundy Yes, I discovered it, but I don't always benchmark all of my code. And in a big code base, that might be riddled with stuff like this, it will definitely become a problem for not-so-obvious reasons. Small performance issues become big ones once they come in herds. Can't speak for the community as a whole. But I personally like to always write the most performant code in most cases, because it's a good training for when it actually matters...and saves a lot of headaches later. Though the "most performant" is highly subjective obviously. Adding an explicit "std::optional(...)" isn't a deal breaker for me here. Doing everything with template meta-programming is a big nope. I'm still a fan of readable code. The thing in this case is that not only it *might* worsen the performance, but it always *will* and it's not very obvious. If it's negligible or not, depends.
@cppweekly4 ай бұрын
I don't consider this a micro optimization, I consider it a matter of understanding what your tools are doing. This is the kind of thing that, once I understood it, I got about a 100x performance improvement in my scripting engine. It was a kind of "death by 1000 cuts" In my experience this is where most performance is lost in a C++ program, but people don't think about it and instead do things like inline assembly to try to get an extra bit of performance out. kzfaq.info/get/bejne/orSedaipqdWyg4U.html
@Psy45Kai5 ай бұрын
I think there is a problem with the test setup here: The Lifetime class always have an IO side effect. These cannot be optimized away by the compiler properly! But classes following the rule of zero might not be affected ☝️ I would like to see a follow-up with optional and optional analysing the asm.
@Muzzleflash19905 ай бұрын
You have to be careful to distinguish the guaranteed "copy elision" conditions with general optimization. In fact, if the guaranteed copy elision rules apply then the side effect MUST NOT happen due to the delayed materialization. Suppose you did: Lifetime x = f() where f() function returns a Lifetime (not inside optional or anything) simply by: return Lifetime{42}; then there MUST only be single construction since C++17. The problem is none of these guaranteed copy elision rules apply here. The constructor for optional or the others, take a reference (&&) to the contained type forcing the materialization of an extra Lifetime. So in terms of language semantics it must create the object. You are then right, that under the as-if rule the compiler could automate the copy away, if it did not have a side effect.
@aniketbisht28235 ай бұрын
This is really unfortunate. I think you should discuss this with Arthur O Dwyer. He has proposed many papers on topic of returning objects (and implicit moves) and has also given talks on this subject. This seems like a missed optimization opportunity as far as core language is concerned. This case is very similar to the C++17 guaranteed copy-elision. We can generalized that approach to elide copying any object/value that is used to construct the returned object (given the converting constructor of the returned type itself is not explicit).
@jirihavel97664 ай бұрын
It's not just missed optimization. All these prints are observable side effects that optimizer can't remove. We may need one of those : - print that can be removed by the optimizer (must be explicitly allowed by the standard) - removing any side effects from copy constructors (i.e. copy constructor is only allowed to do copying) This however leads deep into the "undefined behavior" territory. - explicitly allow copy ellision or return value optimization in these situations. All are decisions in the standard. Compiler authors aren't allowed to do this on their own.
@Muzzleflash19904 ай бұрын
To the people thinking this is about RVO (copy elision): it is not. And by the way RVO works fine (which is why you don't see extra outputs from an internal copy of Lifetime when the optional is copied out as a return value: because it is not). The problem is when you have a Lifetime object but what you really want to return is an Optional which implicitly causes the Optional constructor to be called with a Lifetime. As this point (language-wise) the Lifetime must be materialized because the parameter is a glvalue. So Lifetime{42} is materialized as the parameter. Then the inner Lifetime is move constructed from that. The issue here is nothing to do with RVO, but with calling functions (constructors) to make a class B by passing an A and expecting the construction of A to be elided; which is won't. The resulting Optional is perfectly NVRO'ed (which is actually an optional optimization) in the first example; or (unnamed) RVOed out in the remaining cases. And RVO has nothing to do with the constructor/destructor being trivial or not (if elided those copies never existed at all!). For example: godbolt.org/z/fMKzxEbj6 . But can't the compiler optimize it away anyway? In many cases: probably sure. What it can't optimize away is the observable side effect of outputting.
@sirhenrystalwart83034 ай бұрын
When is it not allowed to elide the side effect of printing? RVO works fine in all these cases if your remove the optional.
@Muzzleflash19904 ай бұрын
@@sirhenrystalwart8303Basically, eliding is allowed (and required) when returning unnamed temporaries of the same type as the return value. If you remove the optional then RVO triggers since you are just returning the Lifetime (prvalue) you construct: no intermediate is constructed; only the final value. As the R in RVO hints it works for Return values, but following has nothing to with RVO. The problem is that binding references to temporaries force the construction of the referred to object. When you return an Optional you have to go through the constructor of optional (any function really) that has a named parameter compatible with the inner value. These parameters are references that bind to the prvalue, and by the spec, then the value must be materialized, and thus the printing must be shown.
@PaulMetalhero4 ай бұрын
+1 for the cppreference dark theme!
@VictorYaremaАй бұрын
Awesome episode. I don't regret watching it. Now I can better remember about this specific pitfall. The worst emotion now is a frustration caused by so called "standard" which was supposed to make everyone's life easier instead of making really bad things harder to spot.
@FixedTypo5 ай бұрын
We often face the situation that our objects are returned by some sort of factory function before being placed into the optional, etc. We came up with a solution to avoid moves here. Basically all of these classes have constructors overload that participate if the contained value is constructible from another object. So we created a helper class that holds a callable and defines a conversion operator to the result type of the callable by calling it (so we get rvo there). With this class, a helper function and a lambda wrapping the original function call we were able to emplace the return value of the function directly into an optional. We did introduce a macro as we did not find it too readable though.
@StanleyPinchak4 ай бұрын
Is this similar to the superconstructing super elider technique that Arthur O'Dwyer outlined in his blog?
@FixedTypo4 ай бұрын
@@StanleyPinchak Yes it is actually equivalent to the class with_result_of_t shown in Arthur‘s blog. After hiding the verbosity of invoking the constructor of std::optional with the class and the lambda behind a macro MAKE_OPTIONAL it is actually quite „pretty“. Usage looks like this: MAKE_OPTIONAL(LifeTime{42}) MAKE_OPTIONAL(createLifeTime()) The nice thing is, that you can get direct member initialization too.
@volta9485 ай бұрын
What about std::make_optional?
@furuthebat5 ай бұрын
``` std::optional get_value() { return std::make_optional(42); } ``` this works. ``` std::optional get_value() { Lifetime l; return std::make_optional(l); } ``` Same result as with copy-ctor
@bruderdasisteinschwerermangel4 ай бұрын
afaik make_optional simply calls the constructor of T with all arguments forwarded to it. So in the first case you're actually calling Lifetime(int) and in the second Lifetime(const Lifetime &), I.e. the copy constructor
@sadunozer22414 ай бұрын
I just want you to, I don’t know… regret watching this episode Jason Turner breaks 2024
@VictorYaremaАй бұрын
As a result we don't regret watching the episode. We regret that we have to deal with C++ ugliness.
@davidfong4 ай бұрын
9:47 did you mean to say "more and more implicit conversions" instead of "explicit"?
@cppweekly4 ай бұрын
Yes, I did mean implicit
@avramlevitter61505 ай бұрын
Something I'm noticing: your Lifetime class is great at finding out when you might be calling an expensive operation that can't easily be optimized out. When you're using this for a pure value type this all becomes a non-issue. If you have a complicated type, it might be worth seeing if there's an empty state that can be defined and return that (e.g. an empty vector). If you have a complicated type, that's expensive to move, and can't easily have an empty state and you want to add the empty state by sticking it into an optional... then yeah, this is a problem. Personally I haven't run into it yet but that doesn't mean it's not someone else's use case.
@michaelwillett70844 ай бұрын
Ah, I've run into this problem before trying to write unit tests for my own version of std::expected a couple years ago! The problem I ran into is the fact that you are creating an object like Lifetime to track your constructors and destructors / move operators. In doing so, these functions have side effects that the optimizers will explicitly NOT remove, forcing the duplicate constructors and destructors. If you don't have the observers, and just check the pure ASM, then you realize the RVO can kick in and you don't get the extra function calls. I admit that this doesn't help in cases where you do have classes with custom move assignment / construction / destructors, and by definition we end up with the behavior outlined in this video. It doesn't change your point, but there are a lot of cases with default constructors that the simplified code will run just fine with no additional overhead.
@Lol-ld2lu4 ай бұрын
I don't think that calling a move constructor once is worse, than throwing an exception. Move constructor or operator= by their intent should be lightweight. This situation however is not great, but neither as bas as you describe it.
@AdamSzaj4 ай бұрын
Great episode!
@kuhluhOG5 ай бұрын
Quite frankly, if it comes to exceptions, I use them for truly exceptional things. But errors are not necessarily exceptional. In quite some cases they are even expected (or at least something which you SHOULD expect). And exceptions are ergonomically REALLY stupid for that and express the intent just way worse than something like std::expected. Disconnecting the "happy" and the "error" path is not always the good thing to do. And expressing programmer intent in code is for 99% of code more important than efficiency, at least imo.
@redcrafterlppa3034 ай бұрын
Any generic result container stands and falls with the level of template deduction the language is capable of. Needing to explicitly type a deeply nested type is a nightmare. I don't know how good cpp is but java has one of the worst. It brakes after 2-3 levels of "templates" requiring a hint in order to compile.
@X_Baron5 ай бұрын
It was probably a mistake to make these part of the standard library, instead of language features. Interesting to see if anyone comes up with a workaround.
@MatthewWalker04 ай бұрын
And we could also have built-in arrays that don't have a bunch of pitfalls...
@N....5 ай бұрын
Great video. It's weird that the explicit vs non-explicit constructors seem to be reversed, we can't just write `return {std::in_place, 1};` for best results, but writing `return Lifetime{1}` is allowed and does the wrong thing. I am curious what the committee reasoning is for this strange behavior, I guess maybe they were worried about if the wrapped type also took `std::in_place`
@az-kalaak62155 ай бұрын
well, to be honest I always use optional / variant as a way to return when exceptions is not needed, but code can still fail. but I don't mark the parameter as explicit as those error structs that I use are only used in this context. so no issue for me, but still interesting!
@Qazqi4 ай бұрын
This strikes me as something that could potentially have been dealt with via a more explicit Some(foo) and None design for these container types, but I haven't thought through it to pick out whether that's true.
@FlaviusAspra4 ай бұрын
I loved the end! Makes me subscribe.
@pancio-ciancio2 ай бұрын
Therefore forcing to explicitly construct objects (as convention) can prevent many of this kind of errors?
@cppweekly2 ай бұрын
Yes "mark single parameters explicit" has been a best practice for longer than I've been programming in C++. Why doesn't the standard's committee follow this best practice?
@QuickNETTech4 ай бұрын
I find it interesting that, at 6:48, if you had used an auto return type you would've gotten the behavior you're looking for just coincidentally. Dunno if that's a meaningful observation but I think it makes me want to keep using auto, especially since I don't want to unnecessarily type the return type twice personally.
@piggy84354 ай бұрын
Would love if you could make a video on book recommendations for C++ in 2024
@johnymag6664 ай бұрын
Is there a compiler flag to get a warning for these scenarios?
@patlefofort2 ай бұрын
I run into a situation where I want to be able to return a struct wrapped with std::expected and initialize it with designated initializers but it's just impossible to do that and avoid copy or move. I just hope the compiler is smart and can optimize it.
@erroneum4 ай бұрын
I wonder how hard it would be for a compiler to implement a flag that explicitly says you want implicit conversions to standard library containers to fail when it would force an extra object. Obviously that wouldn't be standard compliant behavior, but that's the point of it being a flag (just like -fno-exceptions or -fno-rtti).
@TheDoomista4 ай бұрын
You could propose it as a part of profiles proposal, then it could be in the standard.
@bruderdasisteinschwerermangel4 ай бұрын
I guess this is what make_optional and the like are here for Just a shame theyre annoying to use because of just the way they look and also giving you horrible compiler errors when the ctor signature changes
@bruderdasisteinschwerermangel21 күн бұрын
What annoys me the most is that when using the make_ family of functions to create the object in place, you can't do aggregate initialization anymore... Nevermind the C++ designated initializers.
@cppweekly4 күн бұрын
Any of these "create an object inside of another object" things are a pain to work with efficiently and cleanly in C++
@bruderdasisteinschwerermangel4 күн бұрын
@@cppweekly yeah... I sort of accepted that I can either write ctors all day or do an unnecessary move
@garrettkajmowicz3 ай бұрын
If you didn't have the operations being performed in the various constructors, would the compilers be able to optimize those operations away?
@cppweekly2 ай бұрын
If the types being contained are trivial, then the discussion is irrelevant. See also: kzfaq.info/get/bejne/mNZ2ZK98tqjLcoU.html
@KillerMZE4 ай бұрын
This episode makes me feel better about my rampant use of raw pointers
@TsvetanDimitrov19765 ай бұрын
Would using some helper function, like make_optional, or make_expected fix this?
@TsvetanDimitrov19765 ай бұрын
@@BaardFigur it actually saves some typing sometimes. For example std::optional{std::in_place_t{}, 42} vs std::make_optional(42)
@dshvets15 ай бұрын
Wouldn't make_optional() be a better option?
@catsolstice5 ай бұрын
afaik make_optional() need a *public* constructor for the type, which can be an issue
@9uiop5 ай бұрын
Isn't that practically the same as he did with the one-liner? I guess template argument deduction cannot apply here, so make_optional is even more lengthy to type
@caiovinicius57452 ай бұрын
With expected is even worse! I'm using a static std::expected to construct my object, and having a private constructor, but this blocks me from passing std::in_place + Args, as the constructor is private... How can I apply rvo in this case? will "return std::expected(Class(args)); " work? I tried this and it called the move ctor...
@DerAlbi5 ай бұрын
Btw, RVO is still working! After all, the return value is not copied. What is copied/moved is the thing that belong into the return value. To say that RVO is disabled in these cases is wrong. But overall, you are not wrong with the video. It is not zero-cost abstraction if the actual use-case (and intended use) is not zero overhead. These features basically violate c++.
@xwize4 ай бұрын
If everyone is using it wrong, what does that say about the language
@MarekKnapek5 ай бұрын
Why there are no `make_optional`, `make_variant`, `make_expected`, `make_unexpected` factory functions? Just like `make_pair`. Function template argument deduction would kick in and I need to write less template stuff. Or is CTAD solving this? Or is thiss non-issue to begin with?
@nickkallen15 ай бұрын
This is a pretty annoying and significant limitation :(. Accidentally calling copy constructors is one of the major pitfalls of c++
@Mike-gs7eo4 ай бұрын
What happened to good defaults?
@cppweekly4 ай бұрын
This is C++
@aniketbisht28235 ай бұрын
6:38 the constructor taking std::inplace_t should also be conditionally explicit. It's tedious to write the whole type name. I usually prefer just returning the value_type of optional but as this video suggests, it might not be as optimal. So std::inplace_t constructor should be used for "non-trivial" value_types but that constructor shouldn't really be explicit.
@N....5 ай бұрын
You can just write `std::in_place`, no need to write the extra `_t{}`, but yes I agree it would be nice to just write `return {std::in_place, 1};`
@georgederleres848918 күн бұрын
I am curious whether we can apply the concept to a function that works with some lvalue. For instance assume we have this code : std::optional findUser(const std::vector& users, int id) { for (auto& user : users) { if (user.id == id) { return user; } } return std::nullopt; } Would it be more optimal to write : std::optional findUser(const std::vector& users, int id) { for (auto& user : users) { if (user.id == id) { return std::optional(user); // Constructing optional directly } } return std::nullopt; }
@cppweekly4 күн бұрын
reference_wrapper is trivial anyhow, so it's highly unlikely you would ever see a difference between these options.
@mix3505 ай бұрын
Cannot be catch using static analysis like a rule for clang-tidy?
@felixdombek60524 ай бұрын
Couldn't you just write `return {Lifetime(42)}`? Same for the std::expected case, just braces around `l` should work?
@Mr.Not_Sure4 ай бұрын
nope. Still extra object
@raymundhofmann76615 ай бұрын
Couldn't RVO be generalized to handle these cases with "nested" types? Not changing how i use optional etc. it's not worth it except in very rare cases.
@sinom5 ай бұрын
This really does seem like a language defect. I haven't looked through the papers for these facilities yet but surely they must have at least thought about this issue? There must have been some way that would not have made this an issue even if it qould have required more involved changes
@oschonrock5 ай бұрын
Oh dear.. that *is* quite unfortunate.
@pandacongolais4 ай бұрын
I learned something ! Again ! Although not sure I'll ever use it. Am I a bad C++ programmer for avoiding std:: as often as I can ? I place clarity and readability of code over anything else. "Ce que l’on conçoit bien s’énonce clairement. Et les mots pour le dire arrivent aisément" And I never felt any clarity in the use of std:: or the huge error cascades that are (were now days isn't it ?) generated when compiling typos.
@Tibor09914 ай бұрын
Yes, you are bad, you're writing C++ wrong and decided to cop out of your guilt by shifting the blame to the STL instead. I bet your code is not as clean and readable as much as you think it is and I'm pretty sure I'll bleed from my eye sockets if I ever see it.
@pandacongolais4 ай бұрын
@@Tibor0991 Thanks, time to become a team leader and tell others their code is bad
@Tibor09914 ай бұрын
@@pandacongolais that's literally what happened to my workplace (before he burned out and left). But srsly, "you don't pay for what you don't use" and the STL rolls by that.
@ujin9814 ай бұрын
I wonder if there are similar problems in Rust
@somerandompersonintheinternet5 ай бұрын
I do regret watching this episode.
@VictorYaremaАй бұрын
Don't be. It is not this episode's fault. It is the C++ "standard", which makes things so "great" and "intuitive".
@TheIgoorR4 ай бұрын
std::make_expected
@scatterarrowАй бұрын
This is the kind of stuff that makes one look for alternatives to c++ or even become a humble avocado farmer instead.
@scatterarrowАй бұрын
Although, I think in most cases, I simply don't care that the move constructor is being called. If I'm writing performance sensitive code, I'm going to be aware of this now. My intuition is to avoid expected there anyway.
@stefanalecu9532Ай бұрын
Why avocados?
@victotronics5 ай бұрын
Interesting issue. How about declaring the return object as "decltype(*this)"?
@Tibor09914 ай бұрын
Are you 100% certain sure that the print() function isn't making the compiler opting out of optimizations due to unoptimizable side effects?
@cppweekly3 ай бұрын
If the types are trivial it all becomes irrelevant, but people rarely go out of their way to make sure the types they use are trivial. If the types are not trivial, normal lifetime rules come into play, this I am 100% certain of. Check out this other video: kzfaq.info/get/bejne/mNZ2ZK98tqjLcoU.html
@MichaelLauerDr4 ай бұрын
Thanks for this insightful episode. Whenever I want to like C++, they‘re doing something like that. 😢
@TheNovakon4 ай бұрын
4:30 - return 42
@wrong10294 ай бұрын
What a mess
@VictorYaremaАй бұрын
Some people call it "standard". :(
@Ursus3105 ай бұрын
why did you return {42} and not just 42? same for expected just do a if (foo) return 42; else return "not foo"; should work and call the right constructor of explicit (once)
@xiao_sings5 ай бұрын
That’s crazy
@chengjiwei4 ай бұрын
Regretted watching this, hahaha
@anon_y_mousse4 ай бұрын
This is one of the things that I've always hated about C++ and that I've hopefully made better in my own language with more inference. I guess you could say in my language I infer all the things.
@FloodAnxiety4 ай бұрын
Yeah... I do regret watching this video. I went from, oh interesting, oh do I have problems I need to fix now? to oh wait... no, implicit brace initialization works, he had to make it explicit for it to not work... so... I think we are fine? Wait... what did I learn from this? I guess I gained worry that I am missing something?
@FloodAnxiety4 ай бұрын
Well, Print(const std::source_location& location = std::source_location::current()) was cool, I'd never seen that before.
@phenanrithe4 ай бұрын
No, I'm not.
@markusasennoptchevich20374 ай бұрын
That's why any serious library or project are written in C, not C++. You cannot expect what instructions compiler will generate without going insane with C++
@Debrugger4 ай бұрын
This language is insane lol
@leshommesdupilly5 ай бұрын
Virgin std::variant fan vs Chad void* + c-style cast enjoyer
@aniketbisht28235 ай бұрын
While using heap to allocate your object (that you're returning a void* pointer to). Yeah, right.
@marce38935 ай бұрын
always resort to the 20-50 constructs of C instead of learning newer useful constructs. make sure to dismiss them as idiomatic C++ complexity too... (don't take it personally, I never meant it. I understand your comment's meant to be a joke. I just want to say it's a bad joke :P )
@Evan490BC4 ай бұрын
@@marce3893You are right and wrong at the same time (in a nice Schrödinger-esque way) 🙂. C++ does automate many things *but* the idiomatic complexity of C++ is indeed insane!