What are the new features in C++17? – Dev

The best answers to the question “What are the new features in C++17?” in the category Dev.

QUESTION:

C++17 is now feature complete, so unlikely to experience large changes. Hundreds of proposals were put forward for C++17.

Which of those features were added to C++ in C++17?

When using a C++ compiler that supports “C++1z”, which of those features are going to be available when the compiler updates to C++17?

ANSWER:

Language features:

Templates and Generic Code

  • Template argument deduction for class templates

    • Like how functions deduce template arguments, now constructors can deduce the template arguments of the class
    • http://wg21.link/p0433r2 http://wg21.link/p0620r0 http://wg21.link/p0512r0
  • template <auto>

    • Represents a value of any (non-type template argument) type.
  • Non-type template arguments fixes

  • template<template<class...>typename bob> struct foo {}

  • ( Folding + … + expressions ) and Revisions

  • auto x{8}; is an int

  • modernizing using with ... and lists

Lambda

  • constexpr lambdas

    • Lambdas are implicitly constexpr if they qualify
  • Capturing *this in lambdas

    • [*this]{ std::cout << could << " be " << useful << '\n'; }

Attributes

  • [[fallthrough]], [[nodiscard]], [[maybe_unused]] attributes

  • [[attributes]] on namespaces and enum { erator[[s]] }

  • using in attributes to avoid having to repeat an attribute namespace.

  • Compilers are now required to ignore non-standard attributes they don’t recognize.

    • The C++14 wording allowed compilers to reject unknown scoped attributes.

Syntax cleanup

  • Inline variables

    • Like inline functions
    • Compiler picks where the instance is instantiated
    • Deprecate static constexpr redeclaration, now implicitly inline.
  • namespace A::B

  • Simple static_assert(expression); with no string

  • no throw unless throw(), and throw() is noexcept(true).

Cleaner multi-return and flow control

  • Structured bindings

    • Basically, first-class std::tie with auto
    • Example:
      • const auto [it, inserted] = map.insert( {"foo", bar} );
      • Creates variables it and inserted with deduced type from the pair that map::insert returns.
    • Works with tuple/pair-likes & std::arrays and relatively flat structs
    • Actually named structured bindings in standard
  • if (init; condition) and switch (init; condition)

    • if (const auto [it, inserted] = map.insert( {"foo", bar} ); inserted)
    • Extends the if(decl) to cases where decl isn’t convertible-to-bool sensibly.
  • Generalizing range-based for loops

    • Appears to be mostly support for sentinels, or end iterators that are not the same type as begin iterators, which helps with null-terminated loops and the like.
  • if constexpr

    • Much requested feature to simplify almost-generic code.

Misc

  • Hexadecimal float point literals

  • Dynamic memory allocation for over-aligned data

  • Guaranteed copy elision

    • Finally!
    • Not in all cases, but distinguishes syntax where you are “just creating something” that was called elision, from “genuine elision”.
  • Fixed order-of-evaluation for (some) expressions with some modifications

    • Not including function arguments, but function argument evaluation interleaving now banned
    • Makes a bunch of broken code work mostly, and makes .then on future work.
  • Direct list-initialization of enums

  • Forward progress guarantees (FPG) (also, FPGs for parallel algorithms)

    • I think this is saying “the implementation may not stall threads forever”?
  • u8'U', u8'T', u8'F', u8'8' character literals (string already existed)

  • “noexcept” in the type system

  • __has_include

    • Test if a header file include would be an error
    • makes migrating from experimental to std almost seamless
  • Arrays of pointer conversion fixes

  • inherited constructors fixes to some corner cases (see P0136R0 for examples of behavior changes)

  • aggregate initialization with inheritance.

  • std::launder, type punning, etc

Library additions:

Data types

  • std::variant<Ts...>

    • Almost-always non-empty last I checked?
    • Tagged union type
    • {awesome|useful}
  • std::optional

    • Maybe holds one of something
    • Ridiculously useful
  • std::any

    • Holds one of anything (that is copyable)
  • std::string_view

    • std::string like reference-to-character-array or substring
    • Never take a string const& again. Also can make parsing a bajillion times faster.
    • "hello world"sv
    • constexpr char_traits
  • std::byte off more than they could chew.

    • Neither an integer nor a character, just data

Invoke stuff

  • std::invoke
    • Call any callable (function pointer, function, member pointer) with one syntax. From the standard INVOKE concept.
  • std::apply
    • Takes a function-like and a tuple, and unpacks the tuple into the call.
  • std::make_from_tuple, std::apply applied to object construction

  • is_invocable, is_invocable_r, invoke_result

    • http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0077r2.html
    • http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0604r0.html
    • Deprecates result_of
    • is_invocable<Foo(Args...), R> is “can you call Foo with Args... and get something compatible with R“, where R=void is default.
    • invoke_result<Foo, Args...> is std::result_of_t<Foo(Args...)> but apparently less confusing?

File System TS v1

  • [class.path]

  • [class.filesystem.error]

  • [class.file_status]

  • [class.directory_entry]

  • [class.directory_iterator] and [class.recursive_directory_iterator]

  • [fs.ops.funcs]

  • fstreams can be opened with paths, as well as with const path::value_type* strings.

New algorithms

  • for_each_n

  • reduce

  • transform_reduce

  • exclusive_scan

  • inclusive_scan

  • transform_exclusive_scan

  • transform_inclusive_scan

  • Added for threading purposes, exposed even if you aren’t using them threaded

Threading

  • std::shared_mutex

    • Untimed, which can be more efficient if you don’t need it.
  • atomic<T>::is_always_lockfree

  • scoped_lock<Mutexes...>

    • Saves some std::lock pain when locking more than one mutex at a time.
  • Parallelism TS v1

    • The linked paper from 2014, may be out of date
    • Parallel versions of std algorithms, and related machinery
  • hardware_*_interference_size

(parts of) Library Fundamentals TS v1 not covered above or below

  • [func.searchers] and [alg.search]
    • A searching algorithm and techniques
  • [pmr]

    • Polymorphic allocator, like std::function for allocators
    • And some standard memory resources to go with it.
    • http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0358r1.html
  • std::sample, sampling from a range?

Container Improvements

  • try_emplace and insert_or_assign

    • gives better guarantees in some cases where spurious move/copy would be bad
  • Splicing for map<>, unordered_map<>, set<>, and unordered_set<>

    • Move nodes between containers cheaply.
    • Merge whole containers cheaply.
  • non-const .data() for string.

  • non-member std::size, std::empty, std::data

    • like std::begin/end
  • Minimal incomplete type support in containers

  • Contiguous iterator “concept”

  • constexpr iterators

  • The emplace family of functions now returns a reference to the created object.

Smart pointer changes

  • unique_ptr<T[]> fixes and other unique_ptr tweaks.
  • weak_from_this and some fixed to shared from this

Other std datatype improvements:

  • {} construction of std::tuple and other improvements
  • TriviallyCopyable reference_wrapper, can be performance boost

Misc

  • C++17 library is based on C11 instead of C99

  • Reserved std[0-9]+ for future standard libraries

  • destroy(_at|_n), uninitialized_move(_n), uninitialized_value_construct(_n), uninitialized_default_construct(_n)

    • utility code already in most std implementations exposed
  • Special math functions
    • scientists may like them
  • std::clamp()
    • std::clamp( a, b, c ) == std::max( b, std::min( a, c ) ) roughly
  • gcd and lcm
  • std::uncaught_exceptions
    • Required if you want to only throw if safe from destructors
  • std::as_const
  • std::bool_constant
  • A whole bunch of _v template variables
  • std::void_t<T>
    • Surprisingly useful when writing templates
  • std::owner_less<void>
    • like std::less<void>, but for smart pointers to sort based on contents
  • std::chrono polish
  • std::conjunction, std::disjunction, std::negation exposed
  • std::not_fn
    • http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0358r1.html
  • Rules for noexcept within std
  • std::is_contiguous_layout, useful for efficient hashing
  • std::to_chars/std::from_chars, high performance, locale agnostic number conversion; finally a way to serialize/deserialize to human readable formats (JSON & co)
  • std::default_order, indirection over std::less. (breaks ABI of some compilers due to name mangling, removed.)

Traits

  • swap
  • is_aggregate
  • has_unique_object_representations

Deprecated

  • Some C libraries,
  • <codecvt>
  • memory_order_consume
  • result_of, replaced with invoke_result
  • shared_ptr::unique, it isn’t very threadsafe

Isocpp.org has has an independent list of changes since C++14; it has been partly pillaged.

Naturally TS work continues in parallel, so there are some TS that are not-quite-ripe that will have to wait for the next iteration. The target for the next iteration is C++20 as previously planned, not C++19 as some rumors implied. C++1O has been avoided.

Initial list taken from this reddit post and this reddit post, with links added via googling or from the above isocpp.org page.

Additional entries pillaged from SD-6 feature-test list.

clang’s feature list and library feature list are next to be pillaged. This doesn’t seem to be reliable, as it is C++1z, not C++17.

these slides had some features missing elsewhere.

While “what was removed” was not asked, here is a short list of a few things ((mostly?) previous deprecated) that are removed in C++17 from C++:

Removed:

  • register, keyword reserved for future use
  • bool b; ++b;
  • trigraphs
    • if you still need them, they are now part of your source file encoding, not part of language
  • ios aliases
  • auto_ptr, old <functional> stuff, random_shuffle
  • allocators in std::function

There were rewordings. I am unsure if these have any impact on code, or if they are just cleanups in the standard:

Papers not yet integrated into above:

  • P0505R0 (constexpr chrono)

  • P0418R2 (atomic tweaks)

  • P0512R0 (template argument deduction tweaks)

  • P0490R0 (structured binding tweaks)

  • P0513R0 (changes to std::hash)

  • P0502R0 (parallel exceptions)

  • P0509R1 (updating restrictions on exception handling)

  • P0012R1 (make exception specifications be part of the type system)

  • P0510R0 (restrictions on variants)

  • P0504R0 (tags for optional/variant/any)

  • P0497R0 (shared ptr tweaks)

  • P0508R0 (structured bindings node handles)

  • P0521R0 (shared pointer use count and unique changes?)

Spec changes:

  • exception specs and throw expressions

Further reference:

  • papers grouped by year; not all accepted

  • https://isocpp.org/files/papers/p0636r0.html

    • Should be updated to “Modifications to existing features” here.