Overall Strategy For Move-Semantics? [C++11]

Started by
26 comments, last by l0calh05t 7 years, 9 months ago

Probably most of them. I've never seen exceptions switched on in a game I've worked on, and standard RTTI has always been off (and usually replaced with some in-house system).

Advertisement

It used to be that many game platforms either didn't support exceptions at all, or not without a massive global performance impact. Now, there's one major game platform that doesn't allow you to disable them anymore!

IMHO c++ exceptions are still a bad idea from a code maintenance point of view though, which is why most projects still ban them.

C++ RTTI is almost useless though - it's basically a code smell...

But to pretend to be on topic, move semantics are actually a useful feature so will likely see introduction into game codebases over time :D

C++ RTTI is almost useless though - it's basically a code smell...


While there is certainly a lot of bad stuff you could do with RTTI what about for example std::type_index? It's certainly not without caveats but in the use case of for example a variant<...> or any type it seems to have some uses.
I'm honestly asking that question, by the way. I have never written either of these nor done the preliminary research for them but it's something that would interest me even if I never actively needed it.

The games I've worked on that needed unique references for types also needed them to be predictable across builds and across platforms, as they're used for serialization, network messaging, etc. Sadly it appears that type_info::hash_code is 'implementation-defined and may vary between executions of the same program' which makes it unusable, hence there usually being an in-house solution instead.

Can't comment on variants - I rarely encounter them these days in C++.

The games I've worked on that needed unique references for types also needed them to be predictable across builds and across platforms, as they're used for serialization, network messaging, etc. Sadly it appears that type_info::hash_code is 'implementation-defined and may vary between executions of the same program' which makes it unusable, hence there usually being an in-house solution instead. Can't comment on variants - I rarely encounter them these days in C++.

Yeah, hash_code isn't even guaranteed to return an unique value for different types in one run. While thats a normal thing for an hash function, it could still be a problem.

Having required a type system for my needs, I have come up with a unique solution, which gives arbitrary integer ids to types at runtime, but allows serialization via a fixed name value.

Also turns out that I'm using a variant-like class in my code for everything reflection-relation and the like. Its maybe not the best solution for everything (ie. storing variable values for my script system in an array of variant-instances is not the best idea). However for certain stuff it allows for a neat interface, which for me makes it viable at least in a few instances.

Are people really in the habit of moving every single time they don't need a variable anymore? Unless you're in the habit of doing that, option 4 is totally opaque and you wouldn't know to take advantage of it without reading the implementation. I think that's kind of in line with what Kylotan was saying.

Are people really in the habit of moving every single time they don't need a variable anymore? Unless you're in the habit of doing that, option 4 is totally opaque and you wouldn't know to take advantage of it without reading the implementation. I think that's kind of in line with what Kylotan was saying.


For me, using move semantics in the context of this is somewhat equivalent to using reserve on a collection class like vector. I just get some efficiency for a little bit of additional thinking/design overhead. So yes, whenever possible (in places where it can matter) I tend to move expensive temporaries (like string, vector, ...). However this mostly means that I adjusted my design. IE, where you would usually see something like this:
Foo foo;std::string& string = foo.GetString();string = "Test";string.append("whatever");
Or something along those lines, I would instead do:
std::string string = "Test";string.append("whatever");Foo foo(std::move(string));
I find the latter much cleaner, especially in non-fabriacted examples :D Obviously you could have done this before without the move-semantics, but it would have most likely invoked a copy operation for the content of the string.

EDIT: i think i misread your question. Anybody who is actively using C++11 surely has at least a basic understanding of how and when to use move-semantics. Anyone else wouldn't have that knowledge, so its probably a matter of who you target.

Are people really in the habit of moving every single time they don't need a variable anymore? Unless you're in the habit of doing that, option 4 is totally opaque and you wouldn't know to take advantage of it without reading the implementation. I think that's kind of in line with what Kylotan was saying.


For me, using move semantics in the context of this is somewhat equivalent to using reserve on a collection class like vector. I just get some efficiency for a little bit of additional thinking/design overhead. So yes, whenever possible (in places where it can matter) I tend to move expensive temporaries (like string, vector, ...). However this mostly means that I adjusted my design. IE, where you would usually see something like this:

Foo foo;std::string& string = foo.GetString();string = "Test";string.append("whatever");
Or something along those lines, I would instead do:

std::string string = "Test";string.append("whatever");Foo foo(std::move(string));
I find the latter much cleaner, especially in non-fabriacted examples :D Obviously you could have done this before without the move-semantics, but it would have most likely invoked a copy operation for the content of the string.

EDIT: i think i misread your question. Anybody who is actively using C++11 surely has at least a basic understanding of how and when to use move-semantics. Anyone else wouldn't have that knowledge, so its probably a matter of who you target.

I know this isn't important to the example, but I feel obligated to point out that a 12-character string isn't really a compelling use of std::move, considering the popularity of small string optimization.

My recommendation: Use the rule of zero wherever possible (should be 90% of your classes), i.e., don't define any of the special constructors/assignment operators but use the default generated ones instead. The few classes that do manage resources directly then get all five.

This topic is closed to new replies.

Advertisement