• Create Account

So... C++14 is done :O

Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

90 replies to this topic

#1Alessio1989  Members

Posted 18 August 2014 - 01:19 PM

POPULAR

C++14 is done and the final specification sould be available in the ISO/IEC store asap.. https://isocpp.org/blog/2014/08/we-have-cpp14

Some new features:

- auto return type for functions
- generic lambdas and extended capturing
- "more reasonable" restrictions for constexpr
- variable templates

Any hope/wish/desire for the next standard? (C++17 maybe) For me, I still wish to see concepts. O_O

Little off-topic: VS14 CTP3 is out http://blogs.msdn.com/b/vcblog/archive/2014/08/18/visual-studio-14-ctp-3-now-available.aspx
"Recursion is the first step towards madness." - "Skeggǫld, Skálmǫld, Skildir ro Klofnir!"
Direct3D 12 quick reference: https://github.com/alessiot89/D3D12QuickRef/

#2Ohforf sake  Members

Posted 18 August 2014 - 01:59 PM

And there I haven't even given every C++11 feature a spin yet.

IMHO, you missed the best "new" feature in that list:
- Binary literals (yay, finally!)

#3Ravyne  Members

Posted 18 August 2014 - 02:14 PM

You also missed extended constexpr Nevermind, no you didn't, but regardless -- for a complete rundown, see https://isocpp.org/wiki/faq/cpp14-language

The new auto return type is more than just extending it to functions, it also has more capability with respect to multiple return statements and recursive calls -- basically, as long as the first return statement's type can be deduced, you can now have subsequent return statements, including recursive calls, as long as they all agree on the type.

decltype(auto) is a new refinement of type deduction that is mostly useful to preserve the reference-ness where simple auto wouldn't -- My understanding is that it performs the same function as auto-with-trailing-return-type-of-decltype, but without the trailing part. It can be used anywhere a declaration can be used, which might be useful but early guidance is that this would be an anti-pattern. This is super important, but mostly for library-implementors.

There's also a new standard [[deprecated]] attribute to mark deprecated APIs, and you can now use the single quote (') character anywhere in numeric literals to separate digits to make them more readable, in any of the literal formats -- e.g. 0b0110'0011 to separate out the nybles in a byte.

Edited by Ravyne, 18 August 2014 - 02:27 PM.

throw table_exception("(ノ ゜Д゜)ノ ︵ ┻━┻");

#4frob  Moderators

Posted 18 August 2014 - 02:15 PM

POPULAR

Good to hear it was finally locked down, the changes to lambdas and the slight corrections to auto to handle them are useful.

As for C++17, work on it started when they started cementing what would not be in C++14, so it's already got about 3 years of work on it.

As it is a major version, there are quite a few big changes in the works.

More real-world concurrency and real-world parallelism, more networking, more real-world file systems, and language-supported reflection and "modules" are all under discussion. Just like before, most of the boost library is under consideration.

There might be an addition of larger bit types, although C++11's growth to 64-bit caused quite a lot of headaches, and the pre-C++98 transition to 32-bit was also painful for a lot of businesses. It would be cool to have some of the 128-bit and 256-bit data types available without platform-specific extensions.

That said, I think modifications to the language core are detrimental in the long run.

C++ has aged well, but most of that has been by sticking with the original minimalist roots.  Additions and modifications to the language core push the language outside those minimalist roots. There are few features left in the imperative programming world that cannot be implemented in the language.

Some of the newer features are just syntactic sugar for things that could already be done, and I tend to disagree with those. I still think the range-based loops were unnecessary. The constexpr system just complicates what was simple and could already be done by leaning on the preprocessor. Others are frustrating in shortsightedness. The 'final' keyword is already a frustration for me, as I frequently write automated tests and system interoperations code so the inability to derive from a class to build a necessary adapter is quite frustrating; just because the programmer writing it is so unimaginative that he cannot fathom a case for extension does not mean no case will ever exist.

I would much rather they focus on standard library growth rather than modifications to the core language.

Check out my book, Game Development with Unity, aimed at beginners who want to build fun games fast.

Also check out my personal website at bryanwagstaff.com, where I occasionally write about assorted stuff.

#5imoogiBG  Members

Posted 18 August 2014 - 04:13 PM

Any hope/wish/desire for the next standard?

Compile time reflections (and being able to process them)

Edited by imoogiBG, 18 August 2014 - 04:14 PM.

#6SeanMiddleditch  Members

Posted 18 August 2014 - 04:22 PM

Keep in mind that C++ also now has Technical Specifications, which are extensions to the language or library that are standardized in functionality but not required. e.g., Reflection is likely to land in a TS, meaning that any compiler that implements it will implement it in a compatible way but compilers can still be C++17 compliant without supporting it. Think of them sort of like OpenGL extensions, but each with the clear intent to roll into the proper standard once they've been hammered on by the community and unforeseen design mistakes are sorted out.

Game Developer, C++ Geek, Dragon Slayer - http://seanmiddleditch.com

C++ SG14 "Games & Low Latency" - Co-chair - public forums

Wargaming Seattle - Lead Server Engineer - We're hiring!

#7KaiserJohan  Members

Posted 19 August 2014 - 12:43 AM

I still think the range-based loops were unnecessary.

Can you elaborate more? Personally I feel it is alot more readable.

#8frob  Moderators

Posted 19 August 2014 - 01:18 AM

POPULAR

I still think the range-based loops were unnecessary.

Can you elaborate more? Personally I feel it is alot more readable.
It does not add anything new.

Many of the language changes added something that wasn't there before. Type deduction with auto was not there and there was no equivalent, it was added to support lambdas that have no expressible type. Lambdas were added and there really wasn't a good way to do it without them, there were libraries that did something very similar but they relied on tricks rather than being something natively handled everywhere. Addition of 64 bit types standardized something that was only partially developed as an extension on various platforms, each with their own different 64 bit name. These features added something new to the core of the language, made it something better than it was before.

Range based loops, however, added nothing. The old method was still there, and it is still there. The result is that instead of the traditional 'minimalist' approach, there is duplication. It did not enable any new thing. It did not add a feature. It did not do something that could not be trivially done before. It obscures details, adds an additional interface, but doesn't add any functionality. It is syntactic sugar, it is language bloat.

Check out my book, Game Development with Unity, aimed at beginners who want to build fun games fast.

Also check out my personal website at bryanwagstaff.com, where I occasionally write about assorted stuff.

#9Chris_F  Members

Posted 19 August 2014 - 01:46 AM

Glad to see C++14 finalized. I've already been making use of it as I tend to use GCC and increasingly Clang/LLVM.

Concepts are nice, but what I think C++ desperately needs is modules, and I don't think it can wait till C++17. We need modules yesterday. Besides that, I personally would like to see a standardized ABI for C++, as purposed by N4028, as that is something which I personally think is important.

#10Chris_F  Members

Posted 19 August 2014 - 01:48 AM

It is syntactic sugar, it is language bloat.

It can make code shorter and easier to read. C++ is already extremely large and complicated, removing the "bloat" of range-based for loops would not improve the situation in any noticeable way.

#11Juliean  GDNet+

Posted 19 August 2014 - 02:35 AM

Range based loops, however, added nothing. The old method was still there, and it is still there. The result is that instead of the traditional 'minimalist' approach, there is duplication. It did not enable any new thing. It did not add a feature. It did not do something that could not be trivially done before. It obscures details, adds an additional interface, but doesn't add any functionality. It is syntactic sugar, it is language bloat.

Range-based for loops basically implemented for-each loops, which in my book is good enough to warrant it. In my personal opinion, I totally love them. Sure, you could possibly do the same thing with a macro before, but its much cleaner that way:

std::vector<Class*> vValues;

for(auto pValue : vValues)
{
pValue->DoSomething();
}

for(auto itr = vValues.begin(); itr = vValues.end(); ++itr)
{
(*itr)->DoSomething(); // i totally loved having to do that itr-dereferencing as well before on vector<pointer>
}

I see your argument about not implementing something totally new, but fail to see why this is a bad thing. Everything that allows you to write code faster and cleaner at the same time, while not being forced upon, is IMHO a decent thing. Why would anyone ever prefer to write the loop the second way (and thats the nice version already using "auto")? Unless you want to delete something from the loop, yeah, quess that counts.

Edited by Juliean, 19 August 2014 - 02:37 AM.

#12phantom  Members

Posted 19 August 2014 - 03:09 AM

Why would you write the loop the 2nd way when you have std::for_each and lambda functions?

#13Juliean  GDNet+

Posted 19 August 2014 - 03:16 AM

Why would you write the loop the 2nd way when you have std::for_each and lambda functions?

You don't,  unless you don't know about std::for_each like I did.

std::vector<Class*> vValues;

std::for_each(vValues.begin(), vValues.end(), [] (Class* pValue)
{
pValue->DoSomething();
});


I quess that works, especially if you make a wrapper function that removes the need for always specifiying "begin/end" when all you want is the full range. Quess I still prefer range-based loops, just a little more explicit than this version. (I do have to admit that this changes things a little bit at least, always more to learn ).

#14phantom  Members

Posted 19 August 2014 - 03:24 AM

C++14 would frame that more like;
std::for_each(std::begin(Values), std::end(Values), [](auto value)
{
value->DoAThing();
});

and once you get use to reading that then there is always this fun setup...

std::erase(std::remove_if(std::begin(values), std::end(values), [](auto value) { return !value->alive();}), std::end(values));


Edited by phantom, 19 August 2014 - 03:28 AM.

#15Hodgman  Moderators

Posted 19 August 2014 - 04:22 AM

POPULAR

Why would you use any of those examples when the idiomatic version from the past 2 or 3 decades still works, is understood by everyone, and generates the same ASM?
std::vector<Class*> vValues;
for( int i=0, end=vValues.size(); i!=end; ++i )
vValues[i]->DoSomething();

I agree with Frob's post on language bloat. New features are nice, but duplicated/redundant features for the sake of being modern are unecessary.

#16N.I.B.  Members

Posted 19 August 2014 - 04:38 AM

nullptr is just about the only feature of C++11 I actually use (though I was fine with the plain-old NULL). Ctr delegation is also nice, but again - syntactic sugar.

Seems to me like C++11/14 features are mostly beneficial if you are writing an STL like library (See Bjorn's FAQ, a lot of the examples are STL related).

I agree with frob - C++11 and C++14 are moving away from the minimalist approach, which isn't a good thing (and don't get me started on the dangers of 'auto').

#17Ryan_001  Prime Members

Posted 19 August 2014 - 05:08 AM

I find many of the C++11 features 'tacked' on and very hackish as is, so I'm actually dreading C++14 a bit.

#18Juliean  GDNet+

Posted 19 August 2014 - 05:13 AM

Why would you use any of those examples when the idiomatic version from the past 2 or 3 decades still works, is understood by everyone, and generates the same ASM?

Lots of things from the past still works, which still doesn't mean its the most optimal way of doing things. One can still send letters for written communication, but using online services is just a tad bit quicker ;)

Also while probably most people understand the old version, doesn't mean its easy to read. In fact, let alone the different variants, like having to explicitely store the end-condition and post/pre-increment validates a fixed solution for me.

More prone to error comes to mind, too. Especially for nested loops. Have lost count of how many times I mistakenly incremented the wrong variable or some stuff like that.

And as I already mentioned: Less code to type each time around - for the cost of what? That someone who hasn't seen this kind of loop might have to get used to reading it? From my personal view, the range-based loop is way easier to read, especially if you are new to the language - would anyone want to argue that a beginner would have an easier time with the old explicit loop?

Although generally, based on the old/new discussion, the question shouldn't be "what do I gain by using the new way" but rather "what do i lose by doing so?". People tend to favor that which they are used to, so unless there is a huge loss and virtually no gain for doing it with a new option, I'd say pick the new one.

EDIT:

nullptr is just about the only feature of C++11 I actually use (though I was fine with the plain-old NULL). Ctr delegation is also nice, but again - syntactic sugar.

Varadic templates are also very useful. Reduces code complexity on things like signal/slots, delegates etc... by a drastic amount, also allowing for perfect forwarding.

Edited by Juliean, 19 August 2014 - 05:14 AM.

#19N.I.B.  Members

Posted 19 August 2014 - 05:23 AM

Although generally, based on the old/new discussion, the question shouldn't be "what do I gain by using the new way" but rather "what do i lose by doing so?". People tend to flavor that which they are used to, so unless there is a huge loss and virtually no gain for doing it with a new option, I'd say pick the new one.

I actually think the question is "in how many ways can someone else screw-up the code?". And in C++11 the answer is a lot more then with the "old" C++.

If you are an experienced programmer, who understands the pros and cons of the new feature - then use whatever you want. The problem is that there are way too many inexperienced programmers who (unintentional?) abuse things, or will understand what you are doing.

Take 'auto' for example - it's great when used with caution (and very very sparsely). But I saw some programmers who just decided that it would be great to use it as much as possible (even a very experienced one), regardless of minor things like code readability and type safety.

[EDIT] - 'type safety' should be 'compile time type checks'.

C++ is not a scripting language, nor is it a high-level abstracted language with powerful RTTI like Java. And it shouldn't be. Most of the new features seem to solve very minor problems and do not provide great benefit over the legacy C++.

Edited by N.I.B., 26 August 2014 - 02:24 AM.

#20Álvaro  Members

Posted 19 August 2014 - 05:31 AM

Regarding the different ways of writing a loop that iterates through a vector, I prefer using indices most of the time, because it's the easiest to modify in the future.

for (size_t i = 0, end = vValues.size(); i != end; ++i)
vValues[i]->DoSomething();

What if I only want to DoSomething on elements that pass some test?
for (size_t i = 0, end = vValues.size(); i != end; ++i) {
if (some_test(*vValues[i]))
vValues[i]->DoSomething();
}

What if I need to add more elements to the vector in some circumstances?
for (size_t i = 0; i != vValues.size(); ++i) {
vValues[i]->DoSomething();
if (some_circumstances(*vValues[i]))
vValues.push_back(some_new_thing); // Iterators are now invalid, but indices still work just fine
}

Try to do that with any of the other styles.

For very simple loops, the range-based format is very clean and I sometimes use it.

Edited by Álvaro, 19 August 2014 - 05:36 AM.

Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.