C++11 Adoption stance

Discussion area about developing or extending OGRE, adding plugins for it or building applications on it. No newbie questions please, use the Help forum for that.
User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5292
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1278
Contact:

C++11 Adoption stance

Post by dark_sylinc »

This question keeps popping up from time to time, so we're going to address it here and make it sticky:

What's the stance on C++11 in Ogre?
It's not gonna happen for a long time. We won't adapt a language feature just because of fashion. There are multiple reasons for doing this:

  • Cross platform compiler
We support a lot of architectures. Not all of their compilers support C++11 yet or have matured.

  • On Windows, compilation performance sucks
All Windows' compilers supporting C++11 are terrible slow. Restricting compilation to Visual Studio 2012 & 2013 is a bold move.

  • The standard library hasn't matured yet
We see arguments in favour of C++11 adoption the usage of std::atomic and std::thread. The problem is, the std lib isn't mature. These libraries have been written in a rush with time constraints and deadlines. And as a result, they favour functionality over run-time performance or compilation speed.
For example, VS 2012's high_resolution_clock isn't high resolution. Not something you would really expect. Some atomic's usage are also several times slower than they should be.
This problem affects all compilers. It would take at least 5 years until the std lib has matured and proven to work as one would expect. Nowadays developers suggest that std::vector<T> should deliver the same performance as a raw pointer. But this wasn't true during the first years. vector<T> used to be a huge bloat. This is normal software development cycle.

  • Boost is not a replacement for C++11
We also see as suggestions that when C++11 is not supported, Boost should be used instead (it's far more mature and had been supporting stuff that just recently got into the standard). Here's the shock for you: We're trying to get away from Boost.
In some game companies, you can literally get fired for adding Boost as a dependency to the game engine. It bloats the executable size (and thus runtime performance), increases memory footprint, and greatly increases the compilation time.
Boost is useful for simplifying your life in regular programs, but it has no place in low latency, high performance graphics engines.

Instead we're using our own cross-platform primitives where we can focus on quality and performance while maintaining dependencies and compilation time to a minimum, without the pressure of supporting every use case. Such examples are the classes LightweightMutex, Barrier, ThreadHandle and the functions Threads::CreateThread and Threads::WaitForThreads. A bonus benefit is that debuggers produce a much cleaner call stack when debugging multiple threads. In other words, it's also cleaner.

  • Adoption requires modifying coding standards
One of our fears is that contributors will start using auto everywhere. Auto looks awesome to get rid of typing 8 extra letters, but it's very horrible when you have to analyze code written by someone else and you can't quickly see what the variable's type is, or you don't have an IDE to help you.
Auto is useful inside templates, since the variable type may not be known until compilation or specialization, or when the syntax inside the template gets too complex. However using auto outside templates (or everywhere!) is an abuse.
It can even introduce subtle bugs: e.g.

Code: Select all

auto x = 7.0; //This is a double
auto x = 7.0f; //This is a float
auto x = 7.; //This is a double!!!
auto x = 7; //Is this an int or a uint?
The first one may be intended to be a float, but the 'f' was missing.
The third one may be supposed to be an integer, but the extra '.' made it a double. Easy to miss.
The fourth one is the worst kind. Signed integer overflow is undefined behavior. Unsigned integer overflow is well defined (wraps around). This can have unforeseen consequences:

Code: Select all

auto x = myInteger; //int myInteger = 262144; causes undefined behavior as result should be 68719476736, but doesn't fit in 32-bit
if( x * x < x )
{
//The compiler may optimize this away. Which wouldn't happen if 'x' were unsigned.
}
Most likely we will end up banning the usage of auto keyword outside templates or specific cases. We would have to also analyze what happens with other C++11 additions like lambdas. The point is, we can't just rush and let contributions using C++11 syntax go ahead. We have to sit down and think about it.


When all these problems get addressed, we will reevaluate adoption of C++11. But for the time being, it's not gonna happen.

The OGRE team.
AusSkiller
Gremlin
Posts: 158
Joined: Wed Nov 28, 2012 1:38 am
x 13

Re: C++11 Adoption stance

Post by AusSkiller »

dark_sylinc wrote:
  • On Windows, compilation performance sucks
All Windows' compilers supporting C++11 are terrible slow. Restricting compilation to Visual Studio 2012 & 2013 is a bold move.
Just wanted to point out that many of the more useful features of C++11 (like lambdas) do work with Visual Studio 2010 so if you were to cherry pick the features of C++11 to use in Ogre you could retain Visual Studio 2010 support (which I'd love since I use Vista and VS 2012/2013 don't work in Vista). Of course then there would be inconsistency with the use of C++11 which probably isn't a good thing :(.
User avatar
c6burns
Beholder
Posts: 1512
Joined: Fri Feb 22, 2013 4:44 am
Location: Deep behind enemy lines
x 138

Re: C++11 Adoption stance

Post by c6burns »

Could not agree more re: C++11 and maturity. I know some studios won't even allow std containers because of implementation specific differences that, while standards compliant, are deal breakers in extreme performance, cross platform code (consoles especially where memory management - where/when allocations are made - is critical). As Ogre pushes new performance boundaries with 2.0 I can see why std and boost become a concern.
User avatar
Klaim
Old One
Posts: 2565
Joined: Sun Sep 11, 2005 1:04 am
Location: Paris, France
x 56
Contact:

Re: C++11 Adoption stance

Post by Klaim »

First, I must say that I totally agree that Ogre devs should not adopt C++11 right now yet (or at least not the whole standard) for several of the reasons cited before.

The following comments are only because I would like to clarify some arguments that don't always hold to me, even if I agree with most of them.
dark_sylinc wrote:
  • The standard library hasn't matured yet
We see arguments in favour of C++11 adoption the usage of std::atomic and std::thread. The problem is, the std lib isn't mature. These libraries have been written in a rush with time constraints and deadlines. And as a result, they favour functionality over run-time performance or compilation speed.
For example, VS 2012's high_resolution_clock isn't high resolution. Not something you would really expect. Some atomic's usage are also several times slower than they should be.
This problem affects all compilers. It would take at least 5 years until the std lib has matured and proven to work as one would expect. Nowadays developers suggest that std::vector<T> should deliver the same performance as a raw pointer. But this wasn't true during the first years. vector<T> used to be a huge bloat. This is normal software development cycle.
While I agree with the arguments, my current estimate is 2 years from now to get C++14 rock solid (note that C++14 is basically C++11 but bugfixed and with a few additional utilities).
The reason is that competition in the c++ implementations made things different from, say, the situation from 10 years ago. Also, this is my intuition from following diverse c++ implementation quality checks with post-C++03.

That's just my estimate, not a disagreement.

  • Boost is not a replacement for C++11
We also see as suggestions that when C++11 is not supported, Boost should be used instead (it's far more mature and had been supporting stuff that just recently got into the standard). Here's the shock for you: We're trying to get away from Boost.
In some game companies, you can literally get fired for adding Boost as a dependency to the game engine. It bloats the executable size (and thus runtime performance), increases memory footprint, and greatly increases the compilation time.
While I agree with the general sentiment and practical truth, I believe (from both research and experience) that this is a double generalization, which makes this argument a bit bold and non-credible to me. The first generalization is that all boost is one big block of libraries that all have the same compilation and performance properties, which is just untrue. (see also recent discussions in the Boost mailing list about MS stl implementors commenting that boost get quickly faster implementations than compilers one but compilers implementation get faster after some years. In practice it depends on which library you are talking about, and you might have surprises.
The second generalization is that all game devs don't use Boost, which is plain false. I've seen and used boost even in console games. But of course the choice of libraries to use was very careful, so it's more like a side effect of assuming that all boost libraries have the same defects.

Anyway,...
Boost is useful for simplifying your life in regular programs, but it has no place in low latency, high performance graphics engines.
Which is incorrect as I do have done high performance low latency code with boost. (in commercial projects, games and not games)
The truth is that it depends on other factors specific to the project (technical limitations or knowledge about meta prog most of the time), but I agree that most game companies will generally not use boost (whatever the reason) which is already a good reason for Ogre to not use it either.

Instead we're using our own cross-platform primitives where we can focus on quality and performance while maintaining dependencies and compilation time to a minimum, without the pressure of supporting every use case. Such examples are the classes LightweightMutex, Barrier, ThreadHandle and the functions Threads::CreateThread and Threads::WaitForThreads. A bonus benefit is that debuggers produce a much cleaner call stack when debugging multiple threads. In other words, it's also cleaner.
This is unrelated to using C++11 but:
I partially disagree that it's a good idea or that it helps debugging multiple thread (in my experience) and I do fear that Ogre get in the same issues than with the windowing system being maintained by the team while replacing it by a library focused to do just that (SDL/SFML) makes life simpler. Of course not all features are comparable as some enter the specifics of Ogre but I don't believe that concurrency tools (not use) should be implemented by the Ogre team (but having an interface to abstract them is indeed necessary). I think I already said so before and will shut up on this now. :mrgreen:
  • Adoption requires modifying coding standards
One of our fears is that contributors will start using auto everywhere. Auto looks awesome to get rid of typing 8 extra letters, but it's very horrible when you have to analyze code written by someone else and you can't quickly see what the variable's type is, or you don't have an IDE to help you.
Auto is useful inside templates, since the variable type may not be known until compilation or specialization, or when the syntax inside the template gets too complex. However using auto outside templates (or everywhere!) is an abuse.
While I understand the cautious stand here, this argument don't match my experience with auto. I tried to abuse it so that I quickly get experience on when not to use it.
Currently I believe that auto should be considered case by case, with or without generic code.
I have tons of example of non-generic code that made auto helpful with code that might change, as long as you keep the semantic clear.
One example:

auto final_orientation = parent.orientation() * relative.orientation();
auto position = final_orientation * original_position;

What is the type of final_orientation? It could be a Quaternion, a matrix or Euler representation, and all would work here. Recently I wrote some code like this and changed several times the type of orientation() return because of some experimentations. The nice thing is that this code compiled without changing, as long as the semantic don't change.
My point is that with experience I realized that "generic code" might not be only template code. So now I consider auto on case by case, easily ditching it as soon as I want a specific type.
Reading the code hardly is impacted as long as you get the semantic easy to understand.

However, I do not believe that explicit float and int manipulation should use auto at all. It's only confusing in this kind of code, you should always make clear what is the type.
So, in most ogre code I suspect that explicit types are indeed better. However that's not true for all the code. Keep in mind the flexibility of not having to change all the user code
when you manipulate a concept instead of a specific type.

In any way, auto in ogre wouldn't impact my code, so I don't object to the decision; just pointing that 3 years of using auto don't lead me to the same conclusions, but with maybe different kind of code.

It can even introduce subtle bugs: e.g.

Code: Select all

auto x = 7.0; //This is a double
auto x = 7.0f; //This is a float
auto x = 7.; //This is a double!!!
auto x = 7; //Is this an int or a uint?
Last line: It's always a int. What made you think it could be uint?
The rule is that it uses the type of the thing on the right, and the type of litterals have been defined even before C++03.
The first one may be intended to be a float, but the 'f' was missing.
The third one may be supposed to be an integer, but the extra '.' made it a double. Easy to miss.
The fourth one is the worst kind. Signed integer overflow is undefined behavior. Unsigned integer overflow is well defined (wraps around). This can have unforeseen consequences:

Code: Select all

auto x = myInteger; //int myInteger = 262144; causes undefined behavior as result should be 68719476736, but doesn't fit in 32-bit
if( x * x < x )
{
//The compiler may optimize this away. Which wouldn't happen if 'x' were unsigned.
}
I believe that calculations with basic types should not use auto anyway, so I get your point and I agree.
However I don't agree when this example is used as a generalization for all kind of code. Of course it's a good argument for graphic code (except the non-mathematical parts).
Most likely we will end up banning the usage of auto keyword outside templates or specific cases. We would have to also analyze what happens with other C++11 additions like lambdas. The point is, we can't just rush and let contributions using C++11 syntax go ahead. We have to sit down and think about it.
I'm guessing that trying to use auto a lot in other projects could help the team get experience for this. Meanwhile I agree that it's certainly the safer way to go for now.


So basically I'm nitpicking ( :twisted: ), but I agree with the global decision.
User avatar
Kojack
OGRE Moderator
OGRE Moderator
Posts: 7157
Joined: Sun Jan 25, 2004 7:35 am
Location: Brisbane, Australia
x 534

Re: C++11 Adoption stance

Post by Kojack »

dark_sylinc wrote:Most likely we will end up banning the usage of auto keyword outside templates or specific cases.
If auto is allowed in templates or specific cases, then we will need to drop VC2008 support. That goes for pretty much any c++11 feature.

I really like auto for std container iterators. But saving some typing isn't worth dropping a compiler.

There's a list of c++11 features in various compiler versions here: http://wiki.apache.org/stdcxx/C++0xCompilerSupport
User avatar
holocronweaver
Google Summer of Code Student
Google Summer of Code Student
Posts: 273
Joined: Mon Oct 29, 2012 8:52 pm
Location: Princeton, NJ
x 47

Re: C++11 Adoption stance

Post by holocronweaver »

Kojack wrote:I really like auto for std container iterators. But saving some typing isn't worth dropping a compiler.
Considering that VS2008 is approaching seven years old, dropping it should be painless. In computer years that is like 70 human years - retirement age. :)

I agree that auto should be allowed for templates and iterators, and banned otherwise. I have yet to find a practical use for it anywhere else (except when prototyping).

Once Clang gains good integration into VS, or else VS falls out of favor, my hope is that MS compilers will stop holding back multi-platform libraries like ours and we can begin adopting new standards within a couple years of their introduction, rather than 4 to 6.
User avatar
Kojack
OGRE Moderator
OGRE Moderator
Posts: 7157
Joined: Sun Jan 25, 2004 7:35 am
Location: Brisbane, Australia
x 534

Re: C++11 Adoption stance

Post by Kojack »

It's probably around time for another Ogre survey (been 3 years since the last one). This time with visual studio numbers broken down by version.

VC2008 was the last of the classic visual studios, before the entire user interface reboot. It's got a faster gui than any of the recent versions. I can imagine developers deciding not to upgrade from VC2008 to VC2010 due to the worse user experience. I don't know how many that would be though, which is why a survey could be handy. Maybe nobody uses it anymore.
User avatar
Zonder
Ogre Magi
Posts: 1168
Joined: Mon Aug 04, 2008 7:51 pm
Location: Manchester - England
x 73

Re: C++11 Adoption stance

Post by Zonder »

Kojack wrote:It's probably around time for another Ogre survey (been 3 years since the last one). This time with visual studio numbers broken down by version.

VC2008 was the last of the classic visual studios, before the entire user interface reboot. It's got a faster gui than any of the recent versions. I can imagine developers deciding not to upgrade from VC2008 to VC2010 due to the worse user experience. I don't know how many that would be though, which is why a survey could be handy. Maybe nobody uses it anymore.
As well as getting slower it if getting more and more memory hungry. It wouldn't surprise me that Microsoft's stance might be they expect your hardware to be upgrading at the same time :) (And personally my dev machine does get upgraded every 2 years)
There are 10 types of people in the world: Those who understand binary, and those who don't...
User avatar
Klaim
Old One
Posts: 2565
Joined: Sun Sep 11, 2005 1:04 am
Location: Paris, France
x 56
Contact:

Re: C++11 Adoption stance

Post by Klaim »

holocronweaver wrote: I agree that auto should be allowed for templates and iterators, and banned otherwise. I have yet to find a practical use for it anywhere else (except when prototyping).
I have other non-prototyping cases where it's useful (when chrono is involved for example, or generic algorithm that is not templated but work with types returned by members of their arguments objects), but I guess it's hard to make any generalization about auto anyway. Lot of controvercy about it. I guess it will be fun when C++14 will be stabilized for most compilers, with auto being used both to make a lambda generic and as an auto-deducing return type for functions. :twisted:
Once Clang gains good integration into VS, or else VS falls out of favor, my hope is that MS compilers will stop holding back multi-platform libraries like ours and we can begin adopting new standards within a couple years of their introduction, rather than 4 to 6.
Oh by the way you and others here might be interested in following this new status page: http://clang.llvm.org/docs/MSVCCompatibility.html
They don't have a lot of efforts/people helping with MSVC compatibility yet but it's still promising.
User avatar
lunkhound
Gremlin
Posts: 169
Joined: Sun Apr 29, 2012 1:03 am
Location: Santa Monica, California
x 19

Re: C++11 Adoption stance

Post by lunkhound »

While on the topic of C++ features and things that
has no place in low latency, high performance graphics engines
What about exceptions?
paroj
OGRE Team Member
OGRE Team Member
Posts: 1993
Joined: Sun Mar 30, 2014 2:51 pm
x 1073
Contact:

Re: C++11 Adoption stance

Post by paroj »

lunkhound wrote:While on the topic of C++ features and things that
has no place in low latency, high performance graphics engines
What about exceptions?
not an issue when used correctly. (as in Ogre)
paroj
OGRE Team Member
OGRE Team Member
Posts: 1993
Joined: Sun Mar 30, 2014 2:51 pm
x 1073
Contact:

Re: C++11 Adoption stance

Post by paroj »

for reference here is what the Unreal Engine Devs think about C++11.
User avatar
Klaim
Old One
Posts: 2565
Joined: Sun Sep 11, 2005 1:04 am
Location: Paris, France
x 56
Contact:

Re: C++11 Adoption stance

Post by Klaim »

paroj wrote:for reference here is what the Unreal Engine Devs think about C++11.
Wow interesting! I'm surprised they do use C++11 a bit, but they sure use the less problematic features so it's understandable and still appropriately conservative.
iblues1976
Gnome
Posts: 379
Joined: Fri Sep 16, 2011 4:54 pm
x 10

Re: C++11 Adoption stance

Post by iblues1976 »

In my opinion, if the performance and problems with C++11 is a reason not to use it, I think it is understandable. We are in 2014, therefore, C++11 should be more mature.

With this said, I think trying to please older compilers for the OGRE 2.0+ is no win situation. Compilers and technology moves so quickly, that if we worry about compilers that do not support c++11, by the time OGRE 2.0+ is out and mature, no one will be using it for new projects (those compilers) or I hope.

I think C++11 and major features of the language should be considered if they don't affect performance. In other words, if you are working on a new project with OGRE 2.0+, I think it should support newer compilers more than it supports older compilers. Ogre 1.x can support the older ones.

Of course, it is my opinion. I think whoever is working in OGRE 2.0+, developing the next gen of OGRE, probably has more technical background and more information that I am.

In conclusion, I don't think the support for older compilers should be the reason not to use C++11.
User avatar
lunkhound
Gremlin
Posts: 169
Joined: Sun Apr 29, 2012 1:03 am
Location: Santa Monica, California
x 19

Re: C++11 Adoption stance

Post by lunkhound »

C++11 adoption doesn't need to be all or nothing. I think it would make sense to consider the various C++11 features on a case-by-case basis. Features like the "override" keyword could be adopted in a way that is compatible with older compilers (i.e. have a macro OGRE_OVERRIDE that expands to nothing on older compilers).
User avatar
Klaim
Old One
Posts: 2565
Joined: Sun Sep 11, 2005 1:04 am
Location: Paris, France
x 56
Contact:

Re: C++11 Adoption stance

Post by Klaim »

iblues1976, Actually C++11 features provide better performance even without using the new features (only compile time performance of some version of Visual Studio compiler is worse) for example because of implicit moving semantics.
In my experience so far, C++11 have never made anything slower even with code generated from VS2010. The reason is that if you look at the new non-purely-syntactic features, all of them provide even more information to the compiler to be able to generate better optimization. Or they rely on the same type system as before, so nothing is added.

The changes in the language that should widely affect performance in unknown way for now will be with the version after C++14, both because of modules and reflection features. This last one will only be about static information first but it might have an impact on binary size.
iblues1976
Gnome
Posts: 379
Joined: Fri Sep 16, 2011 4:54 pm
x 10

Re: C++11 Adoption stance

Post by iblues1976 »

Klaim wrote:iblues1976, Actually C++11 features provide better performance even without using the new features (only compile time performance of some version of Visual Studio compiler is worse) for example because of implicit moving semantics.
In my experience so far, C++11 have never made anything slower even with code generated from VS2010. The reason is that if you look at the new non-purely-syntactic features, all of them provide even more information to the compiler to be able to generate better optimization. Or they rely on the same type system as before, so nothing is added.

The changes in the language that should widely affect performance in unknown way for now will be with the version after C++14, both because of modules and reflection features. This last one will only be about static information first but it might have an impact on binary size.
Thanks for the extra info. It does make sense.
User avatar
Enhex
Gnoblar
Posts: 13
Joined: Sat Feb 22, 2014 7:56 am

Re: C++11 Adoption stance

Post by Enhex »

dark_sylinc wrote:

Code: Select all

auto x = 7.0; //This is a double
auto x = 7.0f; //This is a float
auto x = 7.; //This is a double!!!
auto x = 7; //Is this an int or a uint?

Code: Select all

auto x = myInteger; //int myInteger = 262144; causes undefined behavior as result should be 68719476736, but doesn't fit in 32-bit
if( x * x < x )
{
//The compiler may optimize this away. Which wouldn't happen if 'x' were unsigned.
}
That's not how you use or what auto is for.
Auto is for letting the compiler deduce the type. Not for declaring new variables from ambiguous literals, and definitely not for casting.

auto is for making things like this:

Code: Select all

Ogre::ConfigFile::SectionIterator iSection = cfg.getSectionIterator();
into this:

Code: Select all

auto iSection = cfg.getSectionIterator();
It's much shorter and easier to read and you only need to change the type in one place instead of many, which is excellent for refactoring.


oh and that "terrible slow" review looks extremely biased.

Also the argument that the stdlib somehow de-matured doesn't make sense, and seems to be purely based on social proof.

I'm sorry but I don't see a speck of rationality. Only bias, ignorance, and social proof.
User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5292
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1278
Contact:

Re: C++11 Adoption stance

Post by dark_sylinc »

Enhex wrote:That's not how you use or what auto is for.
Auto is for letting the compiler deduce the type. Not for declaring new variables from ambiguous literals, and definitely not for casting.
You're entirely missing the point. Of course auto is not for literals!

Please tell me, what does the following code do:

Code: Select all

auto x = speed->getDeltaIterator();
auto y = character->getVelocity();

auto finalPosition = y * (*x);
Easy right?, now... what does return DeltaIterator? an iterator of floats? an iterator of integers? an iterator of doubles?. An iterator of Vector3s???
Is 'y' a Vector3? or a float? or an integer? Something else?

We loose control over what type it really is. By the way, if they're both integers, then this code invokes undefined behavior if it overflows.
A lot of information was stripped away from us because someone decided to write auto. No thanks.
It's much shorter and easier to read and you only need to change the type in one place instead of many, which is excellent for refactoring.
No, that's exactly what you should not do when refactoring. When you're refactoring, some things are going to change. And with that, the usage pattern may have changed as well.
It is incredibly useful if the compiler stops every time it sees "cfg.getSectionIterator()" so that you can manually fix all the occurrences. If auto silently lets the compiler let it compile, you may miss to fix a few.

If you want short, readable objects, then use a typedef which will let you globally change the type in one place instead of many, while still in control of that type in particular.

Furthermore Ogre::ConfigFile::SectionIterator isn't hard to read. It's clearly telling you a lot about the type: it's an iterator, to a section in a Config file, belonging to one of Ogre components.
Typing speed is not argument, not in the days of modern IDEs with auto-completion.

As I said in my original post, there are legitimate cases of auto (such as when we're in a complex template, where the type can by definition, be dynamic. So typing auto is much nicer than <T>::SubStruct::<S>::iterator), but those are rare.
oh and that "terrible slow" review looks extremely biased.
Then prove it otherwise.
Also the argument that the stdlib somehow de-matured doesn't make sense, and seems to be purely based on social proof.
No. It hasn't de-matured. The new features incorporated to the std library haven't matured yet. It's not the same.
But it's not like regressions can't happen anyway.
User avatar
Enhex
Gnoblar
Posts: 13
Joined: Sat Feb 22, 2014 7:56 am

Re: C++11 Adoption stance

Post by Enhex »

dark_sylinc wrote: Please tell me, what does the following code do:

Code: Select all

auto x = speed->getDeltaIterator();
auto y = character->getVelocity();

auto finalPosition = y * (*x);
Easy right?, now... what does return DeltaIterator? an iterator of floats? an iterator of integers? an iterator of doubles?. An iterator of Vector3s???
Is 'y' a Vector3? or a float? or an integer? Something else?

We loose control over what type it really is. By the way, if they're both integers, then this code invokes undefined behavior if it overflows.
That's easy just hover over it in Visual Studio. While this argument is 100% true for sharing code snippets, no competent programmer is working with plain text editors.
You'd still get the bug regardless of auto. And auto doesn't mean you should be working with undefined types, you should know the type just like you would without it. Also the variable name should describe it to some degree, that's a fundamental good coding practice to have semantics.
Something like this is pretty obvious:

Code: Select all

auto vec = GetVelocity();
So yeah those problems are true if you a use plain text editor, but the real question is why are you using a plain text editor?
It is incredibly useful if the compiler stops every time it sees "cfg.getSectionIterator()" so that you can manually fix all the occurrences. If auto silently lets the compiler let it compile, you may miss to fix a few.

If you want short, readable objects, then use a typedef which will let you globally change the type in one place instead of many, while still in control of that type in particular.
Using auto would basically be the same as correcting all the use instances of "cfg.getSectionIterator()" to the correct type. It's true that you'll probably want to check out each use instance and make sure it fits the changes, but you can just as well do a "find in files" search for "cfg.getSectionIterator()", and save yourself renaming O(n) instances.
typedef doesn't solve this problem, and it doesn't necessarily makes the code any shorter, since you still need to use namespaces and descriptive names.
oh and that "terrible slow" review looks extremely biased.
Then prove it otherwise.
He doesn't mention the versions of GCC and Clang.
He shows an image of his task manager showing CPU usage maxed out. That can mean 2 things:
Either he got really weak processor that can't handle the load, or the more reasonable option that VS actually does a good job utilizing all the cores on the computer.
About the RAM, Heck my computer is using 5.4GB of RAM right now and that's mostly Chrome alone.
Utilizing resources is a good thing, we're paying for the hardware to use it, not not to use it.
His compilation graph even shows improvement with VS2013.
Also the argument that the stdlib somehow de-matured doesn't make sense, and seems to be purely based on social proof.
No. It hasn't de-matured. The new features incorporated to the std library haven't matured yet. It's not the same.
But it's not like regressions can't happen anyway.
If there are features that don't suit your needs, just don't use them. How is it a disadvantage?


You do provide valid reasons, but they're solvable if you try to take a step back and re-approach the problem differently.
NotCamelCase
Greenskin
Posts: 140
Joined: Sun Feb 03, 2013 6:32 pm
x 8

Re: C++11 Adoption stance

Post by NotCamelCase »

Enhex wrote: That's not how you use or what auto is for.
Auto is for letting the compiler deduce the type. Not for declaring new variables from ambiguous literals, and definitely not for casting.

auto is for making things like this:

Code: Select all

Ogre::ConfigFile::SectionIterator iSection = cfg.getSectionIterator();
into this:

Code: Select all

auto iSection = cfg.getSectionIterator();
It's much shorter and easier to read and you only need to change the type in one place instead of many, which is excellent for refactoring.
I don't see how it's easier to read, either. Yes, it's less typing and less time-consuming but whenever I try to read code mixed with auto's, I find myself struggling scrolling up and down to hover the auto'd vars so IDE will highlight the type (which if you're not on an IDE has no help)
Check out my projects: https://github.com/NotCamelCase
User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5292
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1278
Contact:

Re: C++11 Adoption stance

Post by dark_sylinc »

Enhex wrote:That's easy just hover over it in Visual Studio.
(...)

Code: Select all

auto vec = GetVelocity();
So yeah those problems are true if you a use plain text editor, but the real question is why are you using a plain text editor?
Why would I hover when the alternative is to just read it? Unless the IDE replaces all the autos with their explicit types, or tracks my eyeballs, reading long lines of code is easier when I don't need to bug the IDE all the time.

If I'm looking for a bug that I don't know where it is, something that comes as obvious out of a single glance is much better than something I need to hover over... explicitly.
it doesn't necessarily makes the code any shorter, since you still need to use namespaces and descriptive names.
How is that a disadvantage instead of advantage?
Besides a typedef can make things really short.
He doesn't mention the versions of GCC and Clang.
The version of GCC was 4.8.1 if memory serves me right, Clang was either 3.2 or 3.3
He shows an image of his task manager showing CPU usage maxed out. That can mean 2 things:
Either he got really weak processor that can't handle the load, or the more reasonable option that VS actually does a good job utilizing all the cores on the computer.
So do GCC, Clang and VS 2008. Yet they take significantly less time to build the same code. Which is what matters in the end.
The RAM consumption is abnormal in VS2012+ when compared to their competitors and its own predecessor; which is a strong indication of where the bad performance comes from (memory bandwidth didn't grow the same way as ALU).

I have upgraded to a Core i5 4460 3.2Ghz Quad Core; 16GB RAM; and a 500 MB/s SSD since I did that benchmark.
And I still find irritating that VS 2008 finishes much sooner to compile the same code, whereas I can go do other stuff waiting for 2013 finish.
I can buy bigger hardware, and that won't change the fact the SW is taking too much time in comparison to their competitors, even its old self.

I do have yet to test VS 2015 though. I like the direction where it seems to be going: Android integration, Clang integration.
You do provide valid reasons, but they're solvable if you try to take a step back and re-approach the problem differently.
If I were to code myself alone, yes.
But this is a medium sized open source project with lots of contributors. Disciplined and trained team members or employees can be taught to follow the same rules. But in Open Source projects we have to update the Coding Style Guidelines and enforce them. Sadly, "new" language features have the tendency with lots of contributors to just use them because they're new and modern; without thinking if there's real added value in using them.
We don't select personnel. Anyone can contribute. Which makes the quality of the contributions to vary wildly.
This can result in rejected PR for contribs that do provide a much wanted bugfix/addition to Ogre's functionality but doesn't meet the Coding Style guidelines; or if the functionality is too important, accept it and get someone to sit down and match the coding style issues.
This tendency fades over time as they're no longer new, and people is actually more aware of them as they realize their pitfalls (and advantages) out of experience.

I have been increasingly more interested in C++11 this year; and I need to evaluate VS 2015 yet. I'm not sure if we're there yet, but the situation has improved since the original post was written. I also need to consult this with the other team members.
We also would have to update the Coding Style Guidelines, since C++11 has things that don't belong to a performance oriented software, and things that are useful.
qwertzui11
Halfling
Posts: 80
Joined: Wed May 14, 2008 10:44 am
Location: EU
x 22
Contact:

Re: C++11 Adoption stance

Post by qwertzui11 »

C++11 has some nice features, i cant live without no more :wink:
- nullptr
- std::move()
- *::emplace()
- smart ptr including make_unique<>(), make_shared<>()
- using (type alias) http://en.cppreference.com/w/cpp/language/type_alias
- range based iteration http://en.cppreference.com/w/cpp/language/range-for
- constexpr
- override
- threading

I'd recommend using C++11 because it makes code faster, cleaner and improves readability.
Ofc people could missuse C++11 features, like "auto". It's like meta-programming - don't be a smart-ass.
Ogre 2 should use C++11 using only features approved by visual studio 2012.

In my opinion open source contributors like to use new stuff - so C++11 mandatory.
The standard is 4 years old and matured.
I believe a drop of boost would be possible with C++11.
Compile time, shouldn't be an argument for using C++11.

Markus
User avatar
Zonder
Ogre Magi
Posts: 1168
Joined: Mon Aug 04, 2008 7:51 pm
Location: Manchester - England
x 73

Re: C++11 Adoption stance

Post by Zonder »

Image

Sorry couldn't resist....
There are 10 types of people in the world: Those who understand binary, and those who don't...
User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5292
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1278
Contact:

Re: C++11 Adoption stance

Post by dark_sylinc »

qwertzui11 wrote: - nullptr
- std::move()
- *::emplace()
- constexpr
- override
These are useful, attracting from C++11 features, as they either improve safety, readability, correctness, and/or run time performance.
qwertzui11 wrote:- using (type alias) http://en.cppreference.com/w/cpp/language/type_alias
I don't have an opinion on this one.
qwertzui11 wrote:- smart ptr including make_unique<>(), make_shared<>()
In a regular C++ project, they're useful, yes. But in a graphics engine smart pointers should be avoided (yes, I'm aware Ogre itself uses its own hand-roled smart pointers; and as such we suffered in performance. Ogre 2.1 undid a lot of that nonsense).
They need to be used with care.
qwertzui11 wrote:- range based iteration http://en.cppreference.com/w/cpp/language/range-for
I'm personally against these type of for idiom. I would have to sit down to write down and remember all the things I don't like about that expression. It has enough drawbacks I don't like.
qwertzui11 wrote:- threading
Standard-lib threading has no place in a high performance graphics engine.
qwertzui11 wrote:I believe a drop of boost would be possible with C++11.
Boost is optional right now. And quite discouraged as well. Doesn't add any real value, only slowdowns the compilation time, and makes dependency setup messier.
qwertzui11 wrote:Compile time, shouldn't be an argument for using C++11.
In "large" projects with 15-20-minute compiling time being brought down to 8 minutes by just switching to a different compiler, your opinion will quickly change. Being able to test the code, iterate and debug faster is far more important than a couple of language additions that improve readability when used well.
Particularly in game development, which by nature is all about reducing iteration times as much as possible.
Post Reply