News for hackers. Stuff that matters.
Re:C++11 FAQ by huhtenberg on Thursday January 26, 2017 @10:02AM (#13491876)
I've been programming for money for over 20 years and I grew up professionally writing C and then half-migrating to C++, because the latter very naturally captured lots of C patterns and allowed for more succinct expression of the same. It was lean, expressive and elegant. Just needed a bit of Lisp-y closures and it would've been perfect.

And then things got completely out of hand. Elegance was nuked from the high orbit in favor of "power features" and abstraction. Fucking Boost (I can't tone it down, sorry), move semantics, ass-backwards closures, meta-template programming - C++ that was easy to understand became something that would normally come out of self-indulgent academic research.

Again, I've been using C/C++ for all my professional life, so it pains me to say this, but what it has become, it's... it's just horrible. Anything - C, D, Python, Rust - is cleaner and more elegant than C++ and just as powerful. If nothing else, I feel sorry for Bjarne. What could've been a gem of programming languages became http://i.imgur.com/1oGHYqi.jpg

Re:C++11 FAQ by spoondan on Thursday January 26, 2017 @10:37AM (#13492164)
This is perhaps one of the more unexpected opinions on C++ I've encountered. When I picked up C++ with Turbo C++ 3.0 in the early '90s, it was already widely regarded as an over-complex behemoth. Donald Knuth said of it in 1993, "Whenever the C++ language designers had two competing ideas as to how they should solve some problem, they said 'OK, we'll do them both'. So the language is too baroque for my taste." The last twenty years, there's no C++ that I would call lean, expressive, and elegant. You give the example of template meta-programming as something added more recently, but Erwin Unruh was printing the primes in compiler error messages not long after Knuth was knocking C++ as baroque. It makes me wonder if perhaps the issue isn't simply that over time you've become more aware of how complex the language has always been?

The language has continued to grow, but it's growing in a rather different direction (or rather in a clear direction): towards a modern, preferred subset that _is_ lean, expressive, and elegant. While C++ is still far from my favorite language, I find C++ today to be far simpler, more expressive, and more elegant than at any other point in the past.

Re:C++11 FAQ by cmrdporcupine on Thursday January 26, 2017 @10:40AM (#13492187)
Arguably the std::move stuff and the semantics around it have added uncomfortable complexity to the language, even if it might have been necessary. Other than that I think other advances in C++11 and beyond have made for a quite nicer language to work in.

I love C++11 and use it every day, but I think putting references in the language was an 'original sin'. They should have stuck with C's model: it's either a value or a pointer to a value. References just added a pile of complexity and pontificating about whether something was being copied, moved, or passed by reference.

Re:C++11 FAQ by unscaled on Thursday January 26, 2017 @12:42PM (#13493400)
The 'original sin' of C++ is not having both references and pointers, but trying to remain compatible with C.

That means that Stroustrup couldn't have ditched pointers, but if he wanted to implement operator overloading for value types with same efficiency as C he needed some way to support doing that without using pointers directly: http://www.stroustrup.com/bs_faq2.html#pointers-and-referenc... http://stackoverflow.com/questions/8007832/could-operator-ov...

A lot of the nastiness of C++ comes from trying to maintain C compatibility: Special behavior for POD, most vexing parse, .h/.cc file split, everything preprocessor and many other misfeatures. Of course, there's also the flip side of it: if C++ wasn't a near-superset of C, it would have never become so popular.

Re:C++11 FAQ by cmrdporcupine on Friday January 27, 2017 @12:26PM (#13501113)
Yeah I agree that C compatibility is the fail. But it's also the only reason C++ is around today. There were plenty of other compiled systems languages with OO or module systems floated in the 80s, including the quite capable Modula-2/3s, various Pascal dialects, etc. Of all of them only C++ (and Objective-C because iOS) has any relevance today. And likely because there was a kind of path to trendy-OO for existing C programmers and shops.
Re:C++11 FAQ by JoeAltmaier on Thursday January 26, 2017 @10:42AM (#13492217)
Surely references have intrinsic value to the programmer? They're a pointer that can't be moved or rebased. Other languages have only references, and in C++ you can use that convention and not have any extra confusion.
Re:C++11 FAQ by makecheck on Thursday January 26, 2017 @10:55AM (#13492353)
Except that references still can be bad: invalidated later on by an object deletion, no matter how many rules were enforced to assign the reference to begin with. And in an almost-worse sense, "sometimes" references can prevent this and sometimes not. Just not good enough, while syntactically making it harder to tell that references are being used in function calls and such.
Re:C++11 FAQ by cousin_it on Thursday January 26, 2017 @12:59PM (#13493573)
References are crazy. There's no simple guideline to use them safely. Check this out:

    const string& s = max<string>("a", "b");
    cout << s;
Standard types and functions, const references, no warnings, everything by the book. But it crashes.

There's a similar can of worms related to slicing (treating Derived* as Base* is silently unsafe because arrays and copy constructors exist). C++ is scary.

Re:C++11 FAQ by qcoh on Thursday January 26, 2017 @02:04PM (#13494239)
Works for me in both C++03 and C++14? https://ideone.com/KhfGaN
Re:C++11 FAQ by cousin_it on Thursday January 26, 2017 @03:00PM (#13494773)
Your code is not the same as my code and you're probably new to C++. I suggest trying two changes:

1) Replace max("a", "b") with max("b", "a"). Run it, look closely at the result, and be enlightened.

2) Replace max("a", "b") with max<string>("a", "b"). Run it, look at the result, and be enlightened in a different way.

As a small hint, your code invokes unspecified behavior, while my code invokes undefined behavior.

If this exercise doesn't put the fear of C++ into you, then I don't know what will :-)

Re:C++11 FAQ by qcoh on Thursday January 26, 2017 @04:27PM (#13495385)
Sorry, can you clarify? Adding the template argument causes a crash on idone, but I have no idea why that happens. Moreover, the output on my computer is always b\n.

EDIT: Not sure if this is it, but after some digging I've found [0] on lifetimes of temporaries. As for the lacking template argument, presumably const char* is inferred and a temporary string is constructed in main?

[0] http://stackoverflow.com/a/2784304

Re:C++11 FAQ by cousin_it on Thursday January 26, 2017 @06:10PM (#13496245)
So first of all, max("a", "b") expands to max<const char*>("a", "b"). It computes the maximum of two pointers, without looking at the characters at all. Comparing two pointers to unrelated objects is unspecified behavior, but in this case it usually returns the second pointer.

As for max<string>("a", "b"), it implicitly converts both arguments into temporary strings, then returns a const reference to one of them. Since it's a reference to a temporary, it becomes dangling when max returns, but you can assign it to a const string& anyway. When you try to access it, you'll get garbage or crash.

Re:C++11 FAQ by qcoh on Thursday January 26, 2017 @06:15PM (#13496286)
Thank you for the explanation! I'll have to look out for that one...
Re:C++11 FAQ by cbsmith on Thursday January 26, 2017 @01:10PM (#13493694)
> Arguably the std::move stuff and the semantics around it have added uncomfortable complexity to the language, even if it might have been necessary.

I think the main pain with move semantics was that it had to be bolted on to the language later. Consider that factor, they did an amazing job with it.

Re:C++11 FAQ by Koshkin on Thursday January 26, 2017 @01:56PM (#13494158)
No, the original sin was C's and it was the use of a separate "arrow" operator for accessing fields of a struct through a pointer. Other languages (C#, Java) successfully avoided that. C++ references allow templated code to be agnostic of whether an object is given by value or by reference, because the syntax is now more uniform.
Re:C++11 FAQ by dragontamer on Thursday January 26, 2017 @10:53AM (#13492340)
> Arguably the std::move stuff and the semantics around it have added uncomfortable complexity to the language

Compared to using std::auto?

Nah man. std::move is far easier to understand than trying to shove both concepts down operator=. std::unique is simply easier to use than std::auto by any real measurement.

Re:C++11 FAQ by cmrdporcupine on Thursday January 26, 2017 @10:55AM (#13492357)
My perhaps naive uneducated opinion: they should have added syntactic sugar for it instead of making it look like a function. A new operator perhaps.
Re:C++11 FAQ by kevinnk on Thursday January 26, 2017 @12:55PM (#13493526)
How does adding an operator help? There are two main advantage of having move semantics in the language and at least one of them relies on the fact that moves are implicit; you can write code that will move objects if supported and copy/destroy if not (for example, when returning an object or using an intermediate value in an expression). Adding an operator erases that advantage.

The other advantage is that you can force only move semantics which allows enforcing things like ownership. Adding an operator doesn't destroy this advantage, but it is a bit silly since you're just adding line noise for something that really should be implicit anyway.

Unless you just literally don't like the spelling of "std::move" which seems pretty lame since it should be relatively rare anyway.

Re:C++11 FAQ by dragontamer on Thursday January 26, 2017 @10:59AM (#13492395)
> A new operator perhaps.

That'd invalidate a lot of programs. Just like how the new _ operator in Java is killing a lot of code right now.

Every symbol that can be used... has been used. "Move" is the meaning of the operator in any case. Its no less readable than say... Python's __lshift__ or __add__.

Re:C++11 FAQ by sqeaky on Thursday January 26, 2017 @11:33AM (#13492744)
What if a hypothetical new operator used only characters already not allowed in identifiers and composed of characters not allowed in contiguous operator sequences.

Consider: :=, <-=, <|, $,

Re:C++11 FAQ by cbsmith on Thursday January 26, 2017 @01:18PM (#13493768)
AFAIK, _ isn't an operator in Java (http://docs.oracle.com/javase/specs/jls/se8/html/jls-3.html#...). The language does allow _ to be used as a separator in numeric literals.

Is there a new operator in some upcoming version of the language specification?

Re:C++11 FAQ by yrro on Thursday January 26, 2017 @02:22PM (#13494386)
_ is a keyword in Java 9.
Re:C++11 FAQ by cbsmith on Friday January 27, 2017 @02:35AM (#13498327)
It isn't an operator though, right?
Re:C++11 FAQ by yrro on Friday January 27, 2017 @11:10AM (#13500571)
That's correct, I only intended to clarify your point.
Re:C++11 FAQ by deong on Thursday January 26, 2017 @12:16PM (#13493169)
The thing is that something like computing primes with template instantiations was always a little weird and came with problems around sensible build processes. The rules were...well...complicated, but not that complicated. You had ADL rules that were weird, but basically, you could view a lot of the template hackery as a weird thing that you could understand without too much trouble, but probably didn't need to. That's much less true with most of the C++-11/14/17 features.

C++ has always been complex, but I defy anyone to read "Effective Modern C++" from cover to cover without clutching their pearls in horror.

Don't get me wrong, I actually like C++ in a weird way. There's nothing else out there that goes quite so far in putting you the programmer in charge while still attempting to let you work at a slightly higher level. But the price in cognitive load for this flexibility is just stupidly high.

Re:C++11 FAQ by cbsmith on Thursday January 26, 2017 @01:06PM (#13493652)
> C++ has always been complex, but I defy anyone to read "Effective Modern C++" from cover to cover without clutching their pearls in horror.

Actually, Effective Modern C++ was pretty awesome. A good guide through all the complexity.

Re:C++11 FAQ by deong on Thursday January 26, 2017 @01:52PM (#13494114)
Oh, the book is awesome. I mean the fact that such a book had to be written is a pretty rough statement about the language.
Re:C++11 FAQ by kazinator on Thursday January 26, 2017 @03:05PM (#13494813)
> I find C++ today to be far simpler, more expressive

That is logically impossible, since it hasn't removed anything.

The myopic mantra "just don't use what you don't like" breaks down as soon as you work in a team, where you don't dictate what other's cannot use (let alone what code they inherit).

Re:C++11 FAQ by huhtenberg on Thursday January 26, 2017 @11:19AM (#13492611)
I started with C++ around '92, but you are right, C++ was already complex back then, but it was still manageable, you could, sort of, hold its larger picture entirely in your head and still had some elegance to it.
Re:C++11 FAQ by unscaled on Thursday January 26, 2017 @12:18PM (#13493187)
1992 was just the year MFC came out. I would go as far as saying that C++ of the early '90s was at its Nadir of inelegance. I'd go as far as saying that C++ frameworks of the early 90s were the absolute nadir of elegance.

STL only started getting into compilers around '95, so we had no standard containers and dozens of different string implementations. The only part of the standard library widely available was iostreams, which is easily the most despised part of that library.

With no useful standard library to speak of, C++ devs were basically using the C standard library, rife with such shining gems of perfection as scanf(), strcat() and dear_hacker_please_inject_shellcode_here(). Since no generic containers were in sight, pretty much all 90s code I've had the pleasure to see was infested with macros. Pieces of exquisite beauty. I still have nightmares sometimes.

Then came the late 90s and early 2000s. The STL was widely supported, Boost started to gain ground and Andrei Alexandrescu released Modern C++ Design. Template metaprogramming slowly got out of hand and both code and errors were indecipherable.

The thing is, C++11 and beyond is the very opposite of this. Hairy template metaprogramming is replaced by simple and straightforward constexprs. Proper lambdas obsoleted functors, a gang of bloated design patterns (Visitor, Obeserver, Strategy, Command, Template Method, Decorator and so on) and several complicated lambda libraries from Boost.

Modern C++ is still a mess, but I believe it's way more elegant than ever before.

Re:C++11 FAQ by cbsmith on Thursday January 26, 2017 @01:09PM (#13493686)
> I would go as far as saying that C++ of the early '90s was at its Nadir of inelegance.

Yup. '92 C++ was what gave Java such a boost. If we'd somehow started with '98 C++, or better still C++11, Java might never have picked up so much momentum.

Re:C++11 FAQ by pjmlp on Thursday January 26, 2017 @02:15PM (#13494331)
Java picked momentum because in 1996, ANSI C++98 wasn't a thing, each compiler was catching up with the standard and many library vendors just gave use C libraries with us having to write C++ wrappers ourselves.

Also in 2000 I was writing K&R C on a HP-UX compiler, let alone the state of C++ compilers for writing portable code.

Re:C++11 FAQ by cbsmith on Friday January 27, 2017 @02:36AM (#13498332)
> Java picked momentum because in 1996, ANSI C++98 wasn't a thing, each compiler was catching up with the standard and many library vendors just gave use C libraries with us having to write C++ wrappers ourselves.

Yes. The experience in the early 90's meant everyone was looking for a saner choice. By the time C++ was the saner choice, Java had already received a giant boost.

Re:C++11 FAQ by pjmlp on Thursday January 26, 2017 @02:13PM (#13494303)
> 1992 was just the year MFC came out.

Ignoring the nice work of PowerPlant , Turbo Vision and Object Windows Library, because they were too high level for C devs.

So Microsoft ripped off their Application Frameworks (Afx) prototype and we got MFC instead.

Re:C++11 FAQ by huhtenberg on Thursday January 26, 2017 @02:49PM (#13494654)
OWL and TurboVision... now these are names I haven't heard in a long time. I remember the company I interned at was looking for TurboVision programmers at some point, none were found, soin a true Russian fashion they just wrote their own clone of it.
Re:C++11 FAQ by pjmlp on Thursday January 26, 2017 @03:49PM (#13495124)
I used Turbo Vision in Turbo Pascal 6/7, then migrated to Turbo Pascal for Windows 1.5 with OWL and eventually to Turbo C++ 3.1 with OWL.
Re:C++11 FAQ by banachtarski on Thursday January 26, 2017 @11:40AM (#13492810)
As a dissenting opinion from someone who has not quite 20 years of experience with C/C++ but 14, modern C++ is what brought me back to the language. The idioms allow me to use the language more functionally. More importantly, the STL is actually usable now and you can just code using it and std::algorithm without thinking of the nuts and bolts of move assignment and stuff at all. In the case where you need performance, you have the paradigm at your disposal. Also, you have a ref counted pointer thread safe pointer! A means of transferring ownership so heap allocated objects can also follow the same RAII pattern!

I have a much easier time holding the entire picture together but others are correct in saying you have to throw away old conceptions and ideas of the language. I personally have thrown away the way I think about C entirely (at least when I code in modern C++).

Re:C++11 FAQ by kazinator on Thursday January 26, 2017 @03:12PM (#13494860)
C++ still cannot compete with proper high level languages in this area.

C++ is precisely useful because it's a better C: it has a C-like subset, and works directly with C data structures and function call interfaces. Plus it has features to do that kind of programming in a safer, more managed way.

I would absolutely not use C++ for anything that isn't in the area of "this should be ideally written in C, but that would bring in undue difficulties, risks and time".

The more C++ moves away from its focus of being a language for writing low-levelish systems middleware, the more it loses its relevance.

> Also, you have a ref counted pointer thread safe pointer!

Had those in 1997 using draft ISO C++, thanks.

Re:C++11 FAQ by MichaelMoser123 on Saturday January 28, 2017 @09:11PM (#13511369)
just be careful with those ref counted pointers: shared_ptr/weak_ptr introduce a lot of atomic variable access. if you use them from a single thread then that's pure overhead.
Re:C++11 FAQ by banachtarski on Tuesday January 31, 2017 @02:54AM (#13528611)
Yes, of course. A big chunk of my time at various previous companies was removing usage of such things when not necessary. It's also not "a lot" of atomic variable access but you do need a strong fence to provide the correct semantics (so it is some). To what degree "a lot" or "some" is depends obviously on what you're doing.
Re:C++11 FAQ by cbsmith on Thursday January 26, 2017 @01:08PM (#13493673)
Honestly, back in '92 the language seemed easy, but the practice was hideously complex and error prone. Most people still couldn't even figure out how to do exceptions properly. I would argue that today, the language is more complex, but the practice is comparatively simpler (still complex as a ll get out, but compared to '92...).
Re:C++11 FAQ by otabdeveloper on Thursday January 26, 2017 @12:20PM (#13493203)
C++ occupies the same mental space that languages like Haskell, Scala or OCaml.

Compared to its real competition, C++ is very elegant and a joy to use. These languages are meant for enjoying the maximum out of compile-time type abstractions, not as an easy-to-use tool for simple enterprise apps.

Re:C++11 FAQ by hacker_9 on Thursday January 26, 2017 @10:44AM (#13492243)
I agree. The other day I had to dive into the libigl [1] matrix structure (for those that don't know, a matrix is basically a 4x4 grid of numbers). What I found was over 10 levels of inheritance, along with rampant template use and macros _everywhere_. It actually took so long to parse I ended up just changing my algorithm completely to avoid having to use it. I have utmost respect for anyone that can work with C++ day to day, but I'll be staying away thanks.

[1] https://github.com/libigl/libigl/

Re:C++11 FAQ by rkangel on Thursday January 26, 2017 @10:58AM (#13492387)
The problem is that you can find bad code in any language. It's difficult to tell how much that is the fault of the language, and how much is the fault of that particular author.

I'm not defending C++ here, I actually agree with you, but it's difficult to provide decent evidence for its failings.

Re:C++11 FAQ by dimatura on Thursday January 26, 2017 @05:55PM (#13496142)
Doesn't libigl use Eigen for matrices? Eigen is a full-featured matrix library with a pretty decent API. If you just need a 4x4 grid of numbers, then you don't really need a library, sure. But once you need to do matrix arithmetic, basic linear algebra, various forms of indexing, mixing matrices of different types (e.g. float/double/int/etc), things get complicated, fast. A complex library like igl needs all this and more. I'm guessing this is why there's so many matrix libraries - everyone prefers rolling their own, after all, how hard can it be? (I'm guilty of this, so I'd know. But I reach for Eigen most of the time these days).
Re:C++11 FAQ by cbsmith on Thursday January 26, 2017 @01:23PM (#13493812)
Odd. I wonder why they didn't just use Boost uBLAS or similar.
Re:C++11 FAQ by claudius on Thursday January 26, 2017 @03:41PM (#13495073)
Last time I checked, Boost uBLAS was horribly slow and one should not use it. Use Eigen or Blitz++ (or just call BLAS directly) instead.
Re:C++11 FAQ by cbsmith on Friday January 27, 2017 @02:29AM (#13498316)
That's what I meant... Though Boost uBLAS is still way faster than a deeply inherited 4x4 matrix...
Re:C++11 FAQ by arximboldi on Thursday January 26, 2017 @10:25AM (#13492056)
Interesting that you mention Rust... I am one of those "modern C++" kinds and I am quite curious and excited about Rust (haven't quite jumped boat yet though). I feel that there are quite a few others in such position.

And precisely the reason we like Rust is because it is like the new C++ (moves, lean lambdas, templates, on-the-stack values, borrowing) without so much of the old stuff. What do you think? What do you expect from Rust?

Re:C++11 FAQ by santaclaus on Thursday January 26, 2017 @10:14AM (#13491972)
> move semantics

Move semantics have been great, in my experience (enabling things like unique_ptr). What is causing issues here?

Re:C++11 FAQ by fauigerzigerk on Thursday January 26, 2017 @10:20AM (#13492016)
Move semantics are very useful, but there's also something wrong if articles like this are necessary or even possible:

https://isocpp.org/blog/2012/11/universal-references-in-c11-...

Re:C++11 FAQ by jasode on Thursday January 26, 2017 @10:54AM (#13492344)
Scott Meyer's articles (and numerous video presentations) on Universal References are educational but he doesn't make it clear to the audiences the bigger picture of where and why they'd need to really learn it.

The Forwarding Reference (aka Universal Reference) is for programmers writing generic templates. A lot of C++ programmers can do a ton of productive work and get by for years without writing any templates from scratch. Yes, they use others' templates (such as STL/Boost libraries) but they don't necessarily write their own. I have no survey data but I'll take a wild guess that less than 1% of C++ programmers need to memorize template Forward References.

As an analogy using the plain C Language, it's as if someone created very prominent blogs about the complexity of "char ∗(∗(∗a[])())()" with long paragraphs explaining how it's "an array of pointers to functions returning pointer to function returning pointer to char".

If that type of essay had a lot of visibility, people might think that "Wow the C Language is difficult and too complicated!" In reality, a lot of C programmers don't write complex declarations like that. The more common pointer-to-function for something like qsort() is very easy to write.

Re:C++11 FAQ by fauigerzigerk on Thursday January 26, 2017 @12:02PM (#13493051)
"char ∗(∗(∗a[])())()" may have entertainment value in an obfuscated C contest, but it is otherwise useless.

Using && in templates may be advanced C++, but it is both useful and mainstream.

You're essentially saying, "don't worry, no one uses the new language features anyway". But that's not a convincing response to a complaint about the incredible complexity introduced by a particular new language feature.

Re:C++11 FAQ by jasode on Thursday January 26, 2017 @12:21PM (#13493209)
>You're essentially saying, "don't worry, no one uses the new language features anyway".

No, I'm not saying that. A lot of C++ programmers are application programmers who glue together Qt GUI with some code to read a TCPIP socket or file and write out some data. Many C++ programmers simply don't have the day-to-day need to write generic templates (libraries).

Yes, it may be useful and mainstream to you but I don't think that is reflective of the whole C++ programming community at large.

>But that's not a convincing response to a complaint about the incredible complexity introduced by a particular new language feature.

When I studied it, the "&&" syntax and type deduction rules seem to be "irreducible complexity". Every computer science problem that involves one set of syntax to write another syntax (meta template programming) is complicated. This includes XSLT to rewrite XML, or PHP code that dynamically writes javascript syntax embedded inside of HTML syntax. Reading any of that code-that-writes-code is always ugly. If we were to challenge a language designer to recreate a syntax that meets the same exact goals of C++ (perfectly pass parameters without casts, no unnecessary copies that kills performance, with static type checks, etc), he'd eventually end up at the same complexity you have now. In other words, there is no breakthrough A.I. compiler algorithm that lets the parser correctly infer how parameters pass through to generic code. If there's a whitepaper that claims otherwise, I'd love to read it. (Rust generics are simpler but they also do less than C++ templates.) The TLDR is that C++ templates is a code gen tool and like any other nontrivial code gen tool, they end up being complicated.

Re:C++11 FAQ by wruza on Friday January 27, 2017 @03:38AM (#13498507)
>Every computer science problem that involves one set of syntax to write another syntax (meta template programming) is complicated.

I'm not sure about 'meta' part you mentioning, but it seems that all the complexity of c++ templates comes from declarativity of these. If they were imperative — e.g. 'hey, compiler, put an additional if into specialization for that particular type', or produce specializations in a loop, or create template generators, etc — that would feel less bizarre. Deep inspection of seemingly simple terralang.org turned that upside down to me. These two languages (luajit/terra) are both not very popular, but the idea of simple imperative codegen is right there. I wish I were able to replace terra part with just C...

Re:C++11 FAQ by fauigerzigerk on Thursday January 26, 2017 @01:35PM (#13493926)
>When I studied it, the "&&" syntax and type deduction rules seem to be "irreducible complexity".

That may well be, given a particular set of constraints. But that is exactly the issue with C++ today. It's a conglomerate of powerful and diverse features, and so everything that gets added interacts in countless ways with everything that's already there. There's no orthogonality at all. Everything is both irreducibly and impossibly complex at the same time.

You're right that meta programming is inherently more complex than other issues. But it's not the only area where C++'s complexity is outgrowing our (or at least my) cognitive capacity if the goal is to write reasonably reliable code in a reasonably productive way.

Re:C++11 FAQ by HelloNurse on Thursday January 26, 2017 @11:47AM (#13492891)
" A lot of C++ programmers can do a ton of productive work and get by for years without writing any templates from scratch" as well as people who choose not to have a stove or oven in their kitchen can eat, but with the delusion that they are smartly avoiding difficulties.
Re:C++11 FAQ by bsaul on Thursday January 26, 2017 @10:30AM (#13492089)
Oh gosh... how come does anyone not realize what a dead end a language has become once this kind of article needs to be written ?
Re:C++11 FAQ by CJefferson on Thursday January 26, 2017 @10:53AM (#13492336)
My personal main problem is things like you can't template on an r-value reference, as T&& in a template matches both r-value and l-value references and then you need std::forward or std::move and then I start getting confused.

I wish in templates they had gone with the suggestion I saw to use T&&& to mean "r-value or l-value reference", and then let T&& just mean "r-value reference".

Re:C++11 FAQ by ytugiuyghvk on Thursday January 26, 2017 @11:14AM (#13492547)
If you want to template on an r-value reference, the easiest way is probably to use a forwarding reference and disable the template if the template parameter deduces to a reference

    template <class T, class = enable_if_t<!is_reference<T>::value>>
    auto f(T&& x);
Re:C++11 FAQ by weerd on Thursday January 26, 2017 @11:45AM (#13492866)
Is this C++14? Can you please explain the "class = ..." template parameter?
Re:C++11 FAQ by StephanTLavavej on Thursday January 26, 2017 @12:52PM (#13493491)
Yes, that's C++14.

First, "class = enable_if_t<!is_reference<T>::value>" is just "class Dummy = enable_if_t<!is_reference<T>::value>" that doesn't bother to name Dummy. It's providing a default template argument for a function template (this is a C++11 feature; in C++03, only class templates could have this).

Next, "enable_if_t<!is_reference<T>::value>" is a C++14 library feature (enable_if_t is an alias template; the Core Language gained alias templates in C++11, the library gained these in C++14). It is a synonym for "typename enable_if<!is_reference<T>::value>::type", which is more verbose (and what one had to type in C++11).

"is_reference<T>::value" is a C++11 type trait, that is true when T is X& or X&&, and false otherwise. (It's implemented with partial specializations, and a "static const bool value = true;" data member - actually constexpr these days, but no difference there. This is type traits 101.)

enable_if is a library helper for SFINAE. (Not necessarily C++11 Expression SFINAE; here, just C++03 classic SFINAE is being used.) Basically, enable_if<true>::type is void. enable_if<false>::type doesn't exist. This works with the Core Language's SFINAE rules to make function templates vanish from the overload set (if you don't know what SFINAE is, look it up; it's a little complicated, but it exists for good reasons, and it goes back to C++98).

So, this is how one writes a function template that vanishes under certain criteria. This is often desirable compared to doing different things for different types (that can often be done with "tag dispatch") or emitting compiler errors for certain types (that's a static_assert).

Re:C++11 FAQ by ytugiuyghvk on Thursday January 26, 2017 @12:44PM (#13493423)
class = X is just an anonymous template type parameter with default value X, just like

    auto foo(int = 0);
declares a function with a int parameter with default value 0. In this case, it's just a conventional place to stick an expression in the declaration to trigger SFINAE. If you don't need SFINAE, you can also just place the condition in a static_assert in the definition

    template <class T>
    auto foo(T&&) {
        static_assert(!is_reference<T>::value, "call me with an r-value");
        ...
    }
Re:C++11 FAQ by KKKKkkkk1 on Thursday January 26, 2017 @10:55AM (#13492350)
I'm having trouble understanding the differences between a * and a &, and now with move semantics we have stuff like &&, && &, and && &&. Please stop!
Re:C++11 FAQ by jimktrains2 on Thursday January 26, 2017 @12:34PM (#13493328)
I've come back to learn C++14 and it's _really_ nice. I love how lambdas, move semantics, templates, type inference, &c work. It leads to much cleaner and elegant code.

I'm still not so sure I like how iterators are designed, but maybe it'll grow on me?

Re:C++11 FAQ by KKKKkkkk1 on Thursday January 26, 2017 @10:48AM (#13492282)
But C++ was never easy to understand. For example, can you tell me off the top of your head, what are the conditions to get the compiler to generate a copy constructor and an assignment operator for a class? I have trouble answering that question even with the help of Google, and you're talking pre-Google times.
Re:C++11 FAQ by sqeaky on Thursday January 26, 2017 @11:41AM (#13492821)
The rules really aren't that hard for practical use. Of course pedantic rules in the standard are much more complex and corner cases can bite us.

If you define no constructors then the compiler will generate a default constructor with no args, a copy constructor, a move constructor and an assignment operator. If any class data members don't have one of those then the class you are writing won't have one either.

The simplest practical rule is define none of them or define all of them. It is not often, perhaps one in ten classes, that you should do something else.

If wind up using C++ for more than a small project, than you ought read up and not use simple heuristics like this.

Re:C++11 FAQ by blub on Thursday January 26, 2017 @10:32AM (#13492106)
That pocket knife is a collector's item. It includes most if not all the individual tools available in different models from Wenger. Victorinox also has one.

The problem is that it's not useful as such and I guess most people wouldn't buy one. I wouldn't mind receiving one as a gift though :)

Regarding C++, if I remember my programming language history right, there aren't many languages that are that old, popular, available in so many domains and still evolving to keep up with the times.

Language design has progressed a lot, the hardware has advanced at an exceptional pace. Today's context is very different.

I say we wait another 20 years to see how Rust & D are doing. Python might be old, but it only really became popular this century, as Perl declined. I estimate that C will continue its slow decline with time.

Re:C++11 FAQ by cbsmith on Thursday January 26, 2017 @01:04PM (#13493628)
The mistake is looking at C++ as just an enhanced C (understandable given the name, the marketing, etc.). It's kind of like when they marketed Windows as a DOS upgrade...

In reality, C++ is an entirely different language that provides partial C compatibility (in fairness, it is more compatible than just about any other language out there) in order to improve adoption and minimize the impedance mismatch with systems interfaces (which, at least back in the day, were predominantly C, and largely still are).

If we called "C++" "NotC", and then wrapped all the C compatibility features (type coercion, malloc()/free(), C strings, etc.) with a "unsafe mode" flag, it'd all make much more sense.

Re:C++11 FAQ by athenot on Thursday January 26, 2017 @10:25AM (#13492052)
What you paint as a fault might be an asset: C++ is multi-paradigm. There is more than one way to look at something and there is a joyous chaos of varied abstractions from which to choose from.

Yes it takes a certain openness of mind and a long learning curve. But then, you get to operate at a level that other platforms can only dream.

In full disclosure, I do NOT consider myself a good C++ programmer. But I've always respected the fact that it's one environment which fosters using the whole toolbox instead of just a hammer... no matter how elegant that hammer may be. In that respect, it reminds me a lot of Perl.

Re:C++11 FAQ by huhtenberg on Thursday January 26, 2017 @10:33AM (#13492116)
> C++ is multi-paradigm

Yep, here it is - http://i.imgur.com/1oGHYqi.jpg :)

Re:C++11 FAQ by saalweachter on Thursday January 26, 2017 @10:40AM (#13492190)
Just out of curiosity, which era of C++ did you like? C++98, or pre-Standard C++?

At least since C++98, C++ has always had the "multi-paradigm problem". If you try to use every language feature and paradigm C++ has to offer, you are going to suffer. Writing and maintaining a large C++ codebase has always required restricting yourself to a subset of the language.

Re:C++11 FAQ by segmondy on Thursday January 26, 2017 @10:31AM (#13492094)
How well has Perl fared? How about Lisp and Scala that are multi-paradigm, how well are they doing?
Re:C++11 FAQ by GFK_of_xmaspast on Thursday January 26, 2017 @11:16AM (#13492567)
Perl was doing just fine until they fell in the perl6 hole and stagnated. Scala's getting its data science niche, and lisp has a lot more problems than just being multi-paradigm.
Re:C++11 FAQ by gpderetta on Thursday January 26, 2017 @11:45AM (#13492867)
> Perl was doing just fine until they fell in the perl6 hole and stagnate

i.e. backward compatibility is king.

Paraphrasing Stroustrup, there are two kinds of languages, those that are full of old cruft and those that are too green to have been proven in the field.

Re:C++11 FAQ by GFK_of_xmaspast on Thursday January 26, 2017 @12:53PM (#13493508)
The perl6 problem wasn't 'backward compatibility', the perl6 problem was 'this thing doesn't exist at all but it's sucking up all the momentum.'
Re:C++11 FAQ by shmerl on Thursday January 26, 2017 @11:32AM (#13492731)
C+11 is a different language. Learn it ;) And move semantics is a good thing. If you are fed up with C++ though - try Rust.
Re:C++11 FAQ by andrepd on Thursday January 26, 2017 @11:13AM (#13492528)
Template metaprogramming is not something new, it's old, and indeed much of Modern C++ (e.g. constexpr) is made to replace the complicated TMP with simpler and just-as-powerful abstractions.

Can you name another language that supports the many high-level abstractions that C++ supports (OOP, generic programming) while being just as fast? Only D and Rust come to mind, and they are neither as fast nor, crucially, as well-developed as C++. The amount of resources and existing code in C++ is staggering. Newer languages such as D and Rust simply can't compete.

Re:C++11 FAQ by groovy2shoes on Thursday January 26, 2017 @01:12PM (#13493708)
Modula-3. Bonus points are awarded to Modula-3 and Rust for safety.
Re:C++11 FAQ by waynecochran on Thursday January 26, 2017 @11:24AM (#13492660)
Ada.
Re:C++11 FAQ by steveklabnik on Thursday January 26, 2017 @12:23PM (#13493233)
If Rust is slower than the equivalent C++, that's a bug. Please file them.
Re:C++11 FAQ by utopcell on Thursday January 26, 2017 @10:08AM (#13491930)
some of the pain points you refer to, esp move semantics, bring a lot of additional performance to the table. Would you feel the same way about C++ if you started now and only had to learn a clean C++11 subset going forward ?
Re:C++11 FAQ by maxlybbert on Thursday January 26, 2017 @10:15AM (#13491978)
I've often wondered how anybody manages to teach C++ today. I love working with the language, and I understand the reason behind many of the features, but I can't help but feel like it would be impossible to teach to beginners.
Re:C++11 FAQ by ant6n on Thursday January 26, 2017 @11:40AM (#13492812)
"...but I can't help but feel like it would be impossible to teach to beginners."

So a relatively easy way to learn C++ is as an 'upgrade' to C, starting of with picking the parts of the language that help you the most:

* you start by already knowing C, but maybe not feeling super productive, using it as structs + functions

* you set up the C++ compiler (most modern version available), and just continue writing C

* you start using streams to print (because it can be more convenient than printf)

* you start using std::vector and std::string, arrays being one of the big pain points of C

* you start using `auto` and for-in loops

* you start using simple classes, without any inheritance. just structs with methods

* you start adding operators - so much fun!

* you start learning about references and const, and suddenly all your method arguments become `const T& v`

* you learn about not using pointers (as much on stack as possible), move semantics, shared/unique pointers. This means you'll also use more templates.

* you deepen your understanding of writing your move/copy constructors. Learn RIAA, and become a fan of `}`.

* you learn about constexpr and constexpr functions

* this is already a pretty happy subset of C++, and as you learn to use templates, you may at some point start writing one yourself. Same with lambdas - if you need them you learn them.

Re:C++11 FAQ by _delirium on Thursday January 26, 2017 @10:27AM (#13492075)
The norm in the game industry is usually to expect some kind of background in low-level programming (maybe C, maybe some version of C++), and then teach new employees a very specific, restricted subset of C++ that's the in-house dialect (and every company has its own, different subset).
Re:C++11 FAQ by kire456 on Thursday January 26, 2017 @10:35AM (#13492141)
Fwiw, I followed this course at my university[1]. The 'schedule' and 'setup' links provide an idea of what is treated, and the full book is available[2]. The full course took slightly over six months, so yes, it takes a while :)

1. http://www.icce.rug.nl/edu/ 2. http://www.icce.rug.nl/documents/cplusplus/

Re:C++11 FAQ by baq on Thursday January 26, 2017 @10:29AM (#13492087)
that's because it is impossible. it takes years to master the language and that was before i lost touch with it around 2010 back when C++11 was TR1 or whatnot.

i understand that what is usually considered good form is trying to completely forget about C features like pointers and arrays and use their STL counterparts like unique/shared_ptr, std::vector, std::array and iterators. this gets you a nice modern subset of the language that makes it relatively difficult to shoot yourself in the foot.

Re:C++11 FAQ by maxlybbert on Thursday January 26, 2017 @10:46AM (#13492262)
I didn't use C-style string functions for the longest time. If I had a char*, perhaps because I got it from some C library we were using, I would turn it into a std::string and use it's functions and operators. One day, I realized how silly that was: I'm sure I was causing gratuitous memory allocations (not all strings qualify for the short string optimization).

Perhaps part of my hangup is the expectation that you would teach the difference between, say, enum and enum class. There are good reasons to use enum, and I believe there always will be. There are good reasons to use pointers (in fact, one of the main reasons I use pointers is to point to the payload of a std::unique_ptr, and I use std::unique_ptr when I have an obvious owner, even if I might need other functions to access the payload while the owner is still around).

So I don't think that it's possible to ignore "the old ways" completely.

Re:C++11 FAQ by baq on Thursday January 26, 2017 @11:19AM (#13492602)
it isn't possible if you're doing real work, but it is possible if you're learning or teaching, especially if stdin and stdout are the only ways your program will do IO. it's actually pretty nice and code is surprisingly concise, especially if you use stream iterators.
Re:C++11 FAQ by JackdawX on Thursday January 26, 2017 @11:06AM (#13492468)
Here is the course I was taught by at university:

http://www.dcs.bbk.ac.uk/~roger/cpp/

Lots of value came from the lectures with roger. Sadly he has retired, it would have been nice to have them up on youtube.

Re:C++11 FAQ by speedkills on Thursday January 26, 2017 @10:25AM (#13492059)
Maybe they don't bother. PSU is still teaching C++98.
Re:C++11 FAQ by maxlybbert on Thursday January 26, 2017 @10:27AM (#13492071)
That was the thing: starting with C++98, I was able to pick up C++11. But starting from scratch? I'm not sure.
Re:C++11 FAQ by cmrdporcupine on Thursday January 26, 2017 @10:43AM (#13492232)
Wow I feel the opposite. Because C++98 and earlier were so deficient in a lot of ways, people who got clever with it often ended up down a rabbit hole of template metaprogramming, boost:: bloat, custom classes for callback stuff, custom classes for reference counting or other smart pointers, etc. etc. Unlearning all that took me some time.

In my 5 years at Google, I've watched many developers start from scratch on our subset of modern C++. There doesn't seem to be a huge challenge with it.

Re:C++11 FAQ by acqq on Thursday January 26, 2017 @11:48AM (#13492892)
Is the subset of boost in Google still the same as the public one?

https://google.github.io/styleguide/cppguide.html

It it is, I consider Google very lucky to have these who decided not to allow everything.

Re:C++11 FAQ by izacus on Thursday January 26, 2017 @10:36AM (#13492147)
We have a rather lagerish codebase of C++11/14 and we manage to get people coming from other languages (Java / ObjC) to start working with it just fine. Modern C++ is pretty decent and readable (excluding some quirks of STL naming).

Of course good code reviews and testing is a must to help people to get up to speed and stop shooting themselves in the foot :)

Re:C++11 FAQ by groovy2shoes on Thursday January 26, 2017 @01:27PM (#13493846)
One of C++'s most glaring problems is that everybody only ever uses some subset of some version of the language, but you still need to know basically the entire massive, monstrous language because not everybody uses the same subset and you need to be prepared for anything. On top of that, you're lucky if your employer or potential recipient of contributions (e.g., FOSS project) or whatever has actually codified the subset they want to you to use: most of the time, you need to infer the allowable subset from the existing code.
Re:C++11 FAQ by mmargerum on Friday January 27, 2017 @10:38PM (#13504736)
I would say Go is the first language since C where there is not really a subset to use. Every construct has a distinct purpose.
Re:C++11 FAQ by groovy2shoes on Wednesday February 01, 2017 @02:29AM (#13539036)
I would say that's cute.
Re:C++11 FAQ by pjmlp on Thursday January 26, 2017 @02:18PM (#13494348)
It applies to most mainstream languages, even Python has subsets.
Re:C++11 FAQ by groovy2shoes on Thursday January 26, 2017 @03:21PM (#13494935)
I've written code in over 50 different programming languages at this point (though only about a dozen or so professionally, including Python), and the only languages where I've ever been asked or required to work with a subset in lieu of the full language have been C++ and Perl. I've never worked on a project or for a company that allowed unrestricted use of all of C++.
Re:C++11 FAQ by sandeatr on Thursday January 26, 2017 @10:41AM (#13492196)
The things you are complaining about are what make the language worth using-
Re:C++11 FAQ by kitd on Thursday January 26, 2017 @11:18AM (#13492597)
I returned to C++ 3 years ago, having previously used it in the mid-1990s. I tend to agree with you, but I found that it was necessary to forget my old C mindset (pretty easy since it was 20 years old) and start learning modern C++ idioms from scratch.

Eg, back in the days, I could fling raw pointers around with abandon. Now they need to be handled with care, and there are many tools and patterns available for you not to have to deal with them at all.

Re:C++11 FAQ by VodkaHaze on Thursday January 26, 2017 @01:08PM (#13493670)
> fling raw pointers around with abandon.

Jitters in seat

Re:C++11 FAQ by zwieback on Thursday January 26, 2017 @11:35AM (#13492756)
I feel your pain but the canonical response is that you don't have to use the new features if you don't want to. If you have to work with other people's C++ code you may be in trouble.

I have the same arc as you, but every time I come back to C++ (from C# or Python) I'm surprised how much I enjoy it. I look at the new stuff more as a way to bring features from scripting or functional languages to a real language - makes me happy.

Re:C++11 FAQ by gpderetta on Thursday January 26, 2017 @11:37AM (#13492777)
> ass-backwards closures

that's very surprising. I would say that C++ lambda expressions have been an incredible success and probably the best thing to come out of C++11.

For example, rust started with boxed closures, because that's what all the 'proper' languages do. They were forced to switch to distinctly-typed, unboxed closures with similar capture modifiers to be competitive with C++ [1].

Re:C++11 FAQ by steveklabnik on Thursday January 26, 2017 @12:25PM (#13493250)
Your link got eaten, but we don't have capture modifiers anymore. Captures are inferred, and you can override this with a keyword to take all captures by value instead. This still lets you get the same effect as C++, but we find that it's generally less verbose. It depends though!
Re:C++11 FAQ by gpderetta on Thursday January 26, 2017 @12:46PM (#13493437)
> you can override this with a keyword to take all captures by value instead

that's what I meant by modifiers :). It is not unlike [&] and [=] I guess (except for the "tiny" detail that lifetimes are checked).

BTW, I'm not sure what the [1] reference in my comment was supposed to point to though.

Re:C++11 FAQ by MichaelMoser123 on Saturday January 28, 2017 @09:18PM (#13511412)
move semantics helps you to get rid of temporary objects. otherwise Object a,b,c; ... a = b + c; will create a temporary for b+c before it is assigned to a. The elegance of operator overloading got us there - no need for it without operator overloading.

Me too thought that template meta-programming is just a waste of time; i was surprised that std::tuple uses this stuff.

Re:C++11 FAQ by ytugiuyghvk on Thursday January 26, 2017 @10:36AM (#13492142)
What's wrong with C++'s closures?
Re:C++11 FAQ by alpineidyll3 on Thursday January 26, 2017 @06:48PM (#13496510)
The less I use C++ the happier I am.
Re:C++11 FAQ by kazinator on Thursday January 26, 2017 @12:43PM (#13493410)

  #include "parent-comment"
Me too, exactly. C++ has turned to baroque junk. The last useful new feature C++ acquired was to make string literals const. (When was that, 2005 or 6?)

If you're using C++, it's best to stick with C++03.

The rabid experimenters who run the ISO C++ committee should have started their own language 15 years ago, rather than hijacking an industry standard to everyone's detriment.