Follow

what's the difference between

template<typename T>
auto add1(const T& a, const T& b)
{ return a + b; }

and

template<typename T>
auto add2(T a, const T& b)
{ return a += b; }

?

if you know the answer you are better than boost

Show thread

<type_traits>

static_assert(not std::is_same_v<
decltype(add1( short{1}, short{2} )),
decltype(add2( short{1}, short{2} ))
>);

Show thread

@namark Are you asking because you dont know, or as a riddle?

@namark well my C++ is a little rusty but functionally they should be relatively equivalent as far as I can tell. The second one may be a bit slower as it reassigns a variable with function level scope before returning it (and the scope therefore being dropped)... but aside from the second one being a little inefficient they should behave the same.

@freemo Not entirely sure about performance characteristics myself, good hunch that the differences are minor, but as far as I know add2 can actually be faster in some cases, if you take optimizations in consideration, and the reason it could be slower is not at all what you suggest, it usually is about construction and copying of objects.

There is a notable functional difference though, but not gonna hint too hard for now.

@namark id be curious to see benchmarks on it to suggest the differences. But yea i cant be 100% on the performance here, instinct tells me 2 is slower, but compiler magic can do all sorts of stuff I dont anticipate.

@pleb If you care about optimization you enable optimization

godbolt.org/z/TKdGv3ezv

so only difference is that can't pass const & in register across translation units, but if inlined there will be no difference, and LTO might fix it as well.

If you want to test for more complex classes, write one that counts constructions and run it with optimizations. A single instance will need to be constructed in both cases, but everything else the compiler can elide.

@pleb I gave the counter a try, and seems like I need {a+=b; return a;} for the optimizations to kick in, then for both cases there's a single copy in your example. If you pass a temporary as a first parameter though, you'll get a move instead of a copy with add2, and for that reason it's a general rule of thumb in modern c++: if you know you need a copy - pass by value. That said there is a bigger semantic difference there that I had in mind.

@namark

I very rarely use c, but if b had been globally scooped outside of the function, wouldn't that change things?

@freemo @pleb

@Pat nah no shenanigans like that, there is difference between the two as written.

@freemo @pleb

@namark Lately I've been programming a front end in React and I have been converted to the glory of Javascript

Javascript is much better than C++....

@mew27 understandable, after all javascript is C for pussies...

1 + {} = "1[Object object]"

@mew27 only if you are a true javascript fanboi

@namark @mew27

They're two different animals. C was developed for minicomputers that had teletypes and terminals connected to them. It was created so programmers didn't have to write everything in assembly language.

Javascript was written a couple decades later, shortly after the browser was invented, when personal computers were just beginning to become connected via the World Wide Web (WWW). They made Javascipt to run in the client browser so that web pages could be more interactive.

(But perhaps you just make the comparison so you could make the joke. :)

@Pat same philosophy, same quirky realization, same syntax, same primitives, same usage patterns... if you like one you'll like the other, sans prejudice.

@mew27

@namark @Pat @mew27 quirky realization? this is about C++, I believe. because it is, really, very quirky. but C was always consistent and have never had syntax sugar for pussies like C++.

@iron_bug to you any quirk of C is the word of god, so not sure what to argue here... just look up "quirks of C language"? Plenty of results.

Since we're doing arithmetic here suffice it to say:
unsigned short * unsigned short = insta-undefined-behavior-trollface

Also 2[a] is definitely syntax sugar for puppies only, I agree.

@Pat @mew27

@namark
Just looking at this abomination only reassures my belief that cpp is and always will be a meme

@hanken it does? I though it makes it cheaper... sans a rookie mistake on my part, see this thread
qoto.org/web/statuses/10683944

@namark
Well, I am no expert myself but add2 is a template function and a move constructor isn't guaranteed. So while RVO will take care of return values, in case of chained/nested function calls, e.g. add2(add2(a,b), b) temporaries will be created.

But this is moot, since you mention that this isn't the difference you are talking about.

I am eager to know what you have in mind.🙂

@hanken move not guaranteed as in T might not have a move constructor? Preposterous! I'm not changing my functions you fix your types :<

Anyhow, I posted my answer
qoto.org/web/statuses/10686274

@namark
Wow. This is good!
After looking at your answer I thought, sure, the return types might not be same. But I checked it and wow. add1 is not returning T! Only add2 does.

Thanks for sharing this.

@hanken no one ever expects arithmetic type promotion! This is why you can't in general implement/de-duplicate/replace operator+ with operator+=, and it's even bigger deal when you take into account types that use expression templates, or have bounds or measurement units associated with them at compile time.

Sign in to participate in the conversation
Qoto Mastodon

QOTO: Question Others to Teach Ourselves
An inclusive, Academic Freedom, instance
All cultures welcome.
Hate speech and harassment strictly forbidden.