Over a million developers have joined DZone.

C++17 in Detail: Fixes and Deprecation

DZone's Guide to

C++17 in Detail: Fixes and Deprecation

If you develop in C++, this series is a must read. In Part 1, we'll cover the most important deprecations and fixes to C++ features in the soon to come update.

· Web Dev Zone ·
Free Resource

Read this guide to learn everything you need to know about RPA, and how it can help you manage and automate your processes.

The new C++ Standard, C++17, is near the end to be accepted and published. There’s already a working draft, and not that long ago it went to the final ISO balloting. It’s a good occasion to learn and understand what are the new features.

Let’s start slowly, and today we’ll look at language/library fixes and removed elements.

Intro and Series

This is the first post from my new series about C++17 details. I’ve already shared a lot of stuff, especially in my huge C++17 collaborative post from the beginning of the year. Still, it’s good to look at things in a bit more details.

The plan for the series

  1. Fixes and Deprecations (this post)
  2. Language clarification
  3. Templates
  4. Attributes
  5. Simplification (soon)
  6. Library changes 1 (soon + 1)
  7. Library changes 2 (soon + 2)

Documents and Links

First of all, if you want to dig into the standard on your own, you can read the latest draft here:

N4659, 2017-03-21, Working Draft, Standard for Programming Language C++ - the link also appears on the isocpp.org.

Compiler support: C++ compiler support

In Visual Studio (since VS 2015 Update 3) you can try using Standard Version Switches and test your code conformance with the given standard: Standards version switches in the compiler.

Moreover, I’ve prepared a list of concise descriptions of all of the C++17 language features:

Download a free copy of my C++17 Cheat Sheet!

It’s a one-page reference card, PDF.

Removed Things

The draft for the language now contains over 1,586 pages! Due to compatibility requirements, the new features are added, but not much is removed. Fortunately, there are some things that could go away.

Removing Trigraphs

Trigraphs are special character sequences that could be used when a system doesn’t support 7-bit ASCII - like in the ISO 646 character set. For example ??= generated #, ??- produces ~.

All of C++’s basic source character sets fit in 7-bit ASCII. The sequences are rarely used and by removing them the translation phase of the code might be simpler.

If you want to know more: c++03 - Purpose of Trigraph sequences in C++? - Stack Overflow, or Digraphs and trigraphs - Wikipedia.

You can find more details in N4086. If you really need trigraphs with Visual Studio, take a look at /Zc:trigraphs switch. Also, other compilers might leave the support in some way or the other. Other compiler statuses: done in GCC: 5.1 and Clang: 3.5.

Removing Register Keyword

The register keyword was deprecated in the 2011 C++ standard as it has no meaning. Now it’s being removed. This keyword is reserved and might be repurposed in the future revisions (for example the autokeyword was reused and now is something powerful).

More details: P0001R1, MSVC 2017: not yet. Done in GCC: 7.0 and Clang: 3.8.

Remove Deprecated Operator++(bool)

This operator has been deprecated for a very long time! In C++98, it was decided that it’s better not to use it. But it was not until C++17 that the committee agreed to remove it from the language.

More details: P0002R1, MSVC 2017: not yet. Done in GCC: 7.0 and Clang: 3.8.

Removing Deprecated Exception Specifications From C++17

In C++17, exception specification will be part of the type system (see P0012R1). Still, the standard contains old and deprecated exception specifications that appear to be impractical and unused.

For example:

void fooThrowsInt(int a) throw(int) {  
   printf_s("can throw ints\n");  
   if (a == 0)  
      throw 1;  

The above code was deprecated in C++11. The only practical exception declaration is throw(), which means that this code won’t throw anything. But since C++11, coders have been advised to use noexcept.

For example, in clang 4.0 you’ll get the following error:

error: ISO C++1z does not allow dynamic exception specifications [-Wdynamic-exception-spec]
note: use 'noexcept(false)' instead 

More details: P0003R5, MSVC 2017: not yet. Done in GCC: 7.0 and Clang: 4.0.

Removing Auto_ptr

This is one of my favorite updates to the language!

In C++11, we got smart pointers: unique_ptr, shared_ptr and weak_ptr. Thanks to the move, the semantics of the language could finally support proper unique resource transfers. auto_ptr was an old and buggy thing in the language - see the reasons why auto_ptr was deprecated here. It should be almost automatically converted to unique_ptr

auto_ptr has been deprecated for some time (since C++11). Many compilers would report this deprecation like:

warning: 'template<class> class std::auto_ptr' is deprecated

Now it goes into a zombie state, and basically, your code won’t compile.

Here’s the error from MSVC 2017 when using /std:c++latest:

error C2039: 'auto_ptr': is not a member of 'std'

If you need help with the conversion from auto_ptr to unique_ptr, you can check Clang Tidy, as it provides auto conversion: Clang Tidy: modernize-replace-auto-ptr.

More details: N4190

In the linked paper N4190, there are also other library items that were removed: unary_function/binary_function, ptr_fun(), and mem_fun()/mem_fun_ref(), bind1st()/bind2nd() and random_shuffle.


We can argue what constitutes 'a fix' in a language and what does not. Below, I’ve picked three things that like a fix for something that was missed in the previous standards.

New Auto Rules for Direct-List-Initialization

Since C++11 we've had a strange problem where

auto x { 1 }; 

is deduced as initializer_list. With the new standard, we can fix this, so it will deduce int (as most people would initially guess).

To make this happen, we need to understand the two types of initialization: copy and direct.

auto x = foo(); // copy-initialization
auto x{foo}; // direct-initialization, initializes an
             // initializer_list (until C++17)
int x = foo(); // copy-initialization
int x{foo}; // direct-initialization

For the direct initialization, C++17 introduces new rules:

For a braced-init-list with only a single element, auto
deduction will deduce from that entry;
For a braced-init-list with more than one element, auto
deduction will be ill-formed.

For example:

auto x1 = { 1, 2 }; // decltype(x1) is std::initializer_list<int>
auto x2 = { 1, 2.0 }; // error: cannot deduce element type
auto x3{ 1, 2 }; // error: not a single element
auto x4 = { 3 }; // decltype(x4) is std::initializer_list<int>
auto x5{ 3 }; // decltype(x5) is int

More details in N3922 and also in Auto and braced-init-lists, by Ville Voutilainen. This addition to C++ has been working since MSVC 14.0, GCC: 5.0, Clang: 3.8.

Static_assert With No Message

This is self-explanatory. It allows you to just have the condition without passing the message; the version with the message will also be available. It will be compatible with other asserts like BOOST_STATIC_ASSERT (that didn’t take any message from the start).

static_assert(std::is_arithmetic_v<T>, "T must be arithmetic");
static_assert(std::is_arithmetic_v<T>); // no message needed since C++17

More details: N3928, supported in MSVC 2017, GCC: 6.0 and Clang: 2.5.

Different Begin and End Types in Range-Based For Loop

Since C++11, range-based for loops were defined internally as:

   auto && __range = for-range-initializer;
   for ( auto __begin = begin-expr,
              __end = end-expr;
              __begin != __end;
              ++__begin ) {
        for-range-declaration = *__begin;

As you can see, __begin and __end have the same type. That might cause some trouble - for example when you have something like a sentinel that is of a different type.

In C++17, it’s been changed to:

  auto && __range = for-range-initializer;
  auto __begin = begin-expr;
  auto __end = end-expr;
  for ( ; __begin != __end; ++__begin ) {
    for-range-declaration = *__begin;

The types of __begin and __end might be different; only the comparison operator is required. This little change gives Range TS users a better experience.

More details in P0184R0, supported in MSVC 2017, GCC: 6.0 and Clang: 3.6.


The language standard grows, but there’s some movement in the committee to remove and clean some of the features. For compatibility reasons, we cannot delete all of the problems, but one by one we can get some improvements.

Next time, we’ll address language clarifications: like guaranteed copy elision or expression evaluation order. So stay tuned!

Get the senior executive’s handbook of important trends, tips, and strategies to compete and win in the digital economy.

web dev ,c++ ,language features

Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}