Along with the new features added to the language and the standard library in C++17, there are also existing features that have been either removed (after being deprecated in a previous version) or deprecated so they would be removed sometime in the future. Although not complete, the following tables list the most important of these removed or deprecated features.

The following table lists features that were removed in C++17.

Feature Comments Alternatives

throw(typeid) Explicit dynamic specification allowed specifying one or more types for exception that might be thrown by a function. This feature does not have an alternative. Instead, functions should only specify whether they could throw exceptions or not (without specifying their type). noexcept is the specifier use for this purpose. However, make sure you use it only when it’s guarantee that the invocation of the function cannot throw any error; otherwise, the program will terminate abnormally with a call to std::terminate() .

operator++ for bool The pre-fix and post-fix operator++ was overloaded for type bool . In both cases, the return value for a bool argument is true . Since the bool type does not support the full set of arithmetic types, it is no longer considered an arithmetic type and these operators have been removed. std::exchange for the rare cases where the post-fix operator has valid uses. See exchange() utility function, revision 3 for examples of these cases.

Trigraphs Trigraphs (short for three-character groups) are alternatives for some characters, introduced with two question marks (which is also the reason the question mark has to be escaped '\?' ). They were introduced for compatibility with C which had them for keyboards that did not support the ISO 646 character set. Trigraphs are parsed before comments and string literals are recognized and can be a source of confusion for many programmers. For reason of deprecation see Comment on proposed trigraph deprecation. None

register storage specifier Was a specifier for objects declared at block scope or in function parameter lists to indicate automatic storage duration as well as a hint to the compiler that these variables might be heavily used so that it can do optimization by storing it in a CPU register. Since the automatic storage duration for these kinds of variables is implicit and the hint was rarely used by the compilers this feature was deprecated in C++11 and removed in C++17. None

std::auto_ptr auto_ptr was the attempt to create a smart pointer to handle an object’s lifetime before move semantics were available. This smart pointer quietly steals ownership of the managed object in its copy constructor and copy assignment from the right-hand argument. As a result, the copy is not the same as the original smart pointer object. Because of these copy semantics, auto_ptr does not meet the requirements of being CopyConstructible, and therefore cannot be used in standard containers. For more information about the deprecation of auto_ptr see N1856. For most uses, std::unique_ptr is the direct replacement of std::auto_ptr . In many cases, it can be a simple drop in replacement, although an explicit move might be necessary to be done. For more information on the topic see this discussion.

std::random_shuffle This algorithm reorders elements of a range so that each possible permutation of its elements has an equal probability of appearance. The problem with it is that it may depend on the rand family of C functions, that may be deprecated in the future. On the other hand, it may also have global state for seeding and others. For more information see std::random_shuffle is deprecated in C++14. The replacement is std::shuffle, that needs as the third argument a uniform random bit generator. Although the replacement of the algorithm itself is trivial, you need to setup a URNG, several standard ones being available in the <random> header.

std::unary_function, std::binary_function These are former types used solely for defining some types (argument and result types). They used to be the base class for function objects that required these type definitions because they were necessary in some parts of the standard library. Such an function object was std::less . These restrictions have been lifted in C++11 because they were actually an overspecification. If needed, define the argument and result types in your class.

std::pointer_to_unary_function, std::pointer_to_binary_function Function objects that act as wrappers around unary or binary functions. std::function and std::ref

std::ptr_fun Creates instances of std::pointer_to_unary_function and std::pointer_to_binary_function .

std::mem_fun_t,

std::mem_fun1_t,

std::const_mem_fun_t,

std::const_mem_fun1_t,

std::mem_fun_ref_t,

std::mem_fun1_ref_t,

std::const_mem_fun_ref_t,

std::const_mem_fun1_ref_t These are function objects that wrap a pointer to a member function with no parameters or one parameter. For the former, the object whose member function to call is passed by pointer to the call operator; for the latter, it is passed as a reference. They are deprecated because they are limited to member functions with either none or just one argument and you need different functions and function objects for handling pointers or references to the class instance. std::mem_fn is a variadic template that can handle member functions with any number of variables and not only references or pointers to objects but also smart pointers.

std::mem_fun, std::mem_fun_ref These are helper functions that create the member function wrapper objects above.

std::binder1st, std::binder2nd These are function objects that bind an argument to a binary function. Lambdas, std::bind

std::bind1st, std::bind2nd Helper functions that create instances of std::binder1st or std::binder2nd , binding a given argument to a first or second parameter of a given binary function object.

These were remnants of utility functions in STL that did make it into C++98 but became obsolete with the introduction of lambdas in C++11, when they were deprecated.

std::function allocator support Several constructors allow to specify an allocator used for allocating internal memory if needed. However, this was later considered poorly specified and inconsistently implemented (with some implementation not providing these overloads at all). Therefore, these constructor overloads were removed in C++17. None