All Main C++17 Options You Ought to Know

[ad_1]

The ISO Committee accepted and revealed the C++17 Normal in December 2017. On this mega-long article, I’ve constructed (along with your assist!) a listing of all main options of the brand new normal.

Please take a look and see what we get!

Intro

 

Up to date: This submit was up to date on tenth October 2022.

When you have code examples, higher explanations or any concepts, let me know! I’m completely happy to replace the present submit in order that it has some actual worth for others.

The plan is to have a listing of options with some primary clarification, little instance (if potential) and a few extra sources, plus a be aware about availability in compilers. In all probability, many of the options would possibly require separate articles and even entire chapters in books, so the listing right here will probably be solely a soar begin.

See this GitHub repo: github/fenbf/cpp17features. Add a pull request to replace the content material.

The characteristic listing comes from the next sources:

And one of the essential useful resource: N4659, 2017-03-21, Draft, Normal for Programming Language C++ – from isocpp.org.

Plus, there’s an official listing of adjustments: P0636r0: Adjustments between C++14 and C++17 DIS

Additionally, you may seize my listing of concise descriptions of all the C++17 – It’s a one-page reference card:

I even have a extra detailed sequence:

  1. Fixes and deprecation
  2. Language clarification
  3. Templates
  4. Attributes
  5. Simplification
  6. Library adjustments – Filesystem
  7. Library adjustments – Parallel
    STL
  8. Library adjustments – Utils
  9. Wrap up, Bonus
    with a free e-book! 🙂

And one other cool article:

Assets about C++17 STL:

Language Options

 

New auto guidelines for direct-list-initialization

 

N3922

Fixes some instances with auto sort deduction. The total background will be present in Auto and braced-init-lists, by Ville Voutilainen.

It fixes the issue of deducing std::initializer_list like:

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

And for the direct initialization, new guidelines are:

  • For a braced-init-list with solely a single aspect, auto deduction will deduce from that entry;
  • For a braced-init-list with multiple aspect, auto deduction will probably be ill-formed.

Principally, auto x { 1 }; will probably be now deduced as int, however earlier than it was an initializer listing.

static_assert with no message

 

N3928

Self-explanatory. It permits having the situation with out passing the message, model with the message may also be out there. It will likely be appropriate with different asserts like BOOST_STATIC_ASSERT (that didn’t take any message from the beginning).

constexpr int id(int x) { return x; }
static_assert(id(10) == 10, "anticipated the identical worth"); // since C++11
static_assert(id(10) == 10); // no message, since C++17

Run at @compiler Explorer

typename in a template template parameter

 

N4051

Means that you can use typename as a substitute of class when declaring a template template parameter. Regular sort parameters can use them interchangeably, however template template parameters had been restricted to class, so this transformation unifies these types considerably.

template <template <typename...> typename Container>
//            was invalid ^^^^^^^^
struct foo;

foo<std::vector> my_foo;

Eradicating trigraphs

 

N4086

Removes ??=, ??(, ??>, …

Makes the implementation a bit easier, see MSDN Trigraphs

Nested namespace definition

 

N4230

Permits writing:

namespace A::B::C {
   // ...
}

Relatively than:

namespace A {
    namespace B {
        namespace C {
            // ...
        }
    }
}

Attributes for namespaces and enumerators

 

N4266

Permits attributes on enumerators and namespaces. Extra particulars in N4196.

enum E {
  foobar = 0,
  foobat [[deprecated]] = foobar
};

E e = foobat; // Emits warning

namespace [[deprecated]] old_stuff{
    void legacy();
}

old_stuff::legacy(); // Emits warning

u8 character literals

 

N4267

UTF-8 character literal, e.g. u8'a'. Such literal has sort char and the worth equal to ISO 10646 code level worth of c-char, supplied that the code level worth is representable with a single UTF-8 code unit. If c-char will not be in Primary Latin or C0 Controls Unicode block, this system is ill-formed.

The compiler will report errors if a personality can’t match inside u8 ASCII vary.

Reference:

Enable fixed analysis for all non-type template arguments

 

N4268

Take away syntactic restrictions for pointers, references, and tips to members that seem as non-type template parameters:

For example:

template<int *p> struct A {};
int n;
A<&n> a; // okay

constexpr int *p() { return &n; }
A<p()> b; // error earlier than C++17

Fold Expressions

 

N4295

Extra background right here in P0036

Permits writing compact code with variadic templates with out utilizing express recursion.

Instance:

template<typename... Args>
auto SumWithOne(Args... args){
    return (1 + ... + args);
}

Articles:

Unary fold expressions and empty parameter packs

 

P0036R0

If the parameter pack is empty then the worth of the fold is:

&& true
|| false
, void()

For any operator not listed above, an unary fold expression with an empty parameter pack is ill-formed.

Take away Deprecated Use of the register Key phrase

 

P0001R1

The register key phrase was deprecated within the 2011 C++ normal. C++17 tries to clear the usual, so the key phrase is now eliminated. This key phrase is reserved now and is perhaps repurposed in future revisions.

Take away Deprecated operator++(bool)

 

P0002R1

The ++operator for bool was deprecated within the authentic 1998 C++ normal, and it’s previous time to take away it formally.

Eradicating Deprecated Exception Specs from C++17

 

P0003R5

Dynamic exception specs had been deprecated in C++11. This paper formally proposes eradicating the characteristic from C++17, whereas retaining the (nonetheless) deprecated throw() specification strictly as an alias for noexcept(true).

Make exception specs a part of the sort system

 

P0012R1

Beforehand exception specs for a operate didn’t belong to the kind of the operate, however it will likely be a part of it.

We’ll get an error within the case:

void (*p)();
void (**pp)() noexcept = &p;   // error: can't convert to pointer to noexcept operate

struct S { typedef void (*p)(); operator p(); };
void (*q)() noexcept = S();   // error: can't convert to pointer to noexcept operate

Combination initialization of lessons with base lessons

 

P0017R1

If a category was derived from another sort you couldn’t use mixture initialization. However now the restriction is eliminated.

struct base { int a1, a2; };
struct derived : base { int b1; };

derived d1{{1, 2}, 3};      // full express initialization
derived d1{{}, 1};          // the bottom is worth initialized

To sum up: from the usual:

An mixture is an array or a category with:
* no user-provided constructors (together with these inherited from a
base class),
* no non-public or protected non-static information members (Clause 11),
* no base lessons (Clause 10) and // eliminated now!
* no digital features (10.3), and
* no digital, non-public or protected base lessons (10.1).

See extra in 5 tough matters for information members in C++20 – C++ Tales – “Altering standing of aggregates”

Lambda seize of *this

 

P0018R3

this pointer is implicitly captured by lambdas inside member features (in the event you use a default seize, like [&] or [=]). Member variables are at all times accessed by this pointer.

Instance:

struct S {
   int x ;
   void f() {
      // The next lambda captures are presently similar
      auto a = [&]() { x = 42 ; } // OK: remodeled to (*this).x
      auto b = [=]() { x = 43 ; } // OK: remodeled to (*this).x
      a();
      assert( x == 42 );
      b();
      assert( x == 43 );
   }
};

Now you should utilize *this when declaring a lambda, for instance auto b = [=, *this]() { x = 43 ; }. That manner this is captured by worth. Word that the shape [&,this] is redundant however accepted for compatibility with ISO C++14.

Capturing by worth is perhaps particularly essential for async invocation, paraller processing.

See extra at C++ Lambdas, Threads, std::async and Parallel Algorithms – C++ Tales

Utilizing attribute namespaces with out repetition

 

P0028R4

Different identify for this characteristic was “Utilizing non-standard attributes” in P0028R3 and PDF: P0028R2 (rationale, examples).

Simplifies the case the place you wish to use a number of attributes, like:

void f() {
    [[rpr::kernel, rpr::target(cpu,gpu)]] // repetition
    do-job();
}

Proposed change:

void f() {
    [[using rpr: kernel, target(cpu,gpu)]]
    do-job();
}

That simplification would possibly assist when constructing instruments that routinely translate annotated such code into a distinct programming fashions.

Dynamic reminiscence allocation for over-aligned information

 

P0035R4

Within the following instance:

class alignas(16) float4 {
    float f[4];
};
float4 *p = new float4[1000];

C++11/14 didn’t specify any mechanism by which over-aligned information will be dynamically allotted appropriately (i.e. respecting the alignment of the information). Within the instance above, not solely is an implementation of C++ not required to allocate properly-aligned reminiscence for the array, for sensible functions it is vitally practically required to do the allocation incorrectly.

C++17 fixes that gap by introducing extra reminiscence allocation features that use align parameter:

void* operator new(std::size_t, std::align_val_t);
void* operator new[](std::size_t, std::align_val_t);
void operator delete(void*, std::align_val_t);
void operator delete[](void*, std::align_val_t);
void operator delete(void*, std::size_t, std::align_val_t);
void operator delete[](void*, std::size_t, std::align_val_t);

See extra in New new() – The C++17’s Alignment Parameter for Operator new() – C++ Tales.

__has_include in preprocessor conditionals

 

P0061R1

This characteristic permits a C++ program to instantly, reliably and portably decide whether or not or not a library header is accessible for inclusion.

Instance: This demonstrates a manner to make use of a library non-compulsory facility solely whether it is out there.

#if __has_include(<non-compulsory>)
#  embody <non-compulsory>
#  outline have_optional 1
#elif __has_include(<experimental/non-compulsory>)
#  embody <experimental/non-compulsory>
#  outline have_optional 1
#  outline experimental_optional 1
#else
#  outline have_optional 0
#endif

Template argument deduction for sophistication templates

 

P0091R3

Earlier than C++17, template deduction labored for features however not for lessons. For example, the next code was authorized:

void f(std::pair<int, char>);

f(std::make_pair(42, 'z'));

as a result of std::make_pair is a template operate (so we are able to carry out template deduction). However the next wasn’t:

void f(std::pair<int, char>);

f(std::pair(42, 'z'));

Though it’s semantically equal. This was not authorized as a result of std::pair is a template class, and template lessons couldn’t apply sort deduction of their initialization.

So earlier than C++17 one has to put in writing out the categories explicitly, regardless that this doesn’t add any new data:

void f(std::pair<int, char>);

f(std::pair<int, char>(42, 'z'));

That is fastened in C++17 the place template class constructors can deduce sort parameters. The syntax for setting up such template lessons is due to this fact in step with the syntax for setting up non-template lessons.

See extra in:

Non-type template parameters with auto sort

 

P0127R2

Mechanically deduce sort on non-type template parameters.

template <auto worth> void f() { }
f<10>();               // deduces int

Journey report: Summer season ISO C++ requirements assembly (Oulu) | Sutter’s
Mill

Assured copy elision

 

P0135R1

Copy elision for non permanent objects, not for Named RVO.

// based mostly on P0135R0
struct NonMoveable 
{
  NonMoveable(int);
  // no copy or transfer constructor:
  NonMoveable(const NonMoveable&) = delete;
  NonMoveable(NonMoveable&&) = delete;

  std::array<int, 1024> arr;
};

NonMoveable make() 
{
  return NonMoveable(42);
}

// assemble the thing:
auto largeNonMovableObj = make();

Articles:

New specification for inheriting constructors (DR1941 et al)

 

P0136R1

Extra description and reasoning in P0136R0. Some excerpts under:

An inheriting constructor doesn’t act like every other type of using-declaration. All different using-declarations make some set of declarations seen to call lookup in one other context, however an inheriting constructor declaration declares a brand new constructor that merely delegates to the unique.

This characteristic adjustments inheriting constructor declaration from declaring a set of latest constructors, to creating a set of base class constructors seen in a derived class as in the event that they had been derived class constructors. (When such a constructor is used, the extra derived class subobjects may also be implicitly constructed as if by a defaulted default constructor). Put one other manner: make inheriting a constructor act identical to inheriting every other base class member, to the extent
potential.

This alteration does have an effect on the that means and validity of some applications, however these adjustments enhance the consistency and comprehensibility of C++.

// Hiding works the identical as for different member
// using-declarations within the presence of default arguments
struct A {
  A(int a, int b = 0);
  void f(int a, int b = 0);
};
struct B : A {
  B(int a);      utilizing A::A;
  void f(int a); utilizing A::f;
};
struct C : A {
  C(int a, int b = 0);      utilizing A::A;
  void f(int a, int b = 0); utilizing A::f;
};

B b(0); // was okay, now ambiguous
b.f(0); // ambiguous (unchanged)

C c(0); // was ambiguous, now okay
c.f(0); // okay (unchanged)

// Inheriting constructor parameters are now not copied
struct A { A(const A&) = delete; A(int); };
struct B { B(A); void f(A); };
struct C : B { utilizing B::B; utilizing B::f; };
C c({0}); // was ill-formed, now okay (no copy made)
c.f({0}); // okay (unchanged)

Direct-list-initialization of enumerations

 

P0138R2

Permits the initialization of an enum class with a hard and fast underlying sort:

enum class Deal with : uint32_t { Invalid = 0 };
Deal with h { 42 }; // OK

Permits creating robust varieties which are simple to make use of…

Stricter expression analysis order

 

P0145R3

In a nutshell, given an expression comparable to f(a, b, c), the order during which the sub-expressions f, a, b, c (that are of arbitrary shapes) are evaluated is left unspecified by the usual.

// unspecified behaviour under!
f(i++, i);

v[i] = i++;

std::map<int, int> m;
m[0] = m.dimension(); // {{0, 0}} or {{0, 1}} ?

Abstract of adjustments:

  • Postfix expressions are evaluated from left to proper. This consists of features calls and member choice expressions.
  • Task expressions are evaluated from proper to left. This consists of compound assignments.
  • Operands to shift operators are evaluated from left to proper.

See extra in: Stricter Expression Analysis Order in C++17 – C++ Tales

Reference:

constexpr lambda expressions

 

P0170R1

constexpr can be utilized within the context of lambdas.

constexpr auto ID = [] (int n)  { return n; };
constexpr int I = ID(3);
static_assert(I == 3);

constexpr int AddEleven(int n) {
  // Initialization of the 'information member' for n can
  // happen inside a continuing expression since 'n' is
  // of literal sort.
  return [n] { return n + 11; }();
}
static_assert(AddEleven(5) == 16);

Articles

Completely different start and finish varieties in range-based for

 

P0184R0

Altering the definition of vary based mostly for from:

{
   auto && __range = for-vary-initializer;
   for ( auto __begin = start-expr,
              __end = finish-expr;
              __begin != __end;
              ++__begin ) {
        for-vary-declaration = *__begin;
        assertion
   }
}

Into:

{
  auto && __range = for-vary-initializer;
  auto __begin = start-expr;
  auto __end = finish-expr;
  for ( ; __begin != __end; ++__begin ) {
    for-vary-declaration = *__begin;
    assertion
  }
}

Varieties of __begin and __end is perhaps completely different; solely the comparability operator is required. This little change permits Vary TS customers a greater expertise.

[[fallthrough]] attribute

 

P0188R1

Signifies {that a} fallthrough in a change assertion is intentional and a warning shouldn’t be issued for it. Extra particulars in P0068R0.

change (c) {
case 'a':
    f(); // Warning emitted, fallthrough is probably a programmer error
case 'b':
    g();
[[fallthrough]]; // Warning suppressed, fallthrough is intentional
case 'c':
    h();
}

See extra in C++17 in particulars: Attributes – C++ Tales

[[nodiscard]] attribute

 

P0189R1

[[nodiscard]] is used to emphasize that the return worth of a operate is to not be discarded, on ache of a compiler warning. Extra particulars in P0068R0.

[[nodiscard]] int foo();
void bar() {
    foo(); // Warning emitted, return worth of a nodiscard operate is discarded
}

This attribute will also be utilized to varieties with a view to mark all features which return that sort as [[nodiscard]]:

[[nodiscard]] struct DoNotThrowMeAway{};
DoNotThrowMeAway i_promise();
void oops() {
    i_promise(); // Warning emitted, return worth of a nodiscard operate is discarded
}

Articles:

[[maybe_unused]] attribute

 

P0212R1

Suppresses compiler warnings about unused entities when they’re declared with [[maybe_unused]]. Extra particulars in P0068R0.

                 static void impl1() { ... } // Compilers might warn about this
[[maybe_unused]] static void impl2() { ... } // Warning suppressed

void foo() {
                      int x = 42; // Compilers might warn about this
     [[maybe_unused]] int y = 42; // Warning suppressed
}

A 3 min video about maybe_unused in Jason Turner’s C++ Weekly

Ignore unknown attributes

 

P0283R2

Clarifies that implementations ought to ignore any attribute namespaces which they don’t assist, as this was unspecified. Extra particulars in P0283R1.

//compilers which do not assist MyCompilerSpecificNamespace will ignore this attribute
[[MyCompilerSpecificNamespace::do_special_thing]]
void foo();

Pack expansions in using-declarations

 

P0195R2

Means that you can inject names with using-declarations from all sorts in a parameter pack.

With the intention to expose operator() from all base lessons in a variadic template, we used to must resort to recursion:

template <typename T, typename... Ts>
struct Overloader : T, Overloader<Ts...> {
    utilizing T::operator();
    utilizing Overloader<Ts...>::operator();
    // […]
};

template <typename T> struct Overloader<T> : T {
    utilizing T::operator();
};

Now we are able to merely develop the parameter pack within the using-declaration:

template <typename... Ts>
struct Overloader : Ts... {
    utilizing Ts::operator()...;
    // […]
};

See extra in 2 Traces Of Code and three C++17 Options – The overload Sample – C++ Tales

Remarks

Structured Binding Declarations

 

P0217R3
P0615R0: Renaming for structured
bindings

Helps when utilizing tuples as a return sort. It should routinely create variables and tie them. Extra particulars in P0144R0.

The identify “Decomposition Declaration” was additionally used, however lastly the usual agrees to make use of “Structured Binding Declarations” (part 11.5)

For instance:

int a = 0;
double b = 0.0;
lengthy c = 0;
std::tie(a, b, c) = tuple; // a, b, c have to be declared first

Now we are able to write:

auto [ a, b, c ] = tuple;

Such expressions additionally work on structs, pairs, and arrays.

Articles:

Hexadecimal floating-point literals

 

P0245R1

Permits expressing some particular floating level values, for instance, the smallest regular IEEE-754 single precision worth is instantly written as 0x1.0p-126.

init-statements for if and change

 

P0305R1

New variations of the if and change statements for C++:

if (init; situation) and change (init; situation).

This could simplify the code. For instance, beforehand you needed to write:

{
    auto val = GetValue();
    if (situation(val))
        // on success
    else
        // on false...
}

Look, that val has a separate scope, with out it it is going to ‘leak’.

Now you may write:

if (auto val = GetValue(); situation(val))
    // on success
else
    // on false...

val is seen solely contained in the if and else statements, so it doesn’t ‘leak’. situation is perhaps any situation, not provided that val is true/false.

Examples:

Inline variables

 

P0386R2

Beforehand solely strategies/features may very well be specified as inline, now you are able to do the identical with variables, inside a header file.

A variable declared inline has the identical semantics as a operate declared inline: it may be outlined, identically, in a number of translation items, have to be outlined in each translation unit during which it’s used, and the habits of this system is as if there’s precisely one variable.

struct MyClass
{
    static const int sValue;
};

inline int const MyClass::sValue = 777;

And even:

struct MyClass
{
    inline static const int sValue = 777;
};

Articles

DR: Matching of template template-arguments excludes appropriate templates

 

P0522R0

This characteristic resolves Core subject CWG 150.

From the paper:

This paper permits a template template-parameter to bind to a template argument every time the template parameter is at the very least as specialised because the template argument. This suggests that any template argument listing that may legitimately be utilized to the template template-parameter can also be relevant to the argument template.

Instance:

template <template <int> class> void FI();
template <template <auto> class> void FA();
template <auto> struct SA { /* ... */ };
template <int> struct SI { /* ... */ };
FI<SA>();  // OK; error earlier than this paper
FA<SI>();  // error

template <template <typename> class> void FD();
template <typename, typename = int> struct SD { /* ... */ };
FD<SD>();  // OK; error earlier than this paper (CWG 150)

(Tailored from the remark by IncongruentModulo1)

For a helpful instance, think about one thing like this:

template <template <typename> typename Container>
struct A
{
    Container<int>    m_ints;
    Container<double> m_doubles;
};

In C++14 and earlier, A<std::vector> wouldn’t be legitimate (ignoring the typename and never class earlier than container) since std::vector is asserted as:

template <typename T, typename Allocator = std::allocator<T>> class vector;

This alteration resolves that subject. Earlier than, you would wish to declare template <template <typename...> typename Container>, which is extra permissive and strikes the error to a much less express line (particularly the declaration of m_ints wherever the struct A is applied /declared, as a substitute of the place the struct is instantiated with the improper template sort.

std::uncaught_exceptions()

 

N4259

Extra background within the authentic paper: PDF: N4152 and GOTW subject 47: Uncaught Exceptions.

The operate returns the variety of uncaught exception objects within the present thread.

This is perhaps helpful when implementing correct Scope Guards that works additionally throughout stack unwinding.

A sort that desires to know whether or not its destructor is being run to unwind this object can question uncaught_exceptions in its constructor and retailer the outcome, then question uncaught_exceptions once more in its destructor; if the result’s completely different, then this destructor is being invoked as a part of stack unwinding attributable to a brand new exception that was thrown later than the thing’s building

The above quote comes from PDF: N4152.

constexpr if-statements

 

P0292R2

The static-if for C++! This lets you discard branches of an if assertion at compile-time based mostly on a continuing expression situation.

if constexpr(cond)
     statement1; // Discarded if cond is fake
else
     statement2; // Discarded if cond is true

This removes lots of the need for tag dispatching and SFINAE:

SFINAE

template <typename T, std::enable_if_t<std::is_arithmetic<T>{}>* = nullptr>
auto get_value(T t) {/*...*/}

template <typename T, std::enable_if_t<!std::is_arithmetic<T>{}>* = nullptr>
auto get_value(T t) {/*...*/}

Tag dispatching

template <typename T>
auto get_value(T t, std::true_type) {/*...*/}

template <typename T>
auto get_value(T t, std::false_type) {/*...*/}

template <typename T>
auto get_value(T t) {
    return get_value(t, std::is_arithmetic<T>{});
}

if constexpr

template <typename T>
auto get_value(T t) {
     if constexpr (std::is_arithmetic_v<T>) {
         //...
     }
     else {
         //...
     }
}

Articles:

Library Options

 

To get extra particulars about library implementation I counsel these hyperlinks:

This part solely mentions among the most essential elements of library adjustments, it will be too impractical to enter particulars of each little change.

Merged: The Library Fundamentals 1 TS (most elements)

 

P0220R1

We get the next gadgets:

The wording from these parts comes from Library Fundamentals V2 to make sure the wording consists of the most recent corrections.

Assets:

Elimination of some deprecated varieties and features, together with std::auto_ptr, std::random_shuffle, and outdated operate adaptors

 

N4190

  • Operate objects – unary_function/binary_function, ptr_fun(), and mem_fun()/mem_fun_ref()
  • Binders – bind1st()/bind2nd()
  • auto_ptr
  • Random shuffle – random_shuffle(first, final) and random_shuffle(first, final, rng)

Merged: The Parallelism TS, a.okay.a. “Parallel STL.”,

 

P0024R2

Parralel variations/overloads of most of std algorithms. Plus just a few new
algorithms, like cut back, transform_reduce, for_each.

std::vector<int> v = genLargeVector();

// normal sequential kind
std::kind(v.start(), v.finish());

// explicitly sequential kind
std::kind(std::seq, v.start(), v.finish());

// allowing parallel execution
std::kind(std::par, v.start(), v.finish());

// allowing vectorization as properly
std::kind(std::par_unseq, v.start(), v.finish());

Articles:

Merged: File System TS,

 

P0218R1

namespace fs = std::filesystem;

fs::path pathToShow(/* ... */);
cout << "exists() = " << fs::exists(pathToShow) << "n"
     << "root_name() = " << pathToShow.root_name() << "n"
     << "root_path() = " << pathToShow.root_path() << "n"
     << "relative_path() = " << pathToShow.relative_path() << "n"
     << "parent_path() = " << pathToShow.parent_path() << "n"
     << "filename() = " << pathToShow.filename() << "n"
     << "stem() = " << pathToShow.stem() << "n"
     << "extension() = " << pathToShow.extension() << "n";

Articles:

Merged: The Mathematical Particular Capabilities IS,

 

PDF – WG21 P0226R1

Bettering std::pair and std::tuple

 

N4387

std::shared_mutex (untimed)

 

N4508

std::variant

 

P0088R2

Variant is a typesafe union that can report errors once you wish to entry one thing that’s not presently inside the thing.

std::variant<std::string, int> v { "Hi there A Fairly Lengthy String" };
// v allocates some reminiscence for the string
v = 10; // we name destructor for the string!
// no reminiscence leak

Notes:

  • Variant will not be allowed to allocate extra (dynamic) reminiscence.
  • A variant will not be permitted to carry references, arrays, or the sort void.
  • A variant is default initialized with the worth of its first various.
  • If the primary various sort will not be default constructible, then the variant should use std::monostate as the primary various

Take a look at extra instance in a separate article:

All the things You Must Know About std::variant from C++17 – C++ Tales

Splicing Maps and Units

 

P0083R2

From Herb Sutter, Oulu journey report:

You’ll now have the ability to instantly transfer inside nodes from one node-based container instantly into one other container of the identical sort. Why is that essential? As a result of it ensures no reminiscence allocation overhead, no copying of keys or values, and even no exceptions if the container’s comparability operate doesn’t throw.

New features:

  • std::map::extract
  • std::map::merge
  • std::set::extract
  • std::set::merge

Elementary string conversion

 

from_chars and to_chars that are low-level, and provides the absolute best efficiency

The brand new conversion routines are:

  • non-throwing
  • non-allocating
  • no locale assist
  • reminiscence security
  • error reporting offers extra details about the conversion final result
  • certain checked
  • express round-trip ensures – you should utilize to_chars and from_charsto convert the quantity forwards and backwards, and it provides you with the precise binary representations. This isn’t assured by different routines like printf/sscanf/itoa, and many others.

Easy instance:

std::string str { "xxxxxxxx" };
const int worth = 1986;
std::to_chars(str.information(), str.information() + str.dimension(), worth);

// str is "1986xxxx"

extra in:

std::apply

 

A useful helper for std::tuple. It takes a tuple and a callable object after which invokes this callable with parameters fetched from the tuple.

#embody <iostream>
#embody <tuple>
 
int sum(int a, int b, int c) { 
    return a + b + c; 
}

void print(std::string_view a, std::string_view b) {
    std::cout << "(" << a << ", " << b << ")n";
} 

int important() {
    std::tuple numbers {1, 2, 3};
    std::cout << std::apply(sum, numbers) << 'n';

    std::tuple strs {"Hi there", "World"};
    std::apply(print, strs);
}

See extra in C++ Templates: Tips on how to Iterate by way of std::tuple: std::apply and Extra – C++ Tales

std::invoke

 

With std::invoke you get entry to INVOKE expression that was outlined within the Normal since C++11 (and even in C++0x, TR1), however wasn’t uncovered outdoors.

It might probably deal with the next callables:

  • operate objects: like func(arguments...)
  • tips to member features (obj.*funcPtr)(arguments...)
  • pointer to member information obj.*pdata

In C++20 it was improved and marked with constexpr.

See extra in C++20 Ranges, Projections, std::invoke and if constexpr – C++ Tales

Contributors

 

This can be a place so that you can be talked about!

Contributors:

Abstract

 

Thanks for all of the assist with the listing!

There are nonetheless gadgets that must be up to date, however the listing is generally accomplished.

If you wish to learn extra about C++17, take a look at my ebook (-17% much less with this coupon code, until tenth December 2022)

C++17 In Element, -17% coupon code

[ad_2]

Leave a Reply

Your email address will not be published. Required fields are marked *