Moving to C++11


#21

Okay, here is another, style question.

Without auto there is only one style of declaring variables.
With auto there are two styles, because auto can’t replace all explicit declarations.

I dislike this ambigity, but it’s not very bad.

In your opinion, where auto shall be used and where shan’t?
Do you have some strict rules that can be enforced in guideline?

This criteria is very subjective:


#22

See also: C++ Core Guidelines.


#23

I tried to read it some time ago. It’s quite big, I am on 25% now.
Did you want to accent some part of this document?


#24

It isn’t a stylistic issue.
It’s correctness, type safety, and maintainability.

I think the same as Herb Sutter: if you want to track a type you should use auto, if you want to stick with a type you shouldn’t. Tracking is the common case.
Also auto can be used in other cases to keep things DRY, like new, static casts, example:

auto user = static_cast<Node*>(eventData[Use::P_USER].GetPtr()); // type already mentioned in the static cast

Watch the video I linked, it has excellent examples of cases that not using auto will cause problems.

"This criteria is very subjective:"
This isn’t subjective at all, it’s a fact.

int f();
long x = f(); // f() returns int, we want long. using auto here will result int

#25

long and int is same type :slight_smile:


#26

Wrong, it’s compiler implementation defined and the requirements are different:
http://en.cppreference.com/w/cpp/language/types#Integer_types

So you just created a very subtle bug that may or may not happen to some users on different compilers (including different versions of the same compiler).


#27

Ok, I posted answer above already. I expect one type, but function return other. Complier (VS at least) will warn. But if a will using auto, I would not notice this problem


#28

they won’t warn because there’s no truncation unless they’re implemented as different sizes. (and even then only VC++ by default)

This was an example for not using auto anyway, when the intention is to stick with long.
(the bug is something else - assuming long is same type as int)


#29

Ah, ok I understood what you mean


#30

Okay, let’s imagine. One guy insist that the type of some variable shall be explicit. Another guy insist that type of some variable shall be auto. If your criteria is a fact, please logically solve this argument.

const String::operator std::string() { /* cast to std string here with copying */}
const String& Node::GetName();
...
const auto& name = node->GetName(); // vs const String& name
if (name == "Player") { ... }

One guy said that explicit type is better because if we change String to const char* the nasty bug will appear:

if you don’t want to use the type foo returns you shouldn’t use auto.

Another guy said that auto type is better because if we write explicit String and change String to std::string in function signature, the redundand copying will appear. Also, code is generic enough to work with different types of strings. According to all guidelines, auto shall be used here.


#31

In practice code will be contributed to Urho using the contributors preference, and it is unlikely an issue will arise unless they are going full-auto and it has become hard to read. If there is a bug identified, the contributor will surely feel compelled to correct the bug.


#32

That’s the problem.
Some guys like me will probably almost avoid auto in commits.
Some guys like @1vanK will use auto somewhere for long types.
Some guys like @Enhex will prefer using auto in declarations.
Then, code may stay readable enough.
However, code will be a mess of different styles. That’s ugly.
Urho3D has so nice style now, because it was written by single person in a languare that has no auto.
It’s hard for me to admit that this will be lost.


#33

Looking through the urho codebase, I don’t see many instances of where code would be improved by auto. For entertainment value, an automated tool can be used to put that to the test (eg, https://github.com/steveire/clazy).

Moving on to other C++11 features, I think brace initialization is clearer and more convenient when extended with initialization_lists. I think typedefs should be upgraded to use using. enums upgraded to enum classes (as long as scripting doesn’t choke on it).

I think an upgrade to use move could be worthwhile. With the change to c++11 we could maybe re-evaluate using our custom containers vs the stl.

I would probably avoid lambdas for the most part.


#34

I hate such disputes, trust me… sigh :weary:

There is interface-oriented AAA (yep, I’ve read Sutter and his articles).
There is type-oriented… huh, let’s call it 98

AAA is nice-looking. 98 is bulky.
AAA is theorectically perfect. 98 has theoretical pitfalls.
Yes, they are more theorethical than practical since function signature is rarerly changed.
You have much more chances to inject bug e.g. in logic or catch a problem with implicit casting from SharedPtr to T*.

98 is used for all legacy code. AAA is used nowhere.
98 is simpler to understand. AAA is more puzzled.

I don’t say that AAA has no benefits.
However, I think that benefits of 98 cost more than benefits of AAA when we are talking about Urho (old big project).
If we were talking about new small project, AAA’d be better.
If we were talking about new big project… questionable. Maybe I have to try big AAA project at some point.

Then we will have to write some migration script to Find&Replace old enums with new ones in client (and Urho) code.

With the change to c++11 we could maybe re-evaluate using our custom containers vs the stl.

Unsure that it’s good idea. This will break a lot of code unless wrappers over STL are written.


#35

Guaranteed binary size is to me still the biggest advantage of the custom containers, which allows storing them “inside” Variant. Moving to STL containers the only safe thing to do would be to always heap allocate them instead, which would add some overhead. I don’t pretend that the custom containers are a performance advantage nowadays, and if I was starting a new engine today I would likely avoid them, just to reduce maintenance cost / codebase size / possibility of errors.


#36

In https://github.com/1vanK/Urho3DSpriteBatch/blob/master/SpriteBatch.h I compared Urho3D::PODVector vs std::vector, and Urho3D::PODVector won :slight_smile:


#37

However, your containers are much faster than STL ones in debug mode.
It’s getting too hard to debug something when you have 5 FPS on complex scene with these safe iterators.


#38

Does the iterator debug level help, though?

https://msdn.microsoft.com/en-us/library/hh697468.aspx


#39

I haven’t managed to make it work last time when I tried it. It was long time ago.


#40

What about STL implementations which aren’t bundled with the compiler? Like EASTL (haven’t looked into it myself).

Boost.Container also provides some nice optimized containers.
I benchmarked its small_vector and it’s very fast for its purpose:


(source: https://github.com/Enhex/Benchmarks/tree/master/boost%20small_vector)
Tho I’m getting off topic.

That’s because they don’t provide any debugging information, which defeats the purpose.
I know that in my code I had to replace things like HashMap with std::unordered_map to be able to debug their content.

it’s like saying:

int main() {
  while(true) {}
}

is the fastest game engine. It’s fast because it doesn’t do anything useful.