one hour til christmas and you know what that means. time to get high and try to fix someone else's c++ build

· · Web · 2 · 2 · 9

oh no this isn't compiling because it's declaring a unique_ptr<T> where T is incomplete and that only works under persnickety conditions i must not sufficiently understand because they seem to be met here

error: cannot bind non-const lvalue reference of type ‘std::vector<ArchiveEntry*>&’ to an rvalue of type ‘std::vector<ArchiveEntry*>’

wHATWD DOES TH AIS i am shooting my computer with a shotgun

ok wait i think this is saying it can't take a reference to a temporary value

which raises some questions, such as "why can't it generate an implicit temp local" and "when did c++ start caring about preventing errors like this anyway"

@eevee gotta give it credit for at least being a template-class-related error that isn't 800 pages long for no reason

@eevee around c++11 when the language standards folks decided that consistency and correctness were more important than quick hacks

(see also required use of 'typename' where it was previously optional)

@eevee my gut tells me that this is something that MSVC might let you get away with

@revenant oh i am absolutely sure of it, since presumably this builds for the main dev (who is on windows)

@eevee This plus the use of bare pointers points to some pretty severe code smells and it should probably be refactored anyway

which isn't to say that C++ is a great language for making issues like this easy to comprehend

Try using clang though, its errors tend to be more humane than g++

@eevee anyway sounds like it's trying to return a ref to a temporary? yeah that's no longer allowed in most cases

@eevee current 'best practices' (as of c++14) is to just not assign references that way and to return by value, and let move semantics handle the optimizations. But that requires building in c++14 mode to take advantage of. (but it's well worth it!)

@fluffy how would you "not assign references" here, short of changing the function signature?

also lol this project only started using c++11 features like last year

@eevee Is there some reason you can't change the function signature?

If you want to avoid relying on C++14 move semantics, an okay alternative is to make it an 'out' parameter, like

vector<foo>& func(...)


void func(vector<foo>& out, ...)

and assign to/manipulate out instead of returning.

(it isn't great from a code cleanliness standpoint but it gives you the perf characteristics while maintaining correctness.)

@eevee oh also even without C++14 the perf hit of copying a vector of pointers is basically no big deal unless it's like a couple million :P

(and most pre-14 compilers can optimize that construct to do something similar anyway)

@fluffy er i mean, i'm pretty sure the vector is being /returned/ by value just fine; g++ is complaining that i'm then passing it directly to a function that /takes/ it as a reference

@eevee Oh! That's never been valid. g++ just didn't complain about it.

@eevee IIRC, because the return value only exists on the return stack from the called function, which goes out of scope. The fact that g++ used to implement it in a way that made it work doesn't make it valid.

g++ got a lot more strict about it... I forget when, but long before c++11 was ratified.

@fluffy but it could be trivially given workable semantics, which would also make the whole point of reference arguments (passing values and not having to think about it) actually work

@eevee the C++ folks opted to solve the problems by making move semantics a thing, so that value-copies of temporaries are basically free.

@fluffy but that's only useful if i'm actually taking ownership of the data. it's a completely different problem

@eevee can you change the receiving function to take a const ref instead? those semantics are way better-established, I think (and might support what you're trying to do)

@eevee also disclaimer I am not a C++ language expert, I just used to use it a lot for high-performance embedded shit and got used to a lot of its quirks

@fluffy i just assigned the return value to a temporary by hand, that worked

@eevee yeah that's the easy approach and totally valid, especially if you just want to get it working rather than getting it "perfect"

like I said it's just a copy of a vector of raw pointers anyway, that's a really cheap operation

@eevee okay can I see the code? I might be making bad assumptions based on what I picked up from what you said earlier.

Show newer

@mpjeff no, passing by reference a vector returned from another function

@eevee Yep, sorry was slow and didn't see the other responses. Taking a nonconst ref expresses intent to modify. Passing a temporary means those modifications would not go anywhere, which isn't necessarily bad but is conceptually wrong in many cases.

@mpjeff so a const ref would actually work? that is wild and extremely poorly explained lmao

@eevee A const ref would work. Or passing by value (which is efficient with move semantics in this case). Agreed that it's poorly explained. Clangs error is slightly better but still not great.

Sign in to participate in the conversation

The original server operated by the Mastodon gGmbH non-profit