C++17 - The Complete Guide
structured bindings do not decay.
i.ethe type of a still is const char[6].
This is different from initializing a new object with auto, where types decay:
v,n r-value reference to anonymous entity.
We can also capture as a forwarding reference using auto&&.
That is, auto&& will resolve to auto& for lvalue references, and auto&& for rvalue references.
此時 anonymous entity 由 move constructor construct from ms.
也就是 ms 的內容已經 invalidate.
Note that there is only limited usage of inheritance possible.
All non-static data members must be members of the same class definition.
std::tuple
std::array
array:
tuple:
Aggregate Extensions
Definition of Aggregates
- either an array
- or a class type (class, struct, or union) with:
- no user-declared or explicit constructor
- no constructor inherited by a using declaration
- no private or protected non-static data members
- no virtual functions
- no virtual, private, or protected base classes
- no private or
- protected base class members
- or constructors
are used during initialization.
is_aggregate<>
Before C++17, Derived was not an aggregate. Thus,
Derived d1{};
was calling the implicitly defined default constructor of Derived, which by default called the default constructor of the base class Base.
Although the default constructor of the base class is private, it was valid to be called as via the default constructor of the derived class, because the derived class was defined to be a friend class.
Since C++17, Derived in this example is an aggregate, not having an implicit default constructor
at all (the constructor is not inherited by a using declaration).
So the initialization is an aggregate initialization, for which it is not allowed to call private constructors of bases classes. Whether the base class is a friend doesn't matter.
RVO
http://en.cppreference.com/w/cpp/language/copy_elision
Copy ellision works even copy/move constructor is deleted.
Copy ellision works even copy/move constructor is deleted.
NRVO
Copy/move constructor still needs to be around.
So, how this benefits us?
Any type that is _not_ copyable can be used in a factory function
which return the type instance, which is not going to be copied!
Also, any type with it's move constructor deleted, as in factory function,
we still can pass a r-value instance back.
Value Categories
A variable itself is not an lvalue;
only an expression denoting the variable is an lvalue:
In the first statement 3 is a prvalue initializing the variable (not the lvalue) x.
In the second statement x is an lvalue (its evaluation designates an object containing the value 3). The lvalue x is converted to a prvalue, which is what initializes the variable y.
The key approach to explain value categories now is that in general we have two kinds of expressions:
- glvalues: expressions for locations of objects or functions
- prvalues: expressions for initializations
C++17 then introduces a new term, called materialization (of a temporary) for the moment a prvalue becomes a temporary object.
Thus, a temporary materialization conversion is a prvalue-to-xvalue conversion.
Lambda
It's constexpr iff it doesn't capture.
如何測試lambda expression 為constexpr?
將lambda expression 冠上constexpr,如果compile出錯,則非constexpr.Evaluation Order
To fix all this unexpected behavior, for some operators the evaluation guarantees were refined so
that they now specify a guaranteed evaluation order:
For:
e1 [ e2 ]
e1 [ e2 ]
e1 . e2
e1 .* e2
e1 ->* e2
e1 << e2
e1 >> e2
e1 is guaranteed to get evaluated before e2 now, so that the evaluation order is left to right.
However, note that the evaluation order of different arguments of the same function call is still undefined.
That is, in
e1.f(a1,a2,a3)
e1 is guaranteed to get evaluated before a1, a2, and a3 now. However, the evaluation order of a1,
a2, and a3 is still undefined.
In all assignment operators:
e2 = e1
e2 = e1
e2 += e1
e2 *= e1
...
the right-hand side e1 is guaranteed to get evaluated before the left-hand side e2 now.
In new expressions like: (重要!)
new Type(e)
new Type(e)
the allocation is now guaranteed to be performed before the evaluation e, and the initialization of the new value is guaranteed to happen before any usage of the allocated and initialized value.
Enum Initialization from Integral Values
For enumerations with a fixed underlying type, since C++17 you can use an integral value of that type for direct list initialization.
This applies to unscoped enumerations with a specified type and all scoped enumerations, because they always have an underlying default type:
unscoped enum with underlying type
scoped enum with default underlying type
The same applies if Salutation has a specified underlying type:
scoped enum with specified underlying type
you still can't use list initialization for numeric values
Fixed Direct List Initialization with auto
Since C++17 exception handling specifications became part of the type of a function
It is not allowed to overload a function name for the same signature with a different exception specification (as it is not allowed to overload functions with different return types only):
在template programming中,注意noexcept也為type的一部分!
__has_include
Deduction Guides
We can define specific deduction guides to provide additional or fix existing class template argument deductions.
e.g:
A corresponding deduction guide sounds very reasonable for any class template having a constructor taking an object of its template parameter by reference.
Non-Template Deduction Guides
(the deduction works, but the initialization is not allowed):
Class template argument deduction uses the constructor/guide that has the highest priority according to overload resolution.
If a constructor and a deduction guide match equally well, the deduction guide is preferred.
Explicit Deduction Guides
Deduction Guides for Aggregates
Standard Deduction Guides Deduction from Iterators
std::array<> Deduction
if constexpr
注意,任何type T dependable expression can be failed which is OK.
Expression without T dependable will not compile if the expression is itself invalid.
No Short-Circuit Compile-Time Conditions.
Fold Expressions
Motivation for Fold Expressions:
Since before, we can't extract Arg... but only to implement function with recursive calls and retract argument one by one.Supported Operators:
all binary operators for fold expressions except .->
[]
Fold expression can also be used for the comma operator, combining multiple expressions into one statement.
Dealing with Strings as Template Parameters
Non-type template parameters can be only- constant integral values (including enumerations),
- pointers to objects/functions/members,
- lvalue references to objects
- or functions, or std::nullptr_t (the type of nullptr)
However, since C++17, you can have pointers with internal linkage.
For example:
No comments:
Post a Comment
Note: Only a member of this blog may post a comment.