Which C++ idioms are deprecated in C++11?

C++C++11C++ Faq

C++ Problem Overview


With the new standard, there are new ways of doing things, and many are nicer than the old ways, but the old way is still fine. It's also clear that the new standard doesn't officially deprecate very much, for backward compatibility reasons. So the question that remains is:

What old ways of coding are definitely inferior to C++11 styles, and what can we now do instead?

In answering this, you may skip the obvious things like "use auto variables".

C++ Solutions


Solution 1 - C++

  1. Final Class: C++11 provides the final specifier to prevent class derivation
  2. C++11 lambdas substantially reduce the need for named function object (functor) classes.
  3. Move Constructor: The magical ways in which std::auto_ptr works are no longer needed due to first-class support for rvalue references.
  4. Safe bool: This was mentioned earlier. Explicit operators of C++11 obviate this very common C++03 idiom.
  5. Shrink-to-fit: Many C++11 STL containers provide a shrink_to_fit() member function, which should eliminate the need swapping with a temporary.
  6. Temporary Base Class: Some old C++ libraries use this rather complex idiom. With move semantics it's no longer needed.
  7. Type Safe Enum Enumerations are very safe in C++11.
  8. Prohibiting heap allocation: The = delete syntax is a much more direct way of saying that a particular functionality is explicitly denied. This is applicable to preventing heap allocation (i.e., =delete for member operator new), preventing copies, assignment, etc.
  9. Templated typedef: Alias templates in C++11 reduce the need for simple templated typedefs. However, complex type generators still need meta functions.
  10. Some numerical compile-time computations, such as Fibonacci can be easily replaced using generalized constant expressions
  11. result_of: Uses of class template result_of should be replaced with decltype. I think result_of uses decltype when it is available.
  12. In-class member initializers save typing for default initialization of non-static members with default values.
  13. In new C++11 code NULL should be redefined as nullptr, but see STL's talk to learn why they decided against it.
  14. Expression template fanatics are delighted to have the trailing return type function syntax in C++11. No more 30-line long return types!

I think I'll stop there!

Solution 2 - C++

At one point in time it was argued that one should return by const value instead of just by value:

const A foo();
^^^^^

This was mostly harmless in C++98/03, and may have even caught a few bugs that looked like:

foo() = a;

But returning by const is contraindicated in C++11 because it inhibits move semantics:

A a = foo();  // foo will copy into a instead of move into it

So just relax and code:

A foo();  // return by non-const value

Solution 3 - C++

As soon as you can abandon 0 and NULL in favor of nullptr, do so!

In non-generic code the use of 0 or NULL is not such a big deal. But as soon as you start passing around null pointer constants in generic code the situation quickly changes. When you pass 0 to a template<class T> func(T) T gets deduced as an int and not as a null pointer constant. And it can not be converted back to a null pointer constant after that. This cascades into a quagmire of problems that simply do not exist if the universe used only nullptr.

C++11 does not deprecate 0 and NULL as null pointer constants. But you should code as if it did.

Solution 4 - C++

Safe bool idiomexplicit operator bool().

Private copy constructors (boost::noncopyable) → X(const X&) = delete

Simulating final class with private destructor and virtual inheritanceclass X final

Solution 5 - C++

One of the things that just make you avoid writing basic algorithms in C++11 is the availability of lambdas in combination with the algorithms provided by the standard library.

I'm using those now and it's incredible how often you just tell what you want to do by using count_if(), for_each() or other algorithms instead of having to write the damn loops again.

Once you're using a C++11 compiler with a complete C++11 standard library, you have no good excuse anymore to not use standard algorithms to build your's. Lambda just kill it.

Why?

In practice (after having used this way of writing algorithms myself) it feels far easier to read something that is built with straightforward words meaning what is done than with some loops that you have to uncrypt to know the meaning. That said, making lambda arguments automatically deduced would help a lot making the syntax more easily comparable to a raw loop.

Basically, reading algorithms made with standard algorithms are far easier as words hiding the implementation details of the loops.

I'm guessing only higher level algorithms have to be thought about now that we have lower level algorithms to build on.

Solution 6 - C++

You'll need to implement custom versions of swap less often. In C++03, an efficient non-throwing swap is often necessary to avoid costly and throwing copies, and since std::swap uses two copies, swap often has to be customized. In C++, std::swap uses move, and so the focus shifts on implementing efficient and non-throwing move constructors and move assignment operators. Since for these the default is often just fine, this will be much less work than in C++03.

Generally it's hard to predict which idioms will be used since they are created through experience. We can expect an "Effective C++11" maybe next year, and a "C++11 Coding Standards" only in three years because the necessary experience isn't there yet.

Solution 7 - C++

I do not know the name for it, but C++03 code often used the following construct as a replacement for missing move assignment:

std::map<Big, Bigger> createBigMap(); // returns by value

void example ()
{
  std::map<Big, Bigger> map;

  // ... some code using map

  createBigMap().swap(map);  // cheap swap
}

This avoided any copying due to copy elision combined with the swap above.

Solution 8 - C++

When I noticed that a compiler using the C++11 standard no longer faults the following code:

std::vector<std::vector<int>> a;

for supposedly containing operator>>, I began to dance. In the earlier versions one would have to do

std::vector<std::vector<int> > a;

To make matters worse, if you ever had to debug this, you know how horrendous are the error messages that come out of this.

I, however, do not know if this was "obvious" to you.

Solution 9 - C++

Return by value is no longer a problem. With move semantics and/or return value optimization (compiler dependent) coding functions are more natural with no overhead or cost (most of the time).

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAlan BaljeuView Question on Stackoverflow
Solution 1 - C++SumantView Answer on Stackoverflow
Solution 2 - C++Howard HinnantView Answer on Stackoverflow
Solution 3 - C++Howard HinnantView Answer on Stackoverflow
Solution 4 - C++kennytmView Answer on Stackoverflow
Solution 5 - C++KlaimView Answer on Stackoverflow
Solution 6 - C++PhilippView Answer on Stackoverflow
Solution 7 - C++AndrzejView Answer on Stackoverflow
Solution 8 - C++v010dyaView Answer on Stackoverflow
Solution 9 - C++Martin AView Answer on Stackoverflow