SlideShare a Scribd company logo
1 of 188
Download to read offline
Mateusz Pusz
April 9, 2018
BEYOND C++17
4Developers 2018 | Beyond C++17
C++ TIMELINE
2
4Developers 2018 | Beyond C++17
ISO C++ COMMITTEE STRUCTURE
3
DEPENDS ON CURRENT TARGET (ESTIMATED)
Coroutines C++20
Contracts C++20
Ranges
Core concepts in C++20
Rest in C++20 or 23
Modules
Core concepts in C++20
Rest in (TBD) focusing on a bridge from header files
Reflection TS in C++20 timeframe; IS in C++23
Executors TS in C++20 timeframe; IS in C++23
Networking TS Executors IS in C++23
future.then, async2 Executors IS in C++23
4Developers 2018 | Beyond C++17
MAJOR FEATURES STATUS
4
• Usage info
– wg21.link
• Get paper
– wg21.link/nXXXX
– wg21.link/pXXXX - latest version (e.g. wg21.link/p0463)
– wg21.link/pXXXXrX
• Get working dra
– wg21.link/standard
– wg21.link/concepts
– wg21.link/coroutines
– wg21.link/modules
– wg21.link/networking
– wg21.link/ranges
4Developers 2018 | Beyond C++17
FINDING A PAPER - HTTPS://WG21.LINK
5
NEW FEATURES
C++20
• Concepts TS standardised 2 years ago
• No consensus on merging to IS as is
• Consensus reached by postponing the merge of
– introducer syntax
– terse/natural syntax
• Small changes approved
– removed bool from concept syntax
– removed function concepts
• P0734 C++ extensions for Concepts merged with IS
4Developers 2018 | Beyond C++17
CONCEPTS
7
Concept definition
template<class T>
concept Sortable { /* ... */ }
Original template notation
template<typename T>
requires Sortable<T>
void sort(T&);
The shorthand notation
template<Sortable T>
void sort(T&);
4Developers 2018 | Beyond C++17
C++ CONCEPTS IN ACTION
ACCEPTED FEATURES
8
Concept definition
template<class T>
concept Sortable { /* ... */ }
Original template notation
template<typename T>
requires Sortable<T>
void sort(T&);
The shorthand notation
template<Sortable T>
void sort(T&);
The terse/natural notation
void sort(Sortable&);
// Not merged to IS
The concept introducer notation
Sortable{Seq} void sort(Seq&);
// Not merged to IS
4Developers 2018 | Beyond C++17
C++ CONCEPTS IN ACTION
ACCEPTED FEATURES NOT ACCEPTED FEATURES
8
template<typename T>
void f(T&& t)
{
if(t == other) { /* ... */ }
}
void foo()
{
f("abc"s); // OK
std::mutex mtx;
f(mtx); // Error
}
4Developers 2018 | Beyond C++17
CONSTRAINTS AND CONCEPTS
9
<source>: In instantiation of 'void f(T&&) [with T = std::mutex&]':
28 : <source>:28:8: required from here
15 : <source>:15:8: error: no match for 'operator==' (operand types are 'std::mutex' and 'std::mutex')
if(t == other) {
~~^~~~~~~~
In file included from /opt/compiler-explorer/gcc-7.2.0/include/c++/7.2.0/mutex:42:0,
from <source>:2:
/opt/compiler-explorer/gcc-7.2.0/include/c++/7.2.0/system_error:311:3: note: candidate: bool std::operator==(const std::error_cond
operator==(const error_condition& __lhs,
^~~~~~~~
/opt/compiler-explorer/gcc-7.2.0/include/c++/7.2.0/system_error:311:3: note: no known conversion for argument 1 from 'std::mutex
/opt/compiler-explorer/gcc-7.2.0/include/c++/7.2.0/system_error:304:3: note: candidate: bool std::operator==(const std::error_cond
operator==(const error_condition& __lhs, const error_code& __rhs) noexcept
^~~~~~~~
... 290 lines more ...
In file included from /opt/compiler-explorer/gcc-7.2.0/include/c++/7.2.0/bits/stl_algobase.h:64:0,
from /opt/compiler-explorer/gcc-7.2.0/include/c++/7.2.0/memory:62,
from <source>:1:
/opt/compiler-explorer/gcc-7.2.0/include/c++/7.2.0/bits/stl_pair.h:443:5: note: candidate: template<class _T1, class _T2> constexp
operator==(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y)
^~~~~~~~
/opt/compiler-explorer/gcc-7.2.0/include/c++/7.2.0/bits/stl_pair.h:443:5: note: template argument deduction/substitution failed
15 : <source>:15:8: note: 'std::mutex' is not derived from 'const std::pair<_T1, _T2>'
if(t == other) {
~~^~~~~~~~
Compiler exited with result code 1
4Developers 2018 | Beyond C++17
CONSTRAINTS AND CONCEPTS
10
template<typename T>
concept EqualityComparable = requires(T a, T b) {
a == b; requires Boolean<decltype(a == b)>; // simplified definition
};
4Developers 2018 | Beyond C++17
CONSTRAINTS AND CONCEPTS
11
template<typename T>
concept EqualityComparable = requires(T a, T b) {
a == b; requires Boolean<decltype(a == b)>; // simplified definition
};
template<typename T>
requires EqualityComparable<T>
void f(T&& t)
{
if(t == other) { /* ... */ }
}
4Developers 2018 | Beyond C++17
CONSTRAINTS AND CONCEPTS
11
template<typename T>
concept EqualityComparable = requires(T a, T b) {
a == b; requires Boolean<decltype(a == b)>; // simplified definition
};
template<typename T>
requires EqualityComparable<T>
void f(T&& t)
{
if(t == other) { /* ... */ }
}
void foo()
{
f("abc"s); // OK
std::mutex mtx;
std::unique_lock<std::mutex> lock{mtx};
f(mtx); // Error: not EqualityComparable
}
4Developers 2018 | Beyond C++17
CONSTRAINTS AND CONCEPTS
11
<source>: In function 'void foo()':
28 : <source>:28:8: error: cannot call function 'void f(T&&) [with T = std::mutex&]'
f(mtx); // Error: not EqualityComparable
^
12 : <source>:12:6: note: constraints not satisfied
void f(T&& t)
^
6 : <source>:6:14: note: within 'template<class T> concept const bool EqualityComparable<T> [with T = std::mutex&]'
concept bool EqualityComparable = requires(T a, T b) {
^~~~~~~~~~~~~~~~~~
6 : <source>:6:14: note: with 'std::mutex& a'
6 : <source>:6:14: note: with 'std::mutex& b'
6 : <source>:6:14: note: the required expression '(a == b)' would be ill-formed
Compiler exited with result code 1
4Developers 2018 | Beyond C++17
CONSTRAINTS AND CONCEPTS
12
#include <stdio.h>
#include <time.h>
static const char* const wday[] =
{
"Sunday", "Monday", "Tuesday", "Wednesday",
"Thursday", "Friday", "Saturday", "-unknown-"
};
int main()
{
struct tm time_str;
time_str.tm_year = 2001 - 1900;
time_str.tm_mon = 7 - 1;
time_str.tm_mday = 4;
time_str.tm_hour = 0;
time_str.tm_min = 0;
time_str.tm_sec = 0;
time_str.tm_isdst = -1;
if (mktime(&time_str) == (time_t)(-1))
time_str.tm_wday = 7;
printf("%sn", wday[time_str.tm_wday]);
}
4Developers 2018 | Beyond C++17
WHAT DAY OF THE WEEK IS JULY 4, 2001?
C
13
#include <stdio.h>
#include <time.h>
static const char* const wday[] =
{
"Sunday", "Monday", "Tuesday", "Wednesday",
"Thursday", "Friday", "Saturday", "-unknown-"
};
int main()
{
struct tm time_str;
time_str.tm_year = 2001 - 1900;
time_str.tm_mon = 7 - 1;
time_str.tm_mday = 4;
time_str.tm_hour = 0;
time_str.tm_min = 0;
time_str.tm_sec = 0;
time_str.tm_isdst = -1;
if (mktime(&time_str) == (time_t)(-1))
time_str.tm_wday = 7;
printf("%sn", wday[time_str.tm_wday]);
}
#include <chrono>
#include <iostream>
int main()
{
using namespace std::chrono;
std::cout << weekday{jul/4/2001} << 'n';
}
4Developers 2018 | Beyond C++17
WHAT DAY OF THE WEEK IS JULY 4, 2001?
C C++20
13
• Seamless integration with the existing library
• Type safety
• Detection of errors at compile time
• Performance
• Ease of use
• Readable code
• No artificial restrictions on precision
4Developers 2018 | Beyond C++17
P0355 EXTENDING CHRONO TO CALENDARS AND TIME ZONES
GOALS
14
constexpr year_month_day ymd1{2016y, month{5}, day{29}};
constexpr auto ymd2 = 2016y/may/29d;
constexpr auto ymd3 = sun[5]/may/2016;
4Developers 2018 | Beyond C++17
P0355 EXTENDING CHRONO TO CALENDARS AND TIME ZONES
EXAMPLES
15
constexpr year_month_day ymd1{2016y, month{5}, day{29}};
constexpr auto ymd2 = 2016y/may/29d;
constexpr auto ymd3 = sun[5]/may/2016;
constexpr system_clock::time_point tp = sys_days{sun[5]/may/2016};// Convert date to time_point
static_assert(tp.time_since_epoch() == 1'464'480'000'000'000us);
constexpr auto ymd = year_month_weekday{floor<days>(tp)}; // Convert time_point to date
static_assert(ymd == sun[5]/may/2016);
4Developers 2018 | Beyond C++17
P0355 EXTENDING CHRONO TO CALENDARS AND TIME ZONES
EXAMPLES
15
constexpr year_month_day ymd1{2016y, month{5}, day{29}};
constexpr auto ymd2 = 2016y/may/29d;
constexpr auto ymd3 = sun[5]/may/2016;
constexpr system_clock::time_point tp = sys_days{sun[5]/may/2016};// Convert date to time_point
static_assert(tp.time_since_epoch() == 1'464'480'000'000'000us);
constexpr auto ymd = year_month_weekday{floor<days>(tp)}; // Convert time_point to date
static_assert(ymd == sun[5]/may/2016);
auto tp = sys_days{2016y/may/29d} + 7h + 30min + 6s + 153ms; // 2016-05-29 07:30:06.153 UTC
zoned_time zt = {"Asia/Tokyo", tp};
cout << zt << 'n'; // 2016-05-29 16:30:06.153 JST
4Developers 2018 | Beyond C++17
P0355 EXTENDING CHRONO TO CALENDARS AND TIME ZONES
EXAMPLES
15
• Minimal extensions to <chrono> to support calendar and time zone libraries
• A proleptic Gregorian calendar (civil calendar)
• A time zone library based on the IANA Time Zone Database
• strftime-like formatting and parsing facilities with fully operational support for fractional seconds,
time zone abbreviations, and UTC o sets
• Several <chrono> clocks for computing with leap seconds which is also supported by the IANA Time
Zone Database
4Developers 2018 | Beyond C++17
P0355 EXTENDING CHRONO TO CALENDARS AND TIME ZONES
FEATURES
16
• Calendar: http://howardhinnant.github.io/date/date.html
• TimeZone: http://howardhinnant.github.io/date/tz.html
• Calendar: https://www.youtube.com/watch?v=tzyGjOm8AKo
• Time Zone: https://www.youtube.com/watch?v=Vwd3pduVGKY
• https://github.com/HowardHinnant/date
4Developers 2018 | Beyond C++17
P0355 EXTENDING CHRONO TO CALENDARS AND TIME ZONES
DOCUMENTATION
VIDEO INTRODUCTION
FULL IMPLEMENTATION
17
The span type is an abstraction that provides a view over a
contiguous sequence of objects, the storage of which is owned by
some other object.
4Developers 2018 | Beyond C++17
P0122 <span>
18
The span type is an abstraction that provides a view over a
contiguous sequence of objects, the storage of which is owned by
some other object.
• Simply a view over another object’s contiguous storage – it does not own the elements that are
accessible through its interface (similarly to std::string_view)
• Never performs any free store allocations
4Developers 2018 | Beyond C++17
P0122 <span>
VIEW, NOT CONTAINER
18
constexpr ptrdiff_t dynamic_extent = -1;
template <class ElementType, ptrdiff_t Extent = dynamic_extent>
class span;
4Developers 2018 | Beyond C++17
P0122 <span>
19
constexpr ptrdiff_t dynamic_extent = -1;
template <class ElementType, ptrdiff_t Extent = dynamic_extent>
class span;
• dynamic_extent is a unique value outside the normal range of lengths reserved to indicate that the
length of the sequence is only known at runtime and must be stored within the span
• A dynamic-size span is, conceptually, just a pointer and size field
int* somePointer = new int[someLength];
span<int> s{somePointer, someLength};
4Developers 2018 | Beyond C++17
P0122 <span>
DYNAMIC-SIZE (PROVIDED AT RUNTIME)
19
constexpr ptrdiff_t dynamic_extent = -1;
template <class ElementType, ptrdiff_t Extent = dynamic_extent>
class span;
• Provides a value for Extent that is between 0 and PTRDIFF_MAX (inclusive)
• Requires no storage size overhead beyond a single pointer
int arr[10];
span<int, 10> s1{arr}; // fixed-size span of 10 ints
// span<int, 20> s2{arr}; // ERROR: will fail to compile
span<int> s3{arr}; // dynamic-size span of 10 ints
4Developers 2018 | Beyond C++17
P0122 <span>
STATIC-SIZE (FIXED AT COMPILE-TIME)
20
constexpr ptrdiff_t dynamic_extent = -1;
template <class ElementType, ptrdiff_t Extent = dynamic_extent>
class span;
• A fixed-size span may be constructed or assigned from another fixed-size span of equal length
• A dynamic-size span may always be constructed or assigned from a fixed-size span
• A fixed-size span may always be constructed or assigned from a dynamic-size span
– undefined behavior will result if the construction or assignment is not bounds-safe
4Developers 2018 | Beyond C++17
P0122 <span>
FIXED AND STATIC SIZE CONVERSIONS
21
constexpr span();
constexpr span(pointer ptr, index_type count);
constexpr span(pointer firstElem, pointer lastElem);
template <size_t N>
constexpr span(element_type (&arr)[N]);
template <size_t N>
constexpr span(array<remove_const_t<element_type>, N>& arr);
template <size_t N>
constexpr span(const array<remove_const_t<element_type>, N>& arr);
template <class Container>
constexpr span(Container& cont);
template <class Container>
constexpr span(const Container& cont);
constexpr span(const span& other) noexcept = default;
template <class OtherElementType, ptrdiff_t OtherExtent>
constexpr span(const span<OtherElementType, OtherExtent>& other);
4Developers 2018 | Beyond C++17
P0122 <span>
CONSTRUCTION
22
constexpr reference operator[](index_type idx) const;
constexpr reference operator()(index_type idx) const;
constexpr pointer data() const noexcept;
4Developers 2018 | Beyond C++17
P0122 <span>
ELEMENT ACCESS AND ITERATION
23
constexpr reference operator[](index_type idx) const;
constexpr reference operator()(index_type idx) const;
constexpr pointer data() const noexcept;
constexpr iterator begin() const noexcept;
constexpr iterator end() const noexcept;
constexpr const_iterator cbegin() const noexcept;
constexpr const_iterator cend() const noexcept;
constexpr reverse_iterator rbegin() const noexcept;
constexpr reverse_iterator rend() const noexcept;
constexpr const_reverse_iterator crbegin() const noexcept;
constexpr const_reverse_iterator crend() const noexcept;
4Developers 2018 | Beyond C++17
P0122 <span>
ELEMENT ACCESS AND ITERATION
23
template <class ElementType, ptrdiff_t Extent>
span<const byte, ((Extent == dynamic_extent) ? dynamic_extent : (sizeof(ElementType)*Extent))>
as_bytes(span<ElementType, Extent> s) noexcept;
template <class ElementType, ptrdiff_t Extent>
span<byte, ((Extent == dynamic_extent) ? dynamic_extent : (sizeof(ElementType)*Extent))>
as_writeable_bytes(span<ElementType, Extent>) noexcept;
4Developers 2018 | Beyond C++17
P0122 <span>
BYTE REPRESENTATIONS AND CONVERSIONS
24
template <class ElementType, ptrdiff_t Extent>
constexpr bool operator==(span<ElementType, Extent> l, span<ElementType, Extent> r);
template <class ElementType, ptrdiff_t Extent>
constexpr bool operator!=(span<ElementType, Extent> l, span<ElementType, Extent> r);
template <class ElementType, ptrdiff_t Extent>
constexpr bool operator<(span<ElementType, Extent> l, span<ElementType, Extent> r);
template <class ElementType, ptrdiff_t Extent>
constexpr bool operator<=(span<ElementType, Extent> l, span<ElementType, Extent> r);
template <class ElementType, ptrdiff_t Extent>
constexpr bool operator>(span<ElementType, Extent> l, span<ElementType, Extent> r);
template <class ElementType, ptrdiff_t Extent>
constexpr bool operator>=(span<ElementType, Extent> l, span<ElementType, Extent> r);
4Developers 2018 | Beyond C++17
P0122 <span>
COMPARISONS
25
constexpr span<element_type, dynamic_extent> first(index_type count) const;
constexpr span<element_type, dynamic_extent> last(index_type count) const;
constexpr span<element_type, dynamic_extent> subspan(index_type offset,
index_type count = dynamic_extent) const;
4Developers 2018 | Beyond C++17
P0122 <span>
CREATING SUB-SPANS
26
constexpr span<element_type, dynamic_extent> first(index_type count) const;
constexpr span<element_type, dynamic_extent> last(index_type count) const;
constexpr span<element_type, dynamic_extent> subspan(index_type offset,
index_type count = dynamic_extent) const;
template <ptrdiff_t Count>
constexpr span<element_type, Count> first() const;
template <ptrdiff_t Count>
constexpr span<element_type, Count> last() const;
template <ptrdiff_t Offset, ptrdiff_t Count = dynamic_extent>
constexpr span<element_type, Count> subspan() const;
4Developers 2018 | Beyond C++17
P0122 <span>
CREATING SUB-SPANS
26
• Cheap to construct, copy, move, and use
• Users are encouraged to use it as a pass-by-value parameter type
• Construction or assignment between span objects with di erent element types is allowed whenever it
can be determined statically that the element types are exactly storage-size equivalent
• It is always possible to convert from a span<T> to a span<const T>, it is not allowed to convert in the
opposite direction, from span<const T> to span<T> s- Span has a trivial destructor, so common ABI
conventions allow it to be passed in registers
4Developers 2018 | Beyond C++17
P0122 <span>
27
class P {
int x;
int y;
public:
friend bool operator==(const P& a, const P& b)
{ return a.x==b.x && a.y==b.y; }
friend bool operator< (const P& a, const P& b)
{ return a.x<b.x || (a.x==b.x && a.y<b.y); }
friend bool operator!=(const P& a, const P& b)
{ return !(a==b); }
friend bool operator<=(const P& a, const P& b)
{ return !(b<a); }
friend bool operator> (const P& a, const P& b)
{ return b<a; }
friend bool operator>=(const P& a, const P& b)
{ return !(a<b); }
// ... non-comparison functions ...
};
4Developers 2018 | Beyond C++17
P0515 P0768 P0905 CONSISTENT COMPARISON
C++17
28
class P {
int x;
int y;
public:
friend bool operator==(const P& a, const P& b)
{ return a.x==b.x && a.y==b.y; }
friend bool operator< (const P& a, const P& b)
{ return a.x<b.x || (a.x==b.x && a.y<b.y); }
friend bool operator!=(const P& a, const P& b)
{ return !(a==b); }
friend bool operator<=(const P& a, const P& b)
{ return !(b<a); }
friend bool operator> (const P& a, const P& b)
{ return b<a; }
friend bool operator>=(const P& a, const P& b)
{ return !(a<b); }
// ... non-comparison functions ...
};
class P {
int x;
int y;
public:
auto operator<=>(const P&) const = default;
// ... non-comparison functions ...
};
• a <=> b returns an object that compares
– <0 if a < b
– >0 if a > b
– ==0 if a and b are equal/equivalent
• Memberwise semantics by default
• Commonly known as a spaceship operator
4Developers 2018 | Beyond C++17
P0515 P0768 P0905 CONSISTENT COMPARISON
C++17 C++20
28
class ci_string {
std::string s;
public:
// ...
friend bool operator==(const ci_string& a, const ci_string& b) { return ci_compare(a.s.c_str(), b.s.c_str()) != 0; }
friend bool operator< (const ci_string& a, const ci_string& b) { return ci_compare(a.s.c_str(), b.s.c_str()) < 0; }
friend bool operator!=(const ci_string& a, const ci_string& b) { return !(a == b); }
friend bool operator> (const ci_string& a, const ci_string& b) { return b < a; }
friend bool operator>=(const ci_string& a, const ci_string& b) { return !(a < b); }
friend bool operator<=(const ci_string& a, const ci_string& b) { return !(b < a); }
friend bool operator==(const ci_string& a, const char* b) { return ci_compare(a.s.c_str(), b) != 0; }
friend bool operator< (const ci_string& a, const char* b) { return ci_compare(a.s.c_str(), b) < 0; }
friend bool operator!=(const ci_string& a, const char* b) { return !(a == b); }
friend bool operator> (const ci_string& a, const char* b) { return b < a; }
friend bool operator>=(const ci_string& a, const char* b) { return !(a < b); }
friend bool operator<=(const ci_string& a, const char* b) { return !(b < a); }
friend bool operator==(const char* a, const ci_string& b) { return ci_compare(a, b.s.c_str()) != 0; }
friend bool operator< (const char* a, const ci_string& b) { return ci_compare(a, b.s.c_str()) < 0; }
friend bool operator!=(const char* a, const ci_string& b) { return !(a == b); }
friend bool operator> (const char* a, const ci_string& b) { return b < a; }
friend bool operator>=(const char* a, const ci_string& b) { return !(a < b); }
friend bool operator<=(const char* a, const ci_string& b) { return !(b < a); }
};
4Developers 2018 | Beyond C++17
P0515 P0768 P0905 CONSISTENT COMPARISON
29
class ci_string {
std::string s;
public:
// ...
std::weak_ordering operator<=>(const ci_string& b) const { return ci_compare(s.c_str(), b.s.c_str()); }
std::weak_ordering operator<=>(const char* b) const { return ci_compare(s.c_str(), b); }
};
4Developers 2018 | Beyond C++17
P0515 P0768 P0905 CONSISTENT COMPARISON
30
class ci_string {
std::string s;
public:
// ...
std::weak_ordering operator<=>(const ci_string& b) const { return ci_compare(s.c_str(), b.s.c_str()); }
std::weak_ordering operator<=>(const char* b) const { return ci_compare(s.c_str(), b); }
};
• <compare> header needed when user manually provides <=> implementation
TYPE RETURNED FROM OPERATOR<=>() A<B SUPPORTED A<B NOT SUPPORTED
a==b => f(a)==f(b) std::strong_ordering std::strong_equality
a==b => f(a)!=f(b) std::weak_ordering std::weak_equality
4Developers 2018 | Beyond C++17
P0515 P0768 P0905 CONSISTENT COMPARISON
30
class ci_string {
std::string s;
public:
// ...
std::weak_ordering operator<=>(const ci_string& b) const { return ci_compare(s.c_str(), b.s.c_str()); }
std::weak_ordering operator<=>(const char* b) const { return ci_compare(s.c_str(), b); }
};
• <compare> header needed when user manually provides <=> implementation
TYPE RETURNED FROM OPERATOR<=>() A<B SUPPORTED A<B NOT SUPPORTED
a==b => f(a)==f(b) std::strong_ordering std::strong_equality
a==b => f(a)!=f(b) std::weak_ordering std::weak_equality
4Developers 2018 | Beyond C++17
P0515 P0768 P0905 CONSISTENT COMPARISON
<=> operator nearly ended in a header named "=" ;-)
30
class totally_ordered : base {
std::string tax_id_;
std::string first_name_;
std::string last_name_;
public:
std::strong_ordering operator<=>(const totally_ordered& other) const
{
if(auto cmp = (base&)(*this) <=> (base&)other; cmp != 0) return cmp;
if(auto cmp = last_name_ <=> other.last_name_; cmp != 0) return cmp;
if(auto cmp = first_name_ <=> other.first_name_; cmp != 0) return cmp;
return tax_id_ <=> other.tax_id_;
}
// ... non-comparison functions ...
};
4Developers 2018 | Beyond C++17
P0515 P0768 P0905 CONSISTENT COMPARISON
31
class totally_ordered : base {
std::string tax_id_;
std::string first_name_;
std::string last_name_;
public:
std::strong_ordering operator<=>(const totally_ordered& other) const
{
if(auto cmp = (base&)(*this) <=> (base&)other; cmp != 0) return cmp;
if(auto cmp = last_name_ <=> other.last_name_; cmp != 0) return cmp;
if(auto cmp = first_name_ <=> other.first_name_; cmp != 0) return cmp;
return tax_id_ <=> other.tax_id_;
}
// ... non-comparison functions ...
};
4Developers 2018 | Beyond C++17
P0515 P0768 P0905 CONSISTENT COMPARISON
Compile-time error if a member does not have a strong_ordering
31
TYPE CATEGORY
bool, integral, pointer types std::strong_ordering
floating point types std::partial_ordering
enumerations the same as underlying type
std::nullptr_t std::strong_ordering
copyable arrays T[N] the same as T
other arrays no <=>
void no <=>
All built-in <=> comparisons are constexpr beside pointers into the di erent object/allocation
4Developers 2018 | Beyond C++17
P0515 P0768 P0905 CONSISTENT COMPARISON
32
class std::weak_equality;
class std::strong_equality;
class std::partial_ordering;
class std::weak_ordering;
class std::strong_ordering;
4Developers 2018 | Beyond C++17
P0515 P0768 P0905 CONSISTENT COMPARISON
33
class std::weak_equality;
class std::strong_equality;
class std::partial_ordering;
class std::weak_ordering;
class std::strong_ordering;
constexpr bool std::is_eq (std::weak_equality cmp) noexcept { return cmp == 0; }
constexpr bool std::is_neq (std::weak_equality cmp) noexcept { return cmp != 0; }
constexpr bool std::is_lt (std::partial_ordering cmp) noexcept { return cmp < 0; }
constexpr bool std::is_lteq(std::partial_ordering cmp) noexcept { return cmp <= 0; }
constexpr bool std::is_gt (std::partial_ordering cmp) noexcept { return cmp > 0; }
constexpr bool std::is_gteq(std::partial_ordering cmp) noexcept { return cmp >= 0; }
4Developers 2018 | Beyond C++17
P0515 P0768 P0905 CONSISTENT COMPARISON
33
class std::weak_equality;
class std::strong_equality;
class std::partial_ordering;
class std::weak_ordering;
class std::strong_ordering;
constexpr bool std::is_eq (std::weak_equality cmp) noexcept { return cmp == 0; }
constexpr bool std::is_neq (std::weak_equality cmp) noexcept { return cmp != 0; }
constexpr bool std::is_lt (std::partial_ordering cmp) noexcept { return cmp < 0; }
constexpr bool std::is_lteq(std::partial_ordering cmp) noexcept { return cmp <= 0; }
constexpr bool std::is_gt (std::partial_ordering cmp) noexcept { return cmp > 0; }
constexpr bool std::is_gteq(std::partial_ordering cmp) noexcept { return cmp >= 0; }
template<class T> constexpr std::strong_ordering std::strong_order (const T& a, const T& b);
template<class T> constexpr std::weak_ordering std::weak_order (const T& a, const T& b);
template<class T> constexpr std::partial_ordering std::partial_order(const T& a, const T& b);
template<class T> constexpr std::strong_equality std::strong_equal (const T& a, const T& b);
template<class T> constexpr std::weak_equality std::weak_equal (const T& a, const T& b);
4Developers 2018 | Beyond C++17
P0515 P0768 P0905 CONSISTENT COMPARISON
33
template<class T, class U>
constexpr auto std::compare_3way(const T& a, const U& b);
template<class InputIterator1, class InputIterator2>
constexpr auto std::lexicographical_compare_3way(InputIterator1 b1, InputIterator1 e1,
InputIterator2 b2, InputIterator2 e2);
template<class InputIterator1, class InputIterator2, class Cmp>
constexpr auto std::lexicographical_compare_3way(InputIterator1 b1, InputIterator1 e1,
InputIterator2 b2, InputIterator2 e2,
Cmp comp)
-> std::common_comparison_category_t<decltype(comp(*b1,*b2)), std::strong_ordering>;
4Developers 2018 | Beyond C++17
P0515 P0768 P0905 CONSISTENT COMPARISON
34
template<class T, class U>
constexpr auto std::compare_3way(const T& a, const U& b);
template<class InputIterator1, class InputIterator2>
constexpr auto std::lexicographical_compare_3way(InputIterator1 b1, InputIterator1 e1,
InputIterator2 b2, InputIterator2 e2);
template<class InputIterator1, class InputIterator2, class Cmp>
constexpr auto std::lexicographical_compare_3way(InputIterator1 b1, InputIterator1 e1,
InputIterator2 b2, InputIterator2 e2,
Cmp comp)
-> std::common_comparison_category_t<decltype(comp(*b1,*b2)), std::strong_ordering>;
4Developers 2018 | Beyond C++17
P0515 P0768 P0905 CONSISTENT COMPARISON
std::rel_ops are now deprecated
34
1 <=> provides total ordering, 2-way operators are changed accordingly
2 2-way unchanged, <=> provides total ordering - inconsistent
3 2-way unchanged, <=> compatible with 2-way, total order not guaranteed
4Developers 2018 | Beyond C++17
P0515 P0768 P0905 CONSISTENT COMPARISON
ISSUE: COMPARING OBJECT POINTERS
Option (3) selected as for today and waiting for more proposals
35
• Atomically transfers the contents of an internal stream bu er to a basic_ostream’s stream bu er on
destruction of the basic_osyncstream
{
std::osyncstream out{std::cout};
out << "Hello, " << "World!" << ’n’;
}
std::osyncstream{std::cout} << "The answer is " << 6*7 << std::endl;
4Developers 2018 | Beyond C++17
P0053 SYNCHRONIZED BUFFERED OSTREAMS
36
template<class charT, class traits, class Allocator>
class basic_syncbuf : public basic_streambuf<charT, traits> {
public:
bool emit();
streambuf_type* get_wrapped() const noexcept;
void set_emit_on_sync(bool) noexcept;
protected:
int sync() override;
// ...
};
using syncbuf = basic_syncbuf<char>;
using wsyncbuf = basic_syncbuf<wchar_t>;
• emit() atomically transfers the contents of the internal bu er to the wrapped stream bu er, so that
they appear in the output stream as a contiguous sequence of characters
• sync() records that the wrapped stream bu er is to be flushed, then, if emit_on_sync == true, calls
emit()
4Developers 2018 | Beyond C++17
P0053 SYNCHRONIZED BUFFERED OSTREAMS
37
template<class charT, class traits, class Allocator>
class basic_osyncstream : public basic_ostream<charT, traits> {
basic_syncbuf<charT, traits, Allocator> sb_;
public:
void emit() { sb_.emit(); }
streambuf_type* get_wrapped() const noexcept { return sb_.get_wrapped(); }
syncbuf_type* rdbuf() const noexcept { return &sb_; }
// ...
};
using osyncstream = basic_osyncstream<char>;
using wosyncstream = basic_osyncstream<wchar_t>;
4Developers 2018 | Beyond C++17
P0053 SYNCHRONIZED BUFFERED OSTREAMS
38
{
std::osyncstream out{std::cout};
out << "Hello," << ’n’; // no flush
out.emit(); // characters transferred; cout not flushed
out << "World!" << std::endl; // flush noted; out not flushed
out.emit(); // characters transferred; cout flushed
out << "Greetings." << ’n’; // no flush
} // characters transferred; cout not flushed
4Developers 2018 | Beyond C++17
P0053 SYNCHRONIZED BUFFERED OSTREAMS
EXAMPLE: A FLUSH ON A BASIC_OSYNCSTREAM DOES NOT FLUSH IMMEDIATELY
39
{
std::osyncstream out1{std::cout};
out1 << "Hello, ";
{
std::osyncstream(out1.get_wrapped()) << "Goodbye, " << "Planet!" << ’n’;
}
out1 << "World!" << ’n’;
}
Goodbye, Planet!
Hello, World!
4Developers 2018 | Beyond C++17
P0053 SYNCHRONIZED BUFFERED OSTREAMS
EXAMPLE: OBTAINING THE WRAPPED STREAM BUFFER WITH GET_WRAPPED() ALLOWS WRAPPING IT
AGAIN WITH AN OSYNCSTREAM
40
Users of basic_osyncstream known only via ostream& down the call chain do not have the possibility to
modify their flushing behavior.
4Developers 2018 | Beyond C++17
P0753 MANIPULATORS FOR C++ SYNCHRONIZED BUFFERED
OSTREAM
MOTIVATION
41
Users of basic_osyncstream known only via ostream& down the call chain do not have the possibility to
modify their flushing behavior.
Add the following manipulators for ostream
template <class charT, class traits>
basic_ostream<charT, traits>& emit_on_flush(basic_ostream<charT, traits>& os);
template <class charT, class traits>
basic_ostream<charT, traits>& noemit_on_flush(basic_ostream<charT, traits>& os);
template <class charT, class traits>
basic_ostream<charT, traits>& flush_emit(basic_ostream<charT, traits>& os);
4Developers 2018 | Beyond C++17
P0753 MANIPULATORS FOR C++ SYNCHRONIZED BUFFERED
OSTREAM
MOTIVATION
SOLUTION
41
• The C++ standard provides an API to access and manipulate specific shared_ptr objects atomically
auto ptr = std::make_shared<int>(0);
runThreads(5, [&](int i)
{
std::atomic_store(&ptr, std::make_shared<int>(i));
return *ptr;
});
4Developers 2018 | Beyond C++17
P0718 std::atomic<std::shared_ptr<T>>
MOTIVATION
42
• The C++ standard provides an API to access and manipulate specific shared_ptr objects atomically
auto ptr = std::make_shared<int>(0);
runThreads(5, [&](int i)
{
std::atomic_store(&ptr, std::make_shared<int>(i));
return *ptr;
});
• Fragile and error-prone
– shared_ptr objects manipulated through this API are indistinguishable from other shared_ptr
objects
– They may be manipulated/accessed only through this API (i.e. you cannot dereference such a
shared_ptr without first loading it into another shared_ptr object, and then dereferencing
through the second object)
4Developers 2018 | Beyond C++17
P0718 std::atomic<std::shared_ptr<T>>
MOTIVATION
42
• Merge atomic_shared_ptr from Concurrency TS into IS
• Refactor to be std::atomic specializations for smart pointers
template<class T>
struct std::atomic<std::shared_ptr<T>>;
template<class T>
struct std::atomic<std::weak_ptr<T>>;
4Developers 2018 | Beyond C++17
P0718 std::atomic<std::shared_ptr<T>>
43
• Merge atomic_shared_ptr from Concurrency TS into IS
• Refactor to be std::atomic specializations for smart pointers
template<class T>
struct std::atomic<std::shared_ptr<T>>;
template<class T>
struct std::atomic<std::weak_ptr<T>>;
• The C++11 Atomic Interface for shared_ptr is deprecated
4Developers 2018 | Beyond C++17
P0718 std::atomic<std::shared_ptr<T>>
43
• Adds support for atomic addition on an object conforming to the std::atomic<T> where T is a
floating-point type
• Capability critical for parallel high performance computing (HPC) applications
• Explicit specialization for float, double, long double to provide additional atomic operations
appropriate to floating-point types
4Developers 2018 | Beyond C++17
P0020 FLOATING POINT ATOMIC
44
EBO idiom introduces a number of problems
4Developers 2018 | Beyond C++17
P0840 LANGUAGE SUPPORT FOR EMPTY OBJECTS
MOTIVATION
45
EBO idiom introduces a number of problems
• Limited applicability
– EBO is not available for final classes, nor for classes with virtual bases that have non-public
destructors
4Developers 2018 | Beyond C++17
P0840 LANGUAGE SUPPORT FOR EMPTY OBJECTS
MOTIVATION
45
EBO idiom introduces a number of problems
• Limited applicability
– EBO is not available for final classes, nor for classes with virtual bases that have non-public
destructors
• Name leakage
– member names of base classes are visible to users of the derived class (unless shadowed), even if
the base class is inaccessible
– unqualified lookups in code deriving from the class employing EBO is a ected by names in the EBO
base class
4Developers 2018 | Beyond C++17
P0840 LANGUAGE SUPPORT FOR EMPTY OBJECTS
MOTIVATION
45
EBO idiom introduces a number of problems
• Limited applicability
– EBO is not available for final classes, nor for classes with virtual bases that have non-public
destructors
• Name leakage
– member names of base classes are visible to users of the derived class (unless shadowed), even if
the base class is inaccessible
– unqualified lookups in code deriving from the class employing EBO is a ected by names in the EBO
base class
• Implementation awkwardness
– EBO requires state that would naturally be represented as a data member to be moved into a base
class
4Developers 2018 | Beyond C++17
P0840 LANGUAGE SUPPORT FOR EMPTY OBJECTS
MOTIVATION
45
• Unique address is not required for an non-static data member of a class
• A non-static data member with this attribute may share its address with another object, if it could
when used as a base class
• It is meant to replace EBO Idiom
4Developers 2018 | Beyond C++17
P0840 LANGUAGE SUPPORT FOR EMPTY OBJECTS
SOLUTION
46
• Unique address is not required for an non-static data member of a class
• A non-static data member with this attribute may share its address with another object, if it could
when used as a base class
• It is meant to replace EBO Idiom
template<typename Key, typename Value, typename Hash, typename Pred, typename Allocator>
class hash_map {
[[no_unique_address]] Hash hasher;
[[no_unique_address]] Pred pred;
[[no_unique_address]] Allocator alloc;
Bucket *buckets;
// ...
public:
// ...
};
4Developers 2018 | Beyond C++17
P0840 LANGUAGE SUPPORT FOR EMPTY OBJECTS
SOLUTION
46
• Compiler's optimizers o en have no information relating to branch probability which can lead to
suboptimal code generation
• In many cases the excellent dynamic branch predictors on modern processors can make up for this
lack of information
• However in some cases code may execute more slowly than necessary even though the programmer
knew the probability of particular branches being executed
• Currently code developers do not have an easy way to communicate this to the compiler
4Developers 2018 | Beyond C++17
P0479 PROPOSED WORDING FOR likely AND unlikely
ATTRIBUTES
MOTIVATION
47
• The attribute-tokens likely and unlikely may be applied to statements
• They shall appear at most once in each attribute-list and no attribute-argument-clause shall be
present
• The likely attribute is not allowed to appear in the same attribute-list as the unlikely attribute
4Developers 2018 | Beyond C++17
P0479 PROPOSED WORDING FOR likely AND unlikely
ATTRIBUTES
SOLUTION
48
• When a [[likely]] attribute appears in an if statement, implementations are encouraged to
optimize for the case where that statement is executed
if (foo()) [[likely]] {
baz();
}
4Developers 2018 | Beyond C++17
P0479 PROPOSED WORDING FOR likely AND unlikely
ATTRIBUTES
49
• When a [[likely]] attribute appears in an if statement, implementations are encouraged to
optimize for the case where that statement is executed
if (foo()) [[likely]] {
baz();
}
• When a [[likely]] attributes appears in a nested if statement, implementations are encouraged to
optimize for the case where that statement is executed
if (foo()) {
if (bar()) [[likely]] {
baz();
}
}
4Developers 2018 | Beyond C++17
P0479 PROPOSED WORDING FOR likely AND unlikely
ATTRIBUTES
49
• When a [[likely]] attribute appears inside of a switch case statement, implementations are
encouraged to optimize for that case being executed
switch (a) {
case 1:
[[likely]] foo();
break;
case 2:
bar();
break;
default:
baz();
break;
}
4Developers 2018 | Beyond C++17
P0479 PROPOSED WORDING FOR likely AND unlikely
ATTRIBUTES
50
• When an [[unlikely]] attribute appears inside of a loop, implementations are encouraged to
optimize for the case where that statement is not executed
while (foo()) {
[[unlikely]] baz();
}
4Developers 2018 | Beyond C++17
P0479 PROPOSED WORDING FOR likely AND unlikely
ATTRIBUTES
51
• When an [[unlikely]] attribute appears inside of a loop, implementations are encouraged to
optimize for the case where that statement is not executed
while (foo()) {
[[unlikely]] baz();
}
4Developers 2018 | Beyond C++17
P0479 PROPOSED WORDING FOR likely AND unlikely
ATTRIBUTES
Excessive usage of either of these attributes is liable to result in performance
degradation
51
enum class endian
{
little = __ORDER_LITTLE_ENDIAN__,
big = __ORDER_BIG_ENDIAN__,
native = __BYTE_ORDER__
};
4Developers 2018 | Beyond C++17
P0463 ENDIAN, JUST ENDIAN
TYPE_TRAITS
52
enum class endian
{
little = __ORDER_LITTLE_ENDIAN__,
big = __ORDER_BIG_ENDIAN__,
native = __BYTE_ORDER__
};
if(endian::native == endian::big)
// handle big endian
else if(endian::native == endian::little)
// handle little endian
else
// handle mixed endian
4Developers 2018 | Beyond C++17
P0463 ENDIAN, JUST ENDIAN
TYPE_TRAITS
52
struct A {
int x;
int y;
int z;
};
A a{.x = 1, .z = 2}; // OK: a.y initialized to 0
A b{.y = 2, .x = 1}; // Error: designator order does not match declaration order
4Developers 2018 | Beyond C++17
P0329 DESIGNATED INITIALIZATION
53
struct A {
int x;
int y;
int z;
};
A a{.x = 1, .z = 2}; // OK: a.y initialized to 0
A b{.y = 2, .x = 1}; // Error: designator order does not match declaration order
struct A {
string a;
int b = 42;
int c = -1;
};
A a{.c = 21}; // a.a initialized to string{}, a.b to 42, a.c to 21
4Developers 2018 | Beyond C++17
P0329 DESIGNATED INITIALIZATION
53
union u {
int a;
const char* b;
};
u a = { 1 };
u d = { 0, "asdf" }; // Error
u e = { "asdf" }; // Error
u f = { .b = "asdf" };
u g = { .a = 1, .b = "asdf" }; // Error
4Developers 2018 | Beyond C++17
P0329 DESIGNATED INITIALIZATION
54
struct S {
int x : 8 = 42;
};
4Developers 2018 | Beyond C++17
P0683 DEFAULT MEMBER INITIALIZERS FOR BIT-FIELDS
55
{
T thing = f();
for(auto& x : thing.items()) {
mutate(&x);
log(x);
}
}
{
for(auto& x : f().items()) { // WRONG
mutate(&x);
log(x);
}
}
4Developers 2018 | Beyond C++17
P0614 RANGE-BASED FOR STATEMENTS WITH INITIALIZER
C++17
56
{
T thing = f();
for(auto& x : thing.items()) {
mutate(&x);
log(x);
}
}
{
for(auto& x : f().items()) { // WRONG
mutate(&x);
log(x);
}
}
for(T thing = f(); auto& x : thing.items()) {
mutate(&x);
log(x);
}
4Developers 2018 | Beyond C++17
P0614 RANGE-BASED FOR STATEMENTS WITH INITIALIZER
C++17 C++20
56
{
std::size_t i = 0;
for(const auto& x : foo()) {
bar(x, i);
++i;
}
}
4Developers 2018 | Beyond C++17
P0614 RANGE-BASED FOR STATEMENTS WITH INITIALIZER
C++17
57
{
std::size_t i = 0;
for(const auto& x : foo()) {
bar(x, i);
++i;
}
}
for(std::size_t i = 0; const auto& x : foo()) {
bar(x, i);
++i;
}
4Developers 2018 | Beyond C++17
P0614 RANGE-BASED FOR STATEMENTS WITH INITIALIZER
C++17 C++20
57
{
std::size_t i = 0;
for(const auto& x : foo()) {
bar(x, i);
++i;
}
}
for(std::size_t i = 0; const auto& x : foo()) {
bar(x, i);
++i;
}
• Enables and encourages locally scoped variables without the programmer having to introduce a scope
manually
4Developers 2018 | Beyond C++17
P0614 RANGE-BASED FOR STATEMENTS WITH INITIALIZER
C++17 C++20
57
• Adds member functions starts_with and ends_with to class templates std::basic_string and
std::basic_string_view
• Check, whether or not a string starts with a given prefix or ends with a given su ix
4Developers 2018 | Beyond C++17
P0457 STRING PREFIX AND SUFFIX CHECKING
58
• Adds member functions starts_with and ends_with to class templates std::basic_string and
std::basic_string_view
• Check, whether or not a string starts with a given prefix or ends with a given su ix
constexpr bool starts_with(basic_string_view x) const noexcept;
constexpr bool starts_with(charT x) const noexcept;
constexpr bool starts_with(const charT* x) const;
constexpr bool ends_with(basic_string_view x) const noexcept;
constexpr bool ends_with(charT x) const noexcept;
constexpr bool ends_with(const charT* x) const;
4Developers 2018 | Beyond C++17
P0457 STRING PREFIX AND SUFFIX CHECKING
58
• New TransformationTrait for the <type_traits> header
• Like std::decay, it removes any cv and reference qualifiers
• Unlike std::decay, it does not mimic any array-to-pointer or function-to-pointer conversion
4Developers 2018 | Beyond C++17
P0550 std::remove_cvref<T>
59
• New TransformationTrait for the <type_traits> header
• Like std::decay, it removes any cv and reference qualifiers
• Unlike std::decay, it does not mimic any array-to-pointer or function-to-pointer conversion
template<typename T>
class optional {
public:
template<typename U = T,
enable_if_t<conjunction_v<negation<is_same<optional<T>, remove_cvref_t<U>>>,
negation<is_same<in_place_t, remove_cvref_t<U>>>,
is_constructible<T, U&&>,
is_convertible<U&&, T>
>, bool> = true>
constexpr optional(U&& t);
// ...
};
4Developers 2018 | Beyond C++17
P0550 std::remove_cvref<T>
59
• New TransformationTrait for the <type_traits> header
• Like std::decay, it removes any cv and reference qualifiers
• Unlike std::decay, it does not mimic any array-to-pointer or function-to-pointer conversion
template<typename T>
class optional {
public:
template<typename U = T,
enable_if_t<conjunction_v<negation<is_same<optional<T>, remove_cvref_t<U>>>,
negation<is_same<in_place_t, remove_cvref_t<U>>>,
is_constructible<T, U&&>,
is_convertible<U&&, T>
>, bool> = true>
constexpr optional(U&& t);
// ...
};
• Above and more wrong std::decay usages fixed with P0777
4Developers 2018 | Beyond C++17
P0550 std::remove_cvref<T>
59
[[nodiscard]] attribute applied to
• async()
• allocate()
• operator new
• launder()
• empty()
4Developers 2018 | Beyond C++17
P0600 [[nodiscard]] ATTRIBUTE IN THE STANDARD LIBRARY
60
• std::addressof(*p) is not well-defined when p does not reference storage that has an object
constructed in it
auto p = a.allocate(1);
std::allocator_traits<A>::construct(a, std::addressof(*p), v); // WRONG
auto p = a.allocate(1);
std::allocator_traits<A>::construct(a, std::to_address(p), v);
4Developers 2018 | Beyond C++17
P0653 UTILITY TO CONVERT A POINTER TO A RAW POINTER
C++17
C++20
61
template<class Ptr>
auto to_address(const Ptr& p) noexcept
{
return to_address(p.operator->());
}
template<class T>
T* to_address(T* p) noexcept
{
return p;
}
4Developers 2018 | Beyond C++17
P0653 UTILITY TO CONVERT A POINTER TO A RAW POINTER
EXAMPLE IMPLEMENTATION
62
Intend to make the iterators of some classes usable in constant expressions.
Introducing the constexpr iterator requirement that will will easily allow to make constexpr usable
iterators by only adding a few words to the iterator requirements of a container
4Developers 2018 | Beyond C++17
P0858 CONSTEXPR ITERATOR REQUIREMENTS
MOTIVATION
SOLUTION
63
#define F(...) f(0 __VA_OPT__(,) __VA_ARGS__)
F(a, b, c) // replaced by f(0, a, b, c)
F() // replaced by f(0)
4Developers 2018 | Beyond C++17
P0306 COMMA OMISSION AND COMMA DELETION
64
CHANGES AND FIXES
C++20
std::unordered_map<std::string, int> map = /* ... */;
auto it1 = map.find("abc");
auto it2 = map.find("def"sv);
4Developers 2018 | Beyond C++17
P0919 HETEROGENEOUS LOOKUP FOR UNORDERED CONTAINERS
C++17
66
std::unordered_map<std::string, int> map = /* ... */;
auto it1 = map.find("abc");
auto it2 = map.find("def"sv);
struct string_hash {
using transparent_key_equal = std::equal_to<>; // Pred to use
using hash_type = std::hash<std::string_view>; // just a helper local type
size_t operator()(std::string_view txt) const { return hash_type{}(txt); }
size_t operator()(const std::string& txt) const { return hash_type{}(txt); }
size_t operator()(const char* txt) const { return hash_type{}(txt); }
};
std::unordered_map<std::string, int, string_hash> map = /* ... */;
map.find("abc");
map.find("def"sv);
4Developers 2018 | Beyond C++17
P0919 HETEROGENEOUS LOOKUP FOR UNORDERED CONTAINERS
C++17
C++20
66
• The behavior of a program that uses operator== or operator!= on unordered containers is undefined
unless the Hash and Pred function objects respectively have the same behavior for both containers
and the equality comparison function for Key is a refinement of the partition into equivalent-key
groups produced by Pred.
• The UB definition for heterogenous containers should not apply merely because of inequity among
hashers - and in practice, this may be valuable because of hash seeding and randomization
4Developers 2018 | Beyond C++17
P0809 COMPARING UNORDERED CONTAINERS
MOTIVATION
67
• The behavior of a program that uses operator== or operator!= on unordered containers is undefined
unless the Hash and Pred function objects respectively have the same behavior for both containers
and the equality comparison function for Key is a refinement of the partition into equivalent-key
groups produced by Pred.
• The UB definition for heterogenous containers should not apply merely because of inequity among
hashers - and in practice, this may be valuable because of hash seeding and randomization
• The behavior of a program that uses operator== or operator!= on unordered containers is undefined
unless the Pred function object has the same behavior for both containers and the equality
comparison operator for Key...
4Developers 2018 | Beyond C++17
P0809 COMPARING UNORDERED CONTAINERS
MOTIVATION
SOLUTION
67
[]<typename T>(T x) { /* ... */ }
[]<typename T, int N>(T (&a)[N]) { /* ... */ }
4Developers 2018 | Beyond C++17
P0428 FAMILIAR TEMPLATE SYNTAX FOR GENERIC LAMBDAS
68
auto f = [](auto vector) {
using T =
typename decltype(vector)::value_type;
// ...
};
[]<typename T>(T x) { /* ... */ }
[]<typename T, int N>(T (&a)[N]) { /* ... */ }
4Developers 2018 | Beyond C++17
P0428 FAMILIAR TEMPLATE SYNTAX FOR GENERIC LAMBDAS
68
template<typename T>
struct is_std_vector :
std::false_type { };
template<typename T>
struct is_std_vector<std::vector<T>> :
std::true_type { };
auto f = [](auto vector) {
static_assert(
is_std_vector<decltype(vector)>::value);
using T =
typename decltype(vector)::value_type;
// ...
};
[]<typename T>(T x) { /* ... */ }
[]<typename T, int N>(T (&a)[N]) { /* ... */ }
4Developers 2018 | Beyond C++17
P0428 FAMILIAR TEMPLATE SYNTAX FOR GENERIC LAMBDAS
68
template<typename T>
struct is_std_vector :
std::false_type { };
template<typename T>
struct is_std_vector<std::vector<T>> :
std::true_type { };
auto f = [](auto vector) {
static_assert(
is_std_vector<decltype(vector)>::value);
using T =
typename decltype(vector)::value_type;
// ...
};
[]<typename T>(T x) { /* ... */ }
[]<typename T, int N>(T (&a)[N]) { /* ... */ }
auto f = []<typename T>(std::vector<T> vector) {
// ...
};
4Developers 2018 | Beyond C++17
P0428 FAMILIAR TEMPLATE SYNTAX FOR GENERIC LAMBDAS
68
struct S {
void f(int i)
{
[&, i]{ }; // OK
[&, this, i]{ }; // OK: equivalent to [&, i]
[=, *this]{ }; // OK
[=, this]{ }; // OK: equivalent to [=]
[this, *this]{ }; // Error: this appears twice
}
};
4Developers 2018 | Beyond C++17
P0409 ALLOW LAMBDA CAPTURE [=, THIS]
69
auto greater = [](auto x, auto y) { return x > y; };
// No need to care whether 'greater' is a lambda or a function object
std::map<std::string, int, decltype(greater)> map1;
4Developers 2018 | Beyond C++17
P0624 DEFAULT CONSTRUCTIBLE AND ASSIGNABLE STATELESS
LAMBDAS
LIBRARY.H
USER.CPP
70
auto greater = [](auto x, auto y) { return x > y; };
// No need to care whether 'greater' is a lambda or a function object
std::map<std::string, int, decltype(greater)> map1;
std::map<std::string, int, decltype(greater)> map2{/* ... */};
map1 = map2;
4Developers 2018 | Beyond C++17
P0624 DEFAULT CONSTRUCTIBLE AND ASSIGNABLE STATELESS
LAMBDAS
LIBRARY.H
USER.CPP
70
In C++17 template parameter packs can only be captured in lambda by copy, by reference, or by...
std::tuple. There is no possibility to do a simple move.
4Developers 2018 | Beyond C++17
P0780 ALLOW PACK EXPANSION IN LAMBDA INIT-CAPTURE
MOTIVATION
71
template <class... Args>
auto delay_invoke_foo(Args... args)
{
return [args...]() -> decltype(auto) {
return foo(args...);
};
}
In C++17 template parameter packs can only be captured in lambda by copy, by reference, or by...
std::tuple. There is no possibility to do a simple move.
4Developers 2018 | Beyond C++17
P0780 ALLOW PACK EXPANSION IN LAMBDA INIT-CAPTURE
MOTIVATION
BY COPY
71
template <class... Args>
auto delay_invoke_foo(Args... args)
{
return [args...]() -> decltype(auto) {
return foo(args...);
};
}
template <class... Args>
auto delay_invoke_foo(Args... args)
{
return [tup=std::make_tuple(std::move(args)...)]()
-> decltype(auto) {
return std::apply([](auto const&... args)
-> decltype(auto) {
return foo(args...);
}, tup);
};
}
In C++17 template parameter packs can only be captured in lambda by copy, by reference, or by...
std::tuple. There is no possibility to do a simple move.
4Developers 2018 | Beyond C++17
P0780 ALLOW PACK EXPANSION IN LAMBDA INIT-CAPTURE
MOTIVATION
BY COPY BY MOVE
71
Remove the restriction on pack expansions in init-capture, which requires defining a new form of
parameter pack in the language.
4Developers 2018 | Beyond C++17
P0780 ALLOW PACK EXPANSION IN LAMBDA INIT-CAPTURE
SOLUTION
72
template <class... Args>
auto delay_invoke_foo(Args... args)
{
return [tup=std::make_tuple(std::move(args)...)]()
-> decltype(auto) {
return std::apply([](auto const&... args)
-> decltype(auto) {
return foo(args...);
}, tup);
};
}
template <class... Args>
auto delay_invoke_foo(Args... args)
{
return [args=std::move(args)...]() -> decltype(auto) {
return foo(args...);
};
}
Remove the restriction on pack expansions in init-capture, which requires defining a new form of
parameter pack in the language.
4Developers 2018 | Beyond C++17
P0780 ALLOW PACK EXPANSION IN LAMBDA INIT-CAPTURE
SOLUTION
C++17 C++20
72
// OK
constexpr std::complex<double> c1{1.0, 0.0};
constexpr std::complex<double> c2{};
// Failure: arithmetic operations on complex are not constexpr
constexpr auto c3 = -c1 + c2 / 100.0;
4Developers 2018 | Beyond C++17
P0415 constexpr FOR std::complex
MOTIVATION
73
constexpr std::array<char, 6> a { 'H', 'e', 'l', 'l', 'o' }; // OK
constexpr auto it = std::find(a.rbegin(), a.rend(), 'H'); // ERROR: std::find is not constexpr
4Developers 2018 | Beyond C++17
P0202 ADD constexpr MODIFIERS TO FUNCTIONS IN
<algorithm> AND <utility> HEADERS
MOTIVATION
74
constexpr std::array<char, 6> a { 'H', 'e', 'l', 'l', 'o' }; // OK
constexpr auto it = std::find(a.rbegin(), a.rend(), 'H'); // ERROR: std::find is not constexpr
• Add constexpr to all algorithms that
– do not use std::swap
– do not allocate memory (std::stable_partition, std::inplace_merge, and std::stable_sort)
– do not rely upon std::uniform_int_distribution (std::shuffle and std::sample)
4Developers 2018 | Beyond C++17
P0202 ADD constexpr MODIFIERS TO FUNCTIONS IN
<algorithm> AND <utility> HEADERS
MOTIVATION
74
std::vector<std::string> v(10000,"hello"s);
std::string s{"start"};
//s.reserve(s.size() + v.size() * v[0].size()); //useless
std::accumulate(begin(v), end(v), s);
4Developers 2018 | Beyond C++17
P0616 DE-PESSIMIZE LEGACY <numeric> ALGORITHMS WITH
std::move
MOTIVATION
75
std::vector<std::string> v(10000,"hello"s);
std::string s{"start"};
//s.reserve(s.size() + v.size() * v[0].size()); //useless
std::accumulate(begin(v), end(v), s);
• std::accumulate() and std::partial_sum()
acc = std::move(acc) + *i;
• std::inner_product()
acc = std::move(acc) + (*i1) * (*i2);
• std::adjacent_difference()
4Developers 2018 | Beyond C++17
P0616 DE-PESSIMIZE LEGACY <numeric> ALGORITHMS WITH
std::move
MOTIVATION
75
• basic_string::reserve optionally shrinks to fit
• Performance trap - can add unexpected and costly dynamic reallocations
• Portability barrier - feature optionality may cause di erent behavior when run against di erent library
implementations
• Complicates generic code - generic code which accepts vector or basic_string as a template
argument must add code to avoid calling reserve(n) when n is less than capacity
• Duplicates functionality - basic_string::shrink_to_fit
• Inconsistent with vector::reserve which does not shrink-to-fit
4Developers 2018 | Beyond C++17
P0966 string::reserve SHOULD NOT SHRINK
MOTIVATION
76
• basic_string::reserve optionally shrinks to fit
• Performance trap - can add unexpected and costly dynamic reallocations
• Portability barrier - feature optionality may cause di erent behavior when run against di erent library
implementations
• Complicates generic code - generic code which accepts vector or basic_string as a template
argument must add code to avoid calling reserve(n) when n is less than capacity
• Duplicates functionality - basic_string::shrink_to_fit
• Inconsistent with vector::reserve which does not shrink-to-fit
• Rewording of basic_string::reserve to mirror vector::reserve
4Developers 2018 | Beyond C++17
P0966 string::reserve SHOULD NOT SHRINK
MOTIVATION
SOLUTION
76
• Specializing function templates has proven problematic in practice
template<class T> void g(const T&); // function template
template<> void g(const int&); // explicit specialization
void g(double); // function
4Developers 2018 | Beyond C++17
P0551 THOU SHALT NOT SPECIALIZE STD FUNCTION TEMPLATES!
MOTIVATION
77
• Specializing function templates has proven problematic in practice
template<class T> void g(const T&); // function template
template<> void g(const int&); // explicit specialization
void g(double); // function
The overload set described above would consist of at most only two candidates
• The function g(double)
• g<T>(const T&), a compiler-synthesized function template specialization of the primary template,
with the type T deduced from the type of the call’s argument
4Developers 2018 | Beyond C++17
P0551 THOU SHALT NOT SPECIALIZE STD FUNCTION TEMPLATES!
MOTIVATION
77
Change wording to
• Allow specialization of class templates in namespace std provided that the added declaration
depends on at least one user-defined type
• Disallow specializations of function templates in namespace std
4Developers 2018 | Beyond C++17
P0551 THOU SHALT NOT SPECIALIZE STD FUNCTION TEMPLATES!
SOLUTION
78
In a template declaration or a definition, a dependent name that is not a member of the current
instantiation is not considered to be a type unless the disambiguation keyword typename is used or
unless it was already established as a type name.
4Developers 2018 | Beyond C++17
P0634 DOWN WITH TYPENAME!
MOTIVATION
79
In a template declaration or a definition, a dependent name that is not a member of the current
instantiation is not considered to be a type unless the disambiguation keyword typename is used or
unless it was already established as a type name.
template<class T, class Allocator = std::allocator<T>>
class my_vector {
public:
using pointer = typename std::allocator_traits<Allocator>::pointer;
// ...
};
4Developers 2018 | Beyond C++17
P0634 DOWN WITH TYPENAME!
MOTIVATION
79
In a template declaration or a definition, a dependent name that is not a member of the current
instantiation is not considered to be a type unless the disambiguation keyword typename is used or
unless it was already established as a type name.
template<class T, class Allocator = std::allocator<T>>
class my_vector {
public:
using pointer = typename std::allocator_traits<Allocator>::pointer;
// ...
};
but...
template<class T>
struct D : T::B { // no typename required here
};
4Developers 2018 | Beyond C++17
P0634 DOWN WITH TYPENAME!
MOTIVATION
79
Makes typename optional in a number of commonplace contexts that are known to only permit type
names
4Developers 2018 | Beyond C++17
P0634 DOWN WITH TYPENAME!
SOLUTION
80
template<class T>
typename T::R f(typename T::P);
template<class T>
struct S {
using Ptr = typename PtrTraits<T>::Ptr;
typename T::R f(typename T::P p) {
return static_cast<typename T::R>(p);
}
auto g() -> typename S<T*>::Ptr;
};
Makes typename optional in a number of commonplace contexts that are known to only permit type
names
4Developers 2018 | Beyond C++17
P0634 DOWN WITH TYPENAME!
SOLUTION
C++17
80
template<class T>
typename T::R f(typename T::P);
template<class T>
struct S {
using Ptr = typename PtrTraits<T>::Ptr;
typename T::R f(typename T::P p) {
return static_cast<typename T::R>(p);
}
auto g() -> typename S<T*>::Ptr;
};
template<class T>
T::R f(T::P);
template<class T>
struct S {
using Ptr = PtrTraits<T>::Ptr;
T::R f(T::P p) {
return static_cast<T::R>(p);
}
auto g() -> S<T*>::Ptr;
};
Makes typename optional in a number of commonplace contexts that are known to only permit type
names
4Developers 2018 | Beyond C++17
P0634 DOWN WITH TYPENAME!
SOLUTION
C++17 C++20
80
std::shared_ptr<double[]> p = std::make_shared<double[]>(1024);
4Developers 2018 | Beyond C++17
P0674 EXTENDING MAKE_SHARED TO SUPPORT ARRAYS
81
tuple t{tuple{1, 2}}; // Deduces tuple<int, int>
vector v1{vector{1, 2}}; // C++17 - Deduces vector<vector<int>>
vector v2{vector{1, 2}}; // C++20 - Deduces vector<int>
4Developers 2018 | Beyond C++17
P0702 LANGUAGE SUPPORT FOR CONSTRUCTOR TEMPLATE
ARGUMENT DEDUCTION
82
mutex m;
scoped_lock l{adopt_lock, m}; // make this work
variant<int, double> v1{3};
variant v2 = v1; // make this work
4Developers 2018 | Beyond C++17
P0739 IMPROVE CLASS TEMPLATE ARGUMENT DEDUCTION IN THE
STANDARD LIBRARY
83
• Provides the ability to specialize templates on their private and protected nested class-types
template<class T>
struct trait;
class X {
class impl;
};
template<>
struct trait<X::impl>;
4Developers 2018 | Beyond C++17
P0692 ACCESS CHECKING ON SPECIALIZATIONS
84
struct X : std::stringstream { /*...*/ };
std::istream_iterator<char> begin(X& x)
{ return std::istream_iterator<char>(x); }
std::istream_iterator<char> end(X& x)
{ return std::istream_iterator<char>(); }
int main() {
X x;
for (auto&& i : x) { // works in C++20
// ...
}
}
Range-based for loop can handle ranges that
have
• both member rng.begin()/rng.end()
functions
• both non-member begin(rng)/end(rng)
functions
Problem arises when a class has only one of
needed member functions (i.e. end() in
std::ios_base).
4Developers 2018 | Beyond C++17
P0962 RELAXING THE RANGE-FOR LOOP CUSTOMIZATION POINT
FINDING RULES
MOTIVATION
85
struct X : std::stringstream { /*...*/ };
std::istream_iterator<char> begin(X& x)
{ return std::istream_iterator<char>(x); }
std::istream_iterator<char> end(X& x)
{ return std::istream_iterator<char>(); }
int main() {
X x;
for (auto&& i : x) { // works in C++20
// ...
}
}
Range-based for loop can handle ranges that
have
• both member rng.begin()/rng.end()
functions
• both non-member begin(rng)/end(rng)
functions
Problem arises when a class has only one of
needed member functions (i.e. end() in
std::ios_base).
Use non-member functions pair if only one member functions is found.
4Developers 2018 | Beyond C++17
P0962 RELAXING THE RANGE-FOR LOOP CUSTOMIZATION POINT
FINDING RULES
MOTIVATION
SOLUTION
85
In C++17 we can use structured bindings to bind to class members as long as they are public.
4Developers 2018 | Beyond C++17
P0969 ALLOW STRUCTURES BINDINGS TO ACCESSIBLE MEMBERS
MOTIVATION
86
class Foo {
int a_, b_;
void bar(const Foo& other)
{
auto [x, y] = other; // now OK
// ...
}
};
In C++17 we can use structured bindings to bind to class members as long as they are public.
4Developers 2018 | Beyond C++17
P0969 ALLOW STRUCTURES BINDINGS TO ACCESSIBLE MEMBERS
MOTIVATION
86
class Foo {
int a_, b_;
void bar(const Foo& other)
{
auto [x, y] = other; // now OK
// ...
}
};
class X {
int i_;
int j_;
public:
friend void f();
};
void f()
{
X x;
auto [myi, myj] = x; // now OK
}
In C++17 we can use structured bindings to bind to class members as long as they are public.
4Developers 2018 | Beyond C++17
P0969 ALLOW STRUCTURES BINDINGS TO ACCESSIBLE MEMBERS
MOTIVATION
86
• POD is a widely-used term
• The fundamental problem with POD is that it means a large di erent things to di erent people
4Developers 2018 | Beyond C++17
P0767 POD AND std::is_pod<> IS DEPRECATED
87
• POD is a widely-used term
• The fundamental problem with POD is that it means a large di erent things to di erent people
– Can I memcpy this thing?
• std::is_pod<T> or std::is_trivially_copyable<T> are both wrong answers in some cases
• the correct answer is is_trivially_copy_constructible_v<T> &&
is_trivially_copy_assignable_v<T>
4Developers 2018 | Beyond C++17
P0767 POD AND std::is_pod<> IS DEPRECATED
87
• POD is a widely-used term
• The fundamental problem with POD is that it means a large di erent things to di erent people
– Can I memcpy this thing?
• std::is_pod<T> or std::is_trivially_copyable<T> are both wrong answers in some cases
• the correct answer is is_trivially_copy_constructible_v<T> &&
is_trivially_copy_assignable_v<T>
– POD is a struct that can be parsed by both C and C++ compilers?
class Point {
public:
int x;
int y;
};
static_assert(std::is_pod_v<Point>);
4Developers 2018 | Beyond C++17
P0767 POD AND std::is_pod<> IS DEPRECATED
87
namespace std {
typedef enum memory_order {
memory_order_relaxed, memory_order_consume, memory_order_acquire,
memory_order_release, memory_order_acq_rel, memory_order_seq_cst
} memory_order;
}
namespace std {
enum class memory_order : unspecified {
relaxed, consume, acquire, release, acq_rel, seq_cst
};
inline constexpr memory_order memory_order_relaxed = memory_order::relaxed;
inline constexpr memory_order memory_order_consume = memory_order::consume;
inline constexpr memory_order memory_order_acquire = memory_order::acquire;
inline constexpr memory_order memory_order_release = memory_order::release;
inline constexpr memory_order memory_order_acq_rel = memory_order::acq_rel;
inline constexpr memory_order memory_order_seq_cst = memory_order::seq_cst;
}
4Developers 2018 | Beyond C++17
P0439 MAKE std::memory_order A SCOPED ENUMERATION
C++17
C++20
88
• <ciso646> header despite being specified to have no e ect is used to determine the library version
4Developers 2018 | Beyond C++17
P0754 <version>
MOTIVATION
89
• <ciso646> header despite being specified to have no e ect is used to determine the library version
• Standardize a dedicated <version> C++ header for this purpose
• Contains only the implementation-defined boilerplate comments which specify various properties of
the library such as version and copyright notice
• Provides a place to put other implementation-defined library meta-information which an environment
or human reader might find useful
• Ideal place to define the feature test macros
4Developers 2018 | Beyond C++17
P0754 <version>
MOTIVATION
SOLUTION
89
WORK IN PROGRESS
• The first part of compile-time reflection is in wording review
void func(int);
using func_overload_m = reflexpr(func);
using func_m = get_element_t<0, get_overloads_t<func_overload_m>>;
using param0_m = get_element_t<0, get_parameters_t<func_m>>;
std::cout << get_name_v<get_type_t<param0_m>> << 'n'; // prints "int"
• Possible next steps being discussed (P0633)
– code synthesis (raw string injection, token sequence injection, programmatic API, metaclasses)
– control flow (classic template metaprogramming, heterogenous value metaprogramming,
constexpr programming)
4Developers 2018 | Beyond C++17
REFLECTION
93
interface IShape {
int area() const;
void scale_by(double factor);
// ... etc.
};
4Developers 2018 | Beyond C++17
REFLECTION - METACLASSES
INPUT
94
interface IShape {
int area() const;
void scale_by(double factor);
// ... etc.
};
class IShape {
public:
virtual int area() const = 0;
virtual void scale_by(double factor) = 0;
// ... etc.
virtual ~IShape() noexcept { };
// be careful not to write
// nonpublic/nonvirtual function
// or copy/move function or
// data member
};
4Developers 2018 | Beyond C++17
REFLECTION - METACLASSES
INPUT OUTPUT
94
interface IShape {
int area() const;
void scale_by(double factor);
// ... etc.
};
class IShape {
public:
virtual int area() const = 0;
virtual void scale_by(double factor) = 0;
// ... etc.
virtual ~IShape() noexcept { };
// be careful not to write
// nonpublic/nonvirtual function
// or copy/move function or
// data member
};
• Code transformation based on metaclass
definition
– defaults
– constraints, user friendly error reporting
– generated functions
• Remove the need for Qt moc, C++/CX, C++/WinRT IDL and others
4Developers 2018 | Beyond C++17
REFLECTION - METACLASSES
INPUT OUTPUT
94
[[contract-attribute modifier identifier: expression]]
4Developers 2018 | Beyond C++17
P0542 CONTRACTS
95
[[contract-attribute modifier identifier: expression]]
• contract-attribute is one of the
– expects - function precondition
– ensures - function postcondition
– assert - statement verification
4Developers 2018 | Beyond C++17
P0542 CONTRACTS
95
[[contract-attribute modifier identifier: expression]]
• contract-attribute is one of the
– expects - function precondition
– ensures - function postcondition
– assert - statement verification
• Attribute modifier defines assertion level
– default - the cost of run-time checking is assumed to be small
– audit - the cost of run-time checking is assumed to be large
– axiom - formal comments and are not evaluated at run-time
– always - cannot be disabled
4Developers 2018 | Beyond C++17
P0542 CONTRACTS
95
[[contract-attribute modifier identifier: expression]]
• contract-attribute is one of the
– expects - function precondition
– ensures - function postcondition
– assert - statement verification
• Attribute modifier defines assertion level
– default - the cost of run-time checking is assumed to be small
– audit - the cost of run-time checking is assumed to be large
– axiom - formal comments and are not evaluated at run-time
– always - cannot be disabled
• identifier used only for function return value in postconditions
4Developers 2018 | Beyond C++17
P0542 CONTRACTS
95
• If a contract violation is detected, a violation handler will be invoked
void(const std::contract_violation &); // violation handler signature
namespace std {
class contract_violation {
public:
int line_number() const noexcept;
const char* file_name() const noexcept;
const char* function_name() const noexcept;
const char* comment() const noexcept;
const char* contract_violation() const noexcept;
};
}
• Establishing violation handler and setting its argument is implementation defined
• Violation continuation mode can be o or on
4Developers 2018 | Beyond C++17
P0542 CONTRACTS
96
int f(int x)
[[expects audit: x>0]]
[[ensures axiom res: res>1]];
void g()
{
int x = f(5);
int y = f(12);
[[assert: x+y>0]]
//...
}
4Developers 2018 | Beyond C++17
P0542 CONTRACTS
97
int f(int x)
[[expects audit: x>0]]
[[ensures axiom res: res>1]];
void g()
{
int x = f(5);
int y = f(12);
[[assert: x+y>0]]
//...
}
bool positive(int* p) [[expects: p!=nullptr]]
{
return *p > 0;
}
bool g(int* p) [[expects: positive(p)]];
void test()
{
g(nullptr); // Contract violation
}
4Developers 2018 | Beyond C++17
P0542 CONTRACTS
97
Redeclaration of a function either has the contract or completely omits it
int f(int x)
[[expects: x>0]]
[[ensures r: r>0]];
4Developers 2018 | Beyond C++17
P0542 CONTRACTS
98
Redeclaration of a function either has the contract or completely omits it
int f(int x)
[[expects: x>0]]
[[ensures r: r>0]];
int f(int x); // OK: no contract
int f(int x)
[[expects: x>=0]]; // Error: missing ensures and different expects condition
int f(int y)
[[expects: y>0]]
[[ensures res: res>0]]; // OK: same contract even though names differ
4Developers 2018 | Beyond C++17
P0542 CONTRACTS
98
using CT = utf8_encoding::character_type;
auto tv = make_text_view<utf8_encoding>(u8"Ju00F8erg");
auto it = tv.begin();
assert(*it++ == CT{0x004A}); // 'J'
assert(*it++ == CT{0x00F8}); // 'ø' - encoded as UTF-8 using two code units (xC3xB8)
assert(*it++ == CT{0x0065}); // 'e'
4Developers 2018 | Beyond C++17
P0244 TEXT_VIEW: CHARACTER ENCODING AND CODE POINT
ENUMERATION LIBRARY
99
using CT = utf8_encoding::character_type;
auto tv = make_text_view<utf8_encoding>(u8"Ju00F8erg");
auto it = tv.begin();
assert(*it++ == CT{0x004A}); // 'J'
assert(*it++ == CT{0x00F8}); // 'ø' - encoded as UTF-8 using two code units (xC3xB8)
assert(*it++ == CT{0x0065}); // 'e'
it = std::find(tv.begin(), tv.end(), CT{0x00F8});
assert(it != tv.end());
4Developers 2018 | Beyond C++17
P0244 TEXT_VIEW: CHARACTER ENCODING AND CODE POINT
ENUMERATION LIBRARY
99
using CT = utf8_encoding::character_type;
auto tv = make_text_view<utf8_encoding>(u8"Ju00F8erg");
auto it = tv.begin();
assert(*it++ == CT{0x004A}); // 'J'
assert(*it++ == CT{0x00F8}); // 'ø' - encoded as UTF-8 using two code units (xC3xB8)
assert(*it++ == CT{0x0065}); // 'e'
it = std::find(tv.begin(), tv.end(), CT{0x00F8});
assert(it != tv.end());
auto base_it = it.base_range().begin();
assert(*base_it++ == 'xC3');
assert(*base_it++ == 'xB8');
assert(base_it == it.base_range().end());
4Developers 2018 | Beyond C++17
P0244 TEXT_VIEW: CHARACTER ENCODING AND CODE POINT
ENUMERATION LIBRARY
99
string message = fmt::format("The answer is {}.", 42);
fmt::format("{:*^30}", "centered"); // ***********centered***********
4Developers 2018 | Beyond C++17
P0645 TEXT FORMATTING
100
• async(...)
• for_each(...)
• define_task_block(...)
• invoke(...)
• your_favorite_control_structure(...)
• OS threads
• Thread pool schedulers
• OpenMP runtime
• SIMD vector units
• GPU runtime
• Fibers
4Developers 2018 | Beyond C++17
EXECUTORS: PURPOSE
DIVERSE CONTROL STRUCTURES DIVERSE EXECUTION RESOURCES
Executors as an answer to mutliplicative explosion.
101
for_each(par.on(ex), begin, end, function);
4Developers 2018 | Beyond C++17
EXECUTORS: PURPOSE
CONTROL WHERE/HOW EXECUTION SHOULD OCCUR
102
for_each(par.on(ex), begin, end, function);
async(executor, function);
4Developers 2018 | Beyond C++17
EXECUTORS: PURPOSE
CONTROL WHERE/HOW EXECUTION SHOULD OCCUR
CONTROL RELATIONSHIP WITH CALLING THREAD
102
for_each(par.on(ex), begin, end, function);
async(executor, function);
for_each(P.on(executor), ...);
async(executor, ...);
invoke(executor, ...);
my_asynchronous_op(executor, ...);
4Developers 2018 | Beyond C++17
EXECUTORS: PURPOSE
CONTROL WHERE/HOW EXECUTION SHOULD OCCUR
CONTROL RELATIONSHIP WITH CALLING THREAD
UNIFORM INTERFACE FOR EXECUTION SEMANTICS ACROSS CONTROL STRUCTURES
102
Executors are handles to underlying execution contexts
4Developers 2018 | Beyond C++17
EXECUTORS: DESIGN
103
Executors are handles to underlying execution contexts
Execution contexts manage lifetime of units of work called
execution agents (e.g. static_thread_pool)
4Developers 2018 | Beyond C++17
EXECUTORS: DESIGN
103
Executors are handles to underlying execution contexts
Execution contexts manage lifetime of units of work called
execution agents (e.g. static_thread_pool)
Executors, in some cases, may be self-contexts (e.g. inline_executor)
4Developers 2018 | Beyond C++17
EXECUTORS: DESIGN
103
ONE-WAY TWO-WAY THEN
Single execute() twoway_execute() then_execute()
Bulk bulk_execute() bulk_twoway_execute() bulk_then_execute()
4Developers 2018 | Beyond C++17
EXECUTORS: DESIGN
104
ONE-WAY TWO-WAY THEN
Single execute() twoway_execute() then_execute()
Bulk bulk_execute() bulk_twoway_execute() bulk_then_execute()
auto my_task = []{...};
ex.execute(my_task);
• Creates a single execution agent
• Fire-And-Forget
4Developers 2018 | Beyond C++17
EXECUTORS: DESIGN
EXECUTE()
105
ONE-WAY TWO-WAY THEN
Single execute() twoway_execute() then_execute()
Bulk bulk_execute() bulk_twoway_execute() bulk_then_execute()
auto my_task = []{...};
auto future = ex.twoway_execute(my_task);
• Creates a single execution agent
• Returns a future
4Developers 2018 | Beyond C++17
EXECUTORS: DESIGN
TWOWAY_EXECUTE()
106
ONE-WAY TWO-WAY THEN
Single execute() twoway_execute() then_execute()
Bulk bulk_execute() bulk_twoway_execute() bulk_then_execute()
future<int> predecessor = ...;
auto my_task = [](int &pred){...};
auto future = ex.then_execute(my_task, predecessor);
• Creates a single execution agent
• Depends on a predecessor future
• Returns a future
4Developers 2018 | Beyond C++17
EXECUTORS: DESIGN
THEN_EXECUTE()
107
ONE-WAY TWO-WAY THEN
Single execute() twoway_execute() then_execute()
Bulk bulk_execute() bulk_twoway_execute() bulk_then_execute()
auto my_task = [](size_t idx, int& shared){...};
auto shared_factory = []{ return 42; };
ex.bulk_execute(my_task, n, shared_factory);
• Creates multiple execution agents
• Fire-And-Forget
4Developers 2018 | Beyond C++17
EXECUTORS: DESIGN
BULK_EXECUTE()
108
ONE-WAY TWO-WAY THEN
Single execute() twoway_execute() then_execute()
Bulk bulk_execute() bulk_twoway_execute() bulk_then_execute()
auto my_task = [](size_t idx, int& result, int& shared){...};
auto result_factory = []{ return 7; }
auto shared_factory = []{ return 42; };
auto future = ex.bulk_twoway_execute(my_task, n, result_factory, shared_factory);
• Creates multiple execution agents
• Returns a future
4Developers 2018 | Beyond C++17
EXECUTORS: DESIGN
BULK_TWOWAY_EXECUTE()
109
ONE-WAY TWO-WAY THEN
Single execute() twoway_execute() then_execute()
Bulk bulk_execute() bulk_twoway_execute() bulk_then_execute()
future<int> predecessor = ...;
auto my_task = [](size_t idx, int& pred, int& result, int& shared){...};
auto result_factory = []{ return 7; }
auto shared_factory = []{ return 42; };
auto future = ex.bulk_then_execute(my_task, n, predecessor, result_factory, shared_factory);
• Creates multiple execution agents
• Depends on a predecessor future
• Returns a future
4Developers 2018 | Beyond C++17
EXECUTORS: DESIGN
BULK_THEN_EXECUTE()
110
Executor properties are objects associated with executors that
imply a behavior (e.g. never_blocking, bulk, continuation)
• Allow generic code to reason about executor behavior in a uniform way
• Enable executor adaptations
4Developers 2018 | Beyond C++17
EXECUTORS: PROPERTY-BASED DESIGN
111
Executor properties are manipulated via customization points to
express requirements and preferences
• require(ex, props...) - a binding requirement for particular properties
• prefer(ex, props...) - a non-binding requirement for particular properties
• Return another executor
4Developers 2018 | Beyond C++17
EXECUTORS: CUSTOMIZATION POINTS
112
auto non_blocking_ex = execution::require(ex, never_blocking);
non_blocking_ex.execute(task);
• May fail if ex only supports always_blocking
• May fail if ex.require(user_property_t) = delete
4Developers 2018 | Beyond C++17
EXECUTORS: execution::require()
113
auto best_ex = execution::prefer(ex, continuation);
best_ex.execute(task);
• Always compiles
• prefer() simply calls require() when possible
4Developers 2018 | Beyond C++17
EXECUTORS: execution::prefer()
114
int p = execution::query(ex, priority);
• Introspects executor properties
• Can inspect the result of execution::prefer(ex, props...)
4Developers 2018 | Beyond C++17
EXECUTORS: execution::query()
115
struct inline_executor {
template<class F>
void execute(F f) const {
try {
f();
} catch(...) {
std::terminate();
}
}
const inline_executor& context() const noexcept { return *this; }
bool operator==(const inline_executor&) const { return true; }
bool operator!=(const inline_executor&) const { return false; }
};
• Executes work immediately, “inline”
4Developers 2018 | Beyond C++17
EXECUTORS: SIMPLEST COMPLETE EXECUTOR
116
struct static_thread_pool_executor {
// execution functions
template<class F>
void execute(F&& f) const;
// ...
static_thread_pool& context() const noexcept;
// require overloads
static_thread_pool_executor require(oneway_t) const;
// ...
// adapting require overloads
adapted-executor require(never_blocking_t) const;
// ...
// equality
bool operator==(const static_thread_pool&);
bool operator!=(const static_thread_pool&);
};
4Developers 2018 | Beyond C++17
EXECUTORS: static_thread_pool EXECUTOR
117
namespace custom {
// a custom property
struct logging { bool on; };
// a fancy logging executor
template<class Executor>
class logging_executor { ... };
// adapts executors without native logging property
template<class Executor>
std::enable_if_t<!has_require_members_v<Executor, logging>, logging_executor<Executor>>
require(Executor ex, logging l)
{
return logging_executor<Executor>(ex, l);
}
} // custom
4Developers 2018 | Beyond C++17
EXECUTORS: ADAPTING AN EXECUTOR
118

More Related Content

What's hot

Rainer Grimm, “Functional Programming in C++11”
Rainer Grimm, “Functional Programming in C++11”Rainer Grimm, “Functional Programming in C++11”
Rainer Grimm, “Functional Programming in C++11”Platonov Sergey
 
Yurii Shevtsov "V8 + libuv = Node.js. Under the hood"
Yurii Shevtsov "V8 + libuv = Node.js. Under the hood"Yurii Shevtsov "V8 + libuv = Node.js. Under the hood"
Yurii Shevtsov "V8 + libuv = Node.js. Under the hood"OdessaJS Conf
 
Timur Shemsedinov "Пишу на колбеках, а что... (Асинхронное программирование)"
Timur Shemsedinov "Пишу на колбеках, а что... (Асинхронное программирование)"Timur Shemsedinov "Пишу на колбеках, а что... (Асинхронное программирование)"
Timur Shemsedinov "Пишу на колбеках, а что... (Асинхронное программирование)"OdessaJS Conf
 
Operating System Lab Manual
Operating System Lab ManualOperating System Lab Manual
Operating System Lab ManualBilal Mirza
 
81818088 isc-class-xii-computer-science-project-java-programs
81818088 isc-class-xii-computer-science-project-java-programs81818088 isc-class-xii-computer-science-project-java-programs
81818088 isc-class-xii-computer-science-project-java-programsAbhishek Jena
 
とある断片の超動的言語
とある断片の超動的言語とある断片の超動的言語
とある断片の超動的言語Kiyotaka Oku
 
Bartosz Milewski, “Re-discovering Monads in C++”
Bartosz Milewski, “Re-discovering Monads in C++”Bartosz Milewski, “Re-discovering Monads in C++”
Bartosz Milewski, “Re-discovering Monads in C++”Platonov Sergey
 
algorithm design file
algorithm design filealgorithm design file
algorithm design filesuraj kumar
 
Jsr310 - Java 8 Date and Time API
Jsr310 - Java 8 Date and Time APIJsr310 - Java 8 Date and Time API
Jsr310 - Java 8 Date and Time APIAdy Liu
 
Cn os-lp lab manual k.roshan
Cn os-lp lab manual k.roshanCn os-lp lab manual k.roshan
Cn os-lp lab manual k.roshanriturajj
 
20140531 serebryany lecture02_find_scary_cpp_bugs
20140531 serebryany lecture02_find_scary_cpp_bugs20140531 serebryany lecture02_find_scary_cpp_bugs
20140531 serebryany lecture02_find_scary_cpp_bugsComputer Science Club
 
20140531 serebryany lecture01_fantastic_cpp_bugs
20140531 serebryany lecture01_fantastic_cpp_bugs20140531 serebryany lecture01_fantastic_cpp_bugs
20140531 serebryany lecture01_fantastic_cpp_bugsComputer Science Club
 
C++ Certified Associate Programmer CPA
C++ Certified Associate Programmer CPAC++ Certified Associate Programmer CPA
C++ Certified Associate Programmer CPAIsabella789
 

What's hot (19)

Rainer Grimm, “Functional Programming in C++11”
Rainer Grimm, “Functional Programming in C++11”Rainer Grimm, “Functional Programming in C++11”
Rainer Grimm, “Functional Programming in C++11”
 
Yurii Shevtsov "V8 + libuv = Node.js. Under the hood"
Yurii Shevtsov "V8 + libuv = Node.js. Under the hood"Yurii Shevtsov "V8 + libuv = Node.js. Under the hood"
Yurii Shevtsov "V8 + libuv = Node.js. Under the hood"
 
Timur Shemsedinov "Пишу на колбеках, а что... (Асинхронное программирование)"
Timur Shemsedinov "Пишу на колбеках, а что... (Асинхронное программирование)"Timur Shemsedinov "Пишу на колбеках, а что... (Асинхронное программирование)"
Timur Shemsedinov "Пишу на колбеках, а что... (Асинхронное программирование)"
 
Permute
PermutePermute
Permute
 
Operating System Lab Manual
Operating System Lab ManualOperating System Lab Manual
Operating System Lab Manual
 
Permute
PermutePermute
Permute
 
81818088 isc-class-xii-computer-science-project-java-programs
81818088 isc-class-xii-computer-science-project-java-programs81818088 isc-class-xii-computer-science-project-java-programs
81818088 isc-class-xii-computer-science-project-java-programs
 
とある断片の超動的言語
とある断片の超動的言語とある断片の超動的言語
とある断片の超動的言語
 
Os lab 1st mid
Os lab 1st midOs lab 1st mid
Os lab 1st mid
 
Bartosz Milewski, “Re-discovering Monads in C++”
Bartosz Milewski, “Re-discovering Monads in C++”Bartosz Milewski, “Re-discovering Monads in C++”
Bartosz Milewski, “Re-discovering Monads in C++”
 
C Programming lab
C Programming labC Programming lab
C Programming lab
 
algorithm design file
algorithm design filealgorithm design file
algorithm design file
 
Jsr310 - Java 8 Date and Time API
Jsr310 - Java 8 Date and Time APIJsr310 - Java 8 Date and Time API
Jsr310 - Java 8 Date and Time API
 
Lab 1 izz
Lab 1 izzLab 1 izz
Lab 1 izz
 
Cn os-lp lab manual k.roshan
Cn os-lp lab manual k.roshanCn os-lp lab manual k.roshan
Cn os-lp lab manual k.roshan
 
C++ file
C++ fileC++ file
C++ file
 
20140531 serebryany lecture02_find_scary_cpp_bugs
20140531 serebryany lecture02_find_scary_cpp_bugs20140531 serebryany lecture02_find_scary_cpp_bugs
20140531 serebryany lecture02_find_scary_cpp_bugs
 
20140531 serebryany lecture01_fantastic_cpp_bugs
20140531 serebryany lecture01_fantastic_cpp_bugs20140531 serebryany lecture01_fantastic_cpp_bugs
20140531 serebryany lecture01_fantastic_cpp_bugs
 
C++ Certified Associate Programmer CPA
C++ Certified Associate Programmer CPAC++ Certified Associate Programmer CPA
C++ Certified Associate Programmer CPA
 

Similar to 4Developers 2018: Beyond c++17 (Mateusz Pusz)

Debugging and Profiling C++ Template Metaprograms
Debugging and Profiling C++ Template MetaprogramsDebugging and Profiling C++ Template Metaprograms
Debugging and Profiling C++ Template MetaprogramsPlatonov Sergey
 
C++ Concepts and Ranges - How to use them?
C++ Concepts and Ranges - How to use them?C++ Concepts and Ranges - How to use them?
C++ Concepts and Ranges - How to use them?Mateusz Pusz
 
C++20 the small things - Timur Doumler
C++20 the small things - Timur DoumlerC++20 the small things - Timur Doumler
C++20 the small things - Timur Doumlercorehard_by
 
Степан Кольцов — Rust — лучше, чем C++
Степан Кольцов — Rust — лучше, чем C++Степан Кольцов — Rust — лучше, чем C++
Степан Кольцов — Rust — лучше, чем C++Yandex
 
friends functionToshu
friends functionToshufriends functionToshu
friends functionToshuSidd Singh
 
rrxv6 Build a Riscv xv6 Kernel in Rust.pdf
rrxv6 Build a Riscv xv6 Kernel in Rust.pdfrrxv6 Build a Riscv xv6 Kernel in Rust.pdf
rrxv6 Build a Riscv xv6 Kernel in Rust.pdfYodalee
 
Advance C++notes
Advance C++notesAdvance C++notes
Advance C++notesRajiv Gupta
 
Analysis of Microsoft Code Contracts
Analysis of Microsoft Code ContractsAnalysis of Microsoft Code Contracts
Analysis of Microsoft Code ContractsPVS-Studio
 
c++ practical Digvajiya collage Rajnandgaon
c++ practical  Digvajiya collage Rajnandgaonc++ practical  Digvajiya collage Rajnandgaon
c++ practical Digvajiya collage Rajnandgaonyash production
 
Modern c++ Memory Management
Modern c++ Memory ManagementModern c++ Memory Management
Modern c++ Memory ManagementAlan Uthoff
 
C++ Code as Seen by a Hypercritical Reviewer
C++ Code as Seen by a Hypercritical ReviewerC++ Code as Seen by a Hypercritical Reviewer
C++ Code as Seen by a Hypercritical ReviewerAndrey Karpov
 
Detection of errors and potential vulnerabilities in C and C++ code using the...
Detection of errors and potential vulnerabilities in C and C++ code using the...Detection of errors and potential vulnerabilities in C and C++ code using the...
Detection of errors and potential vulnerabilities in C and C++ code using the...Andrey Karpov
 
The Great and Mighty C++
The Great and Mighty C++The Great and Mighty C++
The Great and Mighty C++Andrey Karpov
 
A scrupulous code review - 15 bugs in C++ code
A scrupulous code review - 15 bugs in C++ codeA scrupulous code review - 15 bugs in C++ code
A scrupulous code review - 15 bugs in C++ codePVS-Studio LLC
 

Similar to 4Developers 2018: Beyond c++17 (Mateusz Pusz) (20)

Debugging and Profiling C++ Template Metaprograms
Debugging and Profiling C++ Template MetaprogramsDebugging and Profiling C++ Template Metaprograms
Debugging and Profiling C++ Template Metaprograms
 
C++11 & C++14
C++11 & C++14C++11 & C++14
C++11 & C++14
 
C++ Concepts and Ranges - How to use them?
C++ Concepts and Ranges - How to use them?C++ Concepts and Ranges - How to use them?
C++ Concepts and Ranges - How to use them?
 
C++20 the small things - Timur Doumler
C++20 the small things - Timur DoumlerC++20 the small things - Timur Doumler
C++20 the small things - Timur Doumler
 
Степан Кольцов — Rust — лучше, чем C++
Степан Кольцов — Rust — лучше, чем C++Степан Кольцов — Rust — лучше, чем C++
Степан Кольцов — Rust — лучше, чем C++
 
friends functionToshu
friends functionToshufriends functionToshu
friends functionToshu
 
rrxv6 Build a Riscv xv6 Kernel in Rust.pdf
rrxv6 Build a Riscv xv6 Kernel in Rust.pdfrrxv6 Build a Riscv xv6 Kernel in Rust.pdf
rrxv6 Build a Riscv xv6 Kernel in Rust.pdf
 
Advance C++notes
Advance C++notesAdvance C++notes
Advance C++notes
 
Analysis of Microsoft Code Contracts
Analysis of Microsoft Code ContractsAnalysis of Microsoft Code Contracts
Analysis of Microsoft Code Contracts
 
lecture56.ppt
lecture56.pptlecture56.ppt
lecture56.ppt
 
c++ practical Digvajiya collage Rajnandgaon
c++ practical  Digvajiya collage Rajnandgaonc++ practical  Digvajiya collage Rajnandgaon
c++ practical Digvajiya collage Rajnandgaon
 
Opps manual final copy
Opps manual final   copyOpps manual final   copy
Opps manual final copy
 
OOPs manual final copy
OOPs manual final   copyOOPs manual final   copy
OOPs manual final copy
 
Boosting Developer Productivity with Clang
Boosting Developer Productivity with ClangBoosting Developer Productivity with Clang
Boosting Developer Productivity with Clang
 
Modern c++ Memory Management
Modern c++ Memory ManagementModern c++ Memory Management
Modern c++ Memory Management
 
C++17 now
C++17 nowC++17 now
C++17 now
 
C++ Code as Seen by a Hypercritical Reviewer
C++ Code as Seen by a Hypercritical ReviewerC++ Code as Seen by a Hypercritical Reviewer
C++ Code as Seen by a Hypercritical Reviewer
 
Detection of errors and potential vulnerabilities in C and C++ code using the...
Detection of errors and potential vulnerabilities in C and C++ code using the...Detection of errors and potential vulnerabilities in C and C++ code using the...
Detection of errors and potential vulnerabilities in C and C++ code using the...
 
The Great and Mighty C++
The Great and Mighty C++The Great and Mighty C++
The Great and Mighty C++
 
A scrupulous code review - 15 bugs in C++ code
A scrupulous code review - 15 bugs in C++ codeA scrupulous code review - 15 bugs in C++ code
A scrupulous code review - 15 bugs in C++ code
 

Recently uploaded

Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Patryk Bandurski
 
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...shyamraj55
 
New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024BookNet Canada
 
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Alan Dix
 
Pigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions
 
Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Scott Keck-Warren
 
CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):comworks
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubKalema Edgar
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticscarlostorres15106
 
Key Features Of Token Development (1).pptx
Key  Features Of Token  Development (1).pptxKey  Features Of Token  Development (1).pptx
Key Features Of Token Development (1).pptxLBM Solutions
 
My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024The Digital Insurer
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsRizwan Syed
 
Snow Chain-Integrated Tire for a Safe Drive on Winter Roads
Snow Chain-Integrated Tire for a Safe Drive on Winter RoadsSnow Chain-Integrated Tire for a Safe Drive on Winter Roads
Snow Chain-Integrated Tire for a Safe Drive on Winter RoadsHyundai Motor Group
 
Unlocking the Potential of the Cloud for IBM Power Systems
Unlocking the Potential of the Cloud for IBM Power SystemsUnlocking the Potential of the Cloud for IBM Power Systems
Unlocking the Potential of the Cloud for IBM Power SystemsPrecisely
 
Install Stable Diffusion in windows machine
Install Stable Diffusion in windows machineInstall Stable Diffusion in windows machine
Install Stable Diffusion in windows machinePadma Pradeep
 
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersEnhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersThousandEyes
 
Benefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other FrameworksBenefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other FrameworksSoftradix Technologies
 

Recently uploaded (20)

Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
 
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
 
The transition to renewables in India.pdf
The transition to renewables in India.pdfThe transition to renewables in India.pdf
The transition to renewables in India.pdf
 
New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
 
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
 
Pigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food Manufacturing
 
Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024
 
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptxE-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
 
CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding Club
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
 
Key Features Of Token Development (1).pptx
Key  Features Of Token  Development (1).pptxKey  Features Of Token  Development (1).pptx
Key Features Of Token Development (1).pptx
 
My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL Certs
 
Snow Chain-Integrated Tire for a Safe Drive on Winter Roads
Snow Chain-Integrated Tire for a Safe Drive on Winter RoadsSnow Chain-Integrated Tire for a Safe Drive on Winter Roads
Snow Chain-Integrated Tire for a Safe Drive on Winter Roads
 
Unlocking the Potential of the Cloud for IBM Power Systems
Unlocking the Potential of the Cloud for IBM Power SystemsUnlocking the Potential of the Cloud for IBM Power Systems
Unlocking the Potential of the Cloud for IBM Power Systems
 
Install Stable Diffusion in windows machine
Install Stable Diffusion in windows machineInstall Stable Diffusion in windows machine
Install Stable Diffusion in windows machine
 
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersEnhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
 
DMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special EditionDMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special Edition
 
Benefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other FrameworksBenefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other Frameworks
 

4Developers 2018: Beyond c++17 (Mateusz Pusz)

  • 1. Mateusz Pusz April 9, 2018 BEYOND C++17
  • 2. 4Developers 2018 | Beyond C++17 C++ TIMELINE 2
  • 3. 4Developers 2018 | Beyond C++17 ISO C++ COMMITTEE STRUCTURE 3
  • 4. DEPENDS ON CURRENT TARGET (ESTIMATED) Coroutines C++20 Contracts C++20 Ranges Core concepts in C++20 Rest in C++20 or 23 Modules Core concepts in C++20 Rest in (TBD) focusing on a bridge from header files Reflection TS in C++20 timeframe; IS in C++23 Executors TS in C++20 timeframe; IS in C++23 Networking TS Executors IS in C++23 future.then, async2 Executors IS in C++23 4Developers 2018 | Beyond C++17 MAJOR FEATURES STATUS 4
  • 5. • Usage info – wg21.link • Get paper – wg21.link/nXXXX – wg21.link/pXXXX - latest version (e.g. wg21.link/p0463) – wg21.link/pXXXXrX • Get working dra – wg21.link/standard – wg21.link/concepts – wg21.link/coroutines – wg21.link/modules – wg21.link/networking – wg21.link/ranges 4Developers 2018 | Beyond C++17 FINDING A PAPER - HTTPS://WG21.LINK 5
  • 7. • Concepts TS standardised 2 years ago • No consensus on merging to IS as is • Consensus reached by postponing the merge of – introducer syntax – terse/natural syntax • Small changes approved – removed bool from concept syntax – removed function concepts • P0734 C++ extensions for Concepts merged with IS 4Developers 2018 | Beyond C++17 CONCEPTS 7
  • 8. Concept definition template<class T> concept Sortable { /* ... */ } Original template notation template<typename T> requires Sortable<T> void sort(T&); The shorthand notation template<Sortable T> void sort(T&); 4Developers 2018 | Beyond C++17 C++ CONCEPTS IN ACTION ACCEPTED FEATURES 8
  • 9. Concept definition template<class T> concept Sortable { /* ... */ } Original template notation template<typename T> requires Sortable<T> void sort(T&); The shorthand notation template<Sortable T> void sort(T&); The terse/natural notation void sort(Sortable&); // Not merged to IS The concept introducer notation Sortable{Seq} void sort(Seq&); // Not merged to IS 4Developers 2018 | Beyond C++17 C++ CONCEPTS IN ACTION ACCEPTED FEATURES NOT ACCEPTED FEATURES 8
  • 10. template<typename T> void f(T&& t) { if(t == other) { /* ... */ } } void foo() { f("abc"s); // OK std::mutex mtx; f(mtx); // Error } 4Developers 2018 | Beyond C++17 CONSTRAINTS AND CONCEPTS 9
  • 11. <source>: In instantiation of 'void f(T&&) [with T = std::mutex&]': 28 : <source>:28:8: required from here 15 : <source>:15:8: error: no match for 'operator==' (operand types are 'std::mutex' and 'std::mutex') if(t == other) { ~~^~~~~~~~ In file included from /opt/compiler-explorer/gcc-7.2.0/include/c++/7.2.0/mutex:42:0, from <source>:2: /opt/compiler-explorer/gcc-7.2.0/include/c++/7.2.0/system_error:311:3: note: candidate: bool std::operator==(const std::error_cond operator==(const error_condition& __lhs, ^~~~~~~~ /opt/compiler-explorer/gcc-7.2.0/include/c++/7.2.0/system_error:311:3: note: no known conversion for argument 1 from 'std::mutex /opt/compiler-explorer/gcc-7.2.0/include/c++/7.2.0/system_error:304:3: note: candidate: bool std::operator==(const std::error_cond operator==(const error_condition& __lhs, const error_code& __rhs) noexcept ^~~~~~~~ ... 290 lines more ... In file included from /opt/compiler-explorer/gcc-7.2.0/include/c++/7.2.0/bits/stl_algobase.h:64:0, from /opt/compiler-explorer/gcc-7.2.0/include/c++/7.2.0/memory:62, from <source>:1: /opt/compiler-explorer/gcc-7.2.0/include/c++/7.2.0/bits/stl_pair.h:443:5: note: candidate: template<class _T1, class _T2> constexp operator==(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y) ^~~~~~~~ /opt/compiler-explorer/gcc-7.2.0/include/c++/7.2.0/bits/stl_pair.h:443:5: note: template argument deduction/substitution failed 15 : <source>:15:8: note: 'std::mutex' is not derived from 'const std::pair<_T1, _T2>' if(t == other) { ~~^~~~~~~~ Compiler exited with result code 1 4Developers 2018 | Beyond C++17 CONSTRAINTS AND CONCEPTS 10
  • 12. template<typename T> concept EqualityComparable = requires(T a, T b) { a == b; requires Boolean<decltype(a == b)>; // simplified definition }; 4Developers 2018 | Beyond C++17 CONSTRAINTS AND CONCEPTS 11
  • 13. template<typename T> concept EqualityComparable = requires(T a, T b) { a == b; requires Boolean<decltype(a == b)>; // simplified definition }; template<typename T> requires EqualityComparable<T> void f(T&& t) { if(t == other) { /* ... */ } } 4Developers 2018 | Beyond C++17 CONSTRAINTS AND CONCEPTS 11
  • 14. template<typename T> concept EqualityComparable = requires(T a, T b) { a == b; requires Boolean<decltype(a == b)>; // simplified definition }; template<typename T> requires EqualityComparable<T> void f(T&& t) { if(t == other) { /* ... */ } } void foo() { f("abc"s); // OK std::mutex mtx; std::unique_lock<std::mutex> lock{mtx}; f(mtx); // Error: not EqualityComparable } 4Developers 2018 | Beyond C++17 CONSTRAINTS AND CONCEPTS 11
  • 15. <source>: In function 'void foo()': 28 : <source>:28:8: error: cannot call function 'void f(T&&) [with T = std::mutex&]' f(mtx); // Error: not EqualityComparable ^ 12 : <source>:12:6: note: constraints not satisfied void f(T&& t) ^ 6 : <source>:6:14: note: within 'template<class T> concept const bool EqualityComparable<T> [with T = std::mutex&]' concept bool EqualityComparable = requires(T a, T b) { ^~~~~~~~~~~~~~~~~~ 6 : <source>:6:14: note: with 'std::mutex& a' 6 : <source>:6:14: note: with 'std::mutex& b' 6 : <source>:6:14: note: the required expression '(a == b)' would be ill-formed Compiler exited with result code 1 4Developers 2018 | Beyond C++17 CONSTRAINTS AND CONCEPTS 12
  • 16. #include <stdio.h> #include <time.h> static const char* const wday[] = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "-unknown-" }; int main() { struct tm time_str; time_str.tm_year = 2001 - 1900; time_str.tm_mon = 7 - 1; time_str.tm_mday = 4; time_str.tm_hour = 0; time_str.tm_min = 0; time_str.tm_sec = 0; time_str.tm_isdst = -1; if (mktime(&time_str) == (time_t)(-1)) time_str.tm_wday = 7; printf("%sn", wday[time_str.tm_wday]); } 4Developers 2018 | Beyond C++17 WHAT DAY OF THE WEEK IS JULY 4, 2001? C 13
  • 17. #include <stdio.h> #include <time.h> static const char* const wday[] = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "-unknown-" }; int main() { struct tm time_str; time_str.tm_year = 2001 - 1900; time_str.tm_mon = 7 - 1; time_str.tm_mday = 4; time_str.tm_hour = 0; time_str.tm_min = 0; time_str.tm_sec = 0; time_str.tm_isdst = -1; if (mktime(&time_str) == (time_t)(-1)) time_str.tm_wday = 7; printf("%sn", wday[time_str.tm_wday]); } #include <chrono> #include <iostream> int main() { using namespace std::chrono; std::cout << weekday{jul/4/2001} << 'n'; } 4Developers 2018 | Beyond C++17 WHAT DAY OF THE WEEK IS JULY 4, 2001? C C++20 13
  • 18. • Seamless integration with the existing library • Type safety • Detection of errors at compile time • Performance • Ease of use • Readable code • No artificial restrictions on precision 4Developers 2018 | Beyond C++17 P0355 EXTENDING CHRONO TO CALENDARS AND TIME ZONES GOALS 14
  • 19. constexpr year_month_day ymd1{2016y, month{5}, day{29}}; constexpr auto ymd2 = 2016y/may/29d; constexpr auto ymd3 = sun[5]/may/2016; 4Developers 2018 | Beyond C++17 P0355 EXTENDING CHRONO TO CALENDARS AND TIME ZONES EXAMPLES 15
  • 20. constexpr year_month_day ymd1{2016y, month{5}, day{29}}; constexpr auto ymd2 = 2016y/may/29d; constexpr auto ymd3 = sun[5]/may/2016; constexpr system_clock::time_point tp = sys_days{sun[5]/may/2016};// Convert date to time_point static_assert(tp.time_since_epoch() == 1'464'480'000'000'000us); constexpr auto ymd = year_month_weekday{floor<days>(tp)}; // Convert time_point to date static_assert(ymd == sun[5]/may/2016); 4Developers 2018 | Beyond C++17 P0355 EXTENDING CHRONO TO CALENDARS AND TIME ZONES EXAMPLES 15
  • 21. constexpr year_month_day ymd1{2016y, month{5}, day{29}}; constexpr auto ymd2 = 2016y/may/29d; constexpr auto ymd3 = sun[5]/may/2016; constexpr system_clock::time_point tp = sys_days{sun[5]/may/2016};// Convert date to time_point static_assert(tp.time_since_epoch() == 1'464'480'000'000'000us); constexpr auto ymd = year_month_weekday{floor<days>(tp)}; // Convert time_point to date static_assert(ymd == sun[5]/may/2016); auto tp = sys_days{2016y/may/29d} + 7h + 30min + 6s + 153ms; // 2016-05-29 07:30:06.153 UTC zoned_time zt = {"Asia/Tokyo", tp}; cout << zt << 'n'; // 2016-05-29 16:30:06.153 JST 4Developers 2018 | Beyond C++17 P0355 EXTENDING CHRONO TO CALENDARS AND TIME ZONES EXAMPLES 15
  • 22. • Minimal extensions to <chrono> to support calendar and time zone libraries • A proleptic Gregorian calendar (civil calendar) • A time zone library based on the IANA Time Zone Database • strftime-like formatting and parsing facilities with fully operational support for fractional seconds, time zone abbreviations, and UTC o sets • Several <chrono> clocks for computing with leap seconds which is also supported by the IANA Time Zone Database 4Developers 2018 | Beyond C++17 P0355 EXTENDING CHRONO TO CALENDARS AND TIME ZONES FEATURES 16
  • 23. • Calendar: http://howardhinnant.github.io/date/date.html • TimeZone: http://howardhinnant.github.io/date/tz.html • Calendar: https://www.youtube.com/watch?v=tzyGjOm8AKo • Time Zone: https://www.youtube.com/watch?v=Vwd3pduVGKY • https://github.com/HowardHinnant/date 4Developers 2018 | Beyond C++17 P0355 EXTENDING CHRONO TO CALENDARS AND TIME ZONES DOCUMENTATION VIDEO INTRODUCTION FULL IMPLEMENTATION 17
  • 24. The span type is an abstraction that provides a view over a contiguous sequence of objects, the storage of which is owned by some other object. 4Developers 2018 | Beyond C++17 P0122 <span> 18
  • 25. The span type is an abstraction that provides a view over a contiguous sequence of objects, the storage of which is owned by some other object. • Simply a view over another object’s contiguous storage – it does not own the elements that are accessible through its interface (similarly to std::string_view) • Never performs any free store allocations 4Developers 2018 | Beyond C++17 P0122 <span> VIEW, NOT CONTAINER 18
  • 26. constexpr ptrdiff_t dynamic_extent = -1; template <class ElementType, ptrdiff_t Extent = dynamic_extent> class span; 4Developers 2018 | Beyond C++17 P0122 <span> 19
  • 27. constexpr ptrdiff_t dynamic_extent = -1; template <class ElementType, ptrdiff_t Extent = dynamic_extent> class span; • dynamic_extent is a unique value outside the normal range of lengths reserved to indicate that the length of the sequence is only known at runtime and must be stored within the span • A dynamic-size span is, conceptually, just a pointer and size field int* somePointer = new int[someLength]; span<int> s{somePointer, someLength}; 4Developers 2018 | Beyond C++17 P0122 <span> DYNAMIC-SIZE (PROVIDED AT RUNTIME) 19
  • 28. constexpr ptrdiff_t dynamic_extent = -1; template <class ElementType, ptrdiff_t Extent = dynamic_extent> class span; • Provides a value for Extent that is between 0 and PTRDIFF_MAX (inclusive) • Requires no storage size overhead beyond a single pointer int arr[10]; span<int, 10> s1{arr}; // fixed-size span of 10 ints // span<int, 20> s2{arr}; // ERROR: will fail to compile span<int> s3{arr}; // dynamic-size span of 10 ints 4Developers 2018 | Beyond C++17 P0122 <span> STATIC-SIZE (FIXED AT COMPILE-TIME) 20
  • 29. constexpr ptrdiff_t dynamic_extent = -1; template <class ElementType, ptrdiff_t Extent = dynamic_extent> class span; • A fixed-size span may be constructed or assigned from another fixed-size span of equal length • A dynamic-size span may always be constructed or assigned from a fixed-size span • A fixed-size span may always be constructed or assigned from a dynamic-size span – undefined behavior will result if the construction or assignment is not bounds-safe 4Developers 2018 | Beyond C++17 P0122 <span> FIXED AND STATIC SIZE CONVERSIONS 21
  • 30. constexpr span(); constexpr span(pointer ptr, index_type count); constexpr span(pointer firstElem, pointer lastElem); template <size_t N> constexpr span(element_type (&arr)[N]); template <size_t N> constexpr span(array<remove_const_t<element_type>, N>& arr); template <size_t N> constexpr span(const array<remove_const_t<element_type>, N>& arr); template <class Container> constexpr span(Container& cont); template <class Container> constexpr span(const Container& cont); constexpr span(const span& other) noexcept = default; template <class OtherElementType, ptrdiff_t OtherExtent> constexpr span(const span<OtherElementType, OtherExtent>& other); 4Developers 2018 | Beyond C++17 P0122 <span> CONSTRUCTION 22
  • 31. constexpr reference operator[](index_type idx) const; constexpr reference operator()(index_type idx) const; constexpr pointer data() const noexcept; 4Developers 2018 | Beyond C++17 P0122 <span> ELEMENT ACCESS AND ITERATION 23
  • 32. constexpr reference operator[](index_type idx) const; constexpr reference operator()(index_type idx) const; constexpr pointer data() const noexcept; constexpr iterator begin() const noexcept; constexpr iterator end() const noexcept; constexpr const_iterator cbegin() const noexcept; constexpr const_iterator cend() const noexcept; constexpr reverse_iterator rbegin() const noexcept; constexpr reverse_iterator rend() const noexcept; constexpr const_reverse_iterator crbegin() const noexcept; constexpr const_reverse_iterator crend() const noexcept; 4Developers 2018 | Beyond C++17 P0122 <span> ELEMENT ACCESS AND ITERATION 23
  • 33. template <class ElementType, ptrdiff_t Extent> span<const byte, ((Extent == dynamic_extent) ? dynamic_extent : (sizeof(ElementType)*Extent))> as_bytes(span<ElementType, Extent> s) noexcept; template <class ElementType, ptrdiff_t Extent> span<byte, ((Extent == dynamic_extent) ? dynamic_extent : (sizeof(ElementType)*Extent))> as_writeable_bytes(span<ElementType, Extent>) noexcept; 4Developers 2018 | Beyond C++17 P0122 <span> BYTE REPRESENTATIONS AND CONVERSIONS 24
  • 34. template <class ElementType, ptrdiff_t Extent> constexpr bool operator==(span<ElementType, Extent> l, span<ElementType, Extent> r); template <class ElementType, ptrdiff_t Extent> constexpr bool operator!=(span<ElementType, Extent> l, span<ElementType, Extent> r); template <class ElementType, ptrdiff_t Extent> constexpr bool operator<(span<ElementType, Extent> l, span<ElementType, Extent> r); template <class ElementType, ptrdiff_t Extent> constexpr bool operator<=(span<ElementType, Extent> l, span<ElementType, Extent> r); template <class ElementType, ptrdiff_t Extent> constexpr bool operator>(span<ElementType, Extent> l, span<ElementType, Extent> r); template <class ElementType, ptrdiff_t Extent> constexpr bool operator>=(span<ElementType, Extent> l, span<ElementType, Extent> r); 4Developers 2018 | Beyond C++17 P0122 <span> COMPARISONS 25
  • 35. constexpr span<element_type, dynamic_extent> first(index_type count) const; constexpr span<element_type, dynamic_extent> last(index_type count) const; constexpr span<element_type, dynamic_extent> subspan(index_type offset, index_type count = dynamic_extent) const; 4Developers 2018 | Beyond C++17 P0122 <span> CREATING SUB-SPANS 26
  • 36. constexpr span<element_type, dynamic_extent> first(index_type count) const; constexpr span<element_type, dynamic_extent> last(index_type count) const; constexpr span<element_type, dynamic_extent> subspan(index_type offset, index_type count = dynamic_extent) const; template <ptrdiff_t Count> constexpr span<element_type, Count> first() const; template <ptrdiff_t Count> constexpr span<element_type, Count> last() const; template <ptrdiff_t Offset, ptrdiff_t Count = dynamic_extent> constexpr span<element_type, Count> subspan() const; 4Developers 2018 | Beyond C++17 P0122 <span> CREATING SUB-SPANS 26
  • 37. • Cheap to construct, copy, move, and use • Users are encouraged to use it as a pass-by-value parameter type • Construction or assignment between span objects with di erent element types is allowed whenever it can be determined statically that the element types are exactly storage-size equivalent • It is always possible to convert from a span<T> to a span<const T>, it is not allowed to convert in the opposite direction, from span<const T> to span<T> s- Span has a trivial destructor, so common ABI conventions allow it to be passed in registers 4Developers 2018 | Beyond C++17 P0122 <span> 27
  • 38. class P { int x; int y; public: friend bool operator==(const P& a, const P& b) { return a.x==b.x && a.y==b.y; } friend bool operator< (const P& a, const P& b) { return a.x<b.x || (a.x==b.x && a.y<b.y); } friend bool operator!=(const P& a, const P& b) { return !(a==b); } friend bool operator<=(const P& a, const P& b) { return !(b<a); } friend bool operator> (const P& a, const P& b) { return b<a; } friend bool operator>=(const P& a, const P& b) { return !(a<b); } // ... non-comparison functions ... }; 4Developers 2018 | Beyond C++17 P0515 P0768 P0905 CONSISTENT COMPARISON C++17 28
  • 39. class P { int x; int y; public: friend bool operator==(const P& a, const P& b) { return a.x==b.x && a.y==b.y; } friend bool operator< (const P& a, const P& b) { return a.x<b.x || (a.x==b.x && a.y<b.y); } friend bool operator!=(const P& a, const P& b) { return !(a==b); } friend bool operator<=(const P& a, const P& b) { return !(b<a); } friend bool operator> (const P& a, const P& b) { return b<a; } friend bool operator>=(const P& a, const P& b) { return !(a<b); } // ... non-comparison functions ... }; class P { int x; int y; public: auto operator<=>(const P&) const = default; // ... non-comparison functions ... }; • a <=> b returns an object that compares – <0 if a < b – >0 if a > b – ==0 if a and b are equal/equivalent • Memberwise semantics by default • Commonly known as a spaceship operator 4Developers 2018 | Beyond C++17 P0515 P0768 P0905 CONSISTENT COMPARISON C++17 C++20 28
  • 40. class ci_string { std::string s; public: // ... friend bool operator==(const ci_string& a, const ci_string& b) { return ci_compare(a.s.c_str(), b.s.c_str()) != 0; } friend bool operator< (const ci_string& a, const ci_string& b) { return ci_compare(a.s.c_str(), b.s.c_str()) < 0; } friend bool operator!=(const ci_string& a, const ci_string& b) { return !(a == b); } friend bool operator> (const ci_string& a, const ci_string& b) { return b < a; } friend bool operator>=(const ci_string& a, const ci_string& b) { return !(a < b); } friend bool operator<=(const ci_string& a, const ci_string& b) { return !(b < a); } friend bool operator==(const ci_string& a, const char* b) { return ci_compare(a.s.c_str(), b) != 0; } friend bool operator< (const ci_string& a, const char* b) { return ci_compare(a.s.c_str(), b) < 0; } friend bool operator!=(const ci_string& a, const char* b) { return !(a == b); } friend bool operator> (const ci_string& a, const char* b) { return b < a; } friend bool operator>=(const ci_string& a, const char* b) { return !(a < b); } friend bool operator<=(const ci_string& a, const char* b) { return !(b < a); } friend bool operator==(const char* a, const ci_string& b) { return ci_compare(a, b.s.c_str()) != 0; } friend bool operator< (const char* a, const ci_string& b) { return ci_compare(a, b.s.c_str()) < 0; } friend bool operator!=(const char* a, const ci_string& b) { return !(a == b); } friend bool operator> (const char* a, const ci_string& b) { return b < a; } friend bool operator>=(const char* a, const ci_string& b) { return !(a < b); } friend bool operator<=(const char* a, const ci_string& b) { return !(b < a); } }; 4Developers 2018 | Beyond C++17 P0515 P0768 P0905 CONSISTENT COMPARISON 29
  • 41. class ci_string { std::string s; public: // ... std::weak_ordering operator<=>(const ci_string& b) const { return ci_compare(s.c_str(), b.s.c_str()); } std::weak_ordering operator<=>(const char* b) const { return ci_compare(s.c_str(), b); } }; 4Developers 2018 | Beyond C++17 P0515 P0768 P0905 CONSISTENT COMPARISON 30
  • 42. class ci_string { std::string s; public: // ... std::weak_ordering operator<=>(const ci_string& b) const { return ci_compare(s.c_str(), b.s.c_str()); } std::weak_ordering operator<=>(const char* b) const { return ci_compare(s.c_str(), b); } }; • <compare> header needed when user manually provides <=> implementation TYPE RETURNED FROM OPERATOR<=>() A<B SUPPORTED A<B NOT SUPPORTED a==b => f(a)==f(b) std::strong_ordering std::strong_equality a==b => f(a)!=f(b) std::weak_ordering std::weak_equality 4Developers 2018 | Beyond C++17 P0515 P0768 P0905 CONSISTENT COMPARISON 30
  • 43. class ci_string { std::string s; public: // ... std::weak_ordering operator<=>(const ci_string& b) const { return ci_compare(s.c_str(), b.s.c_str()); } std::weak_ordering operator<=>(const char* b) const { return ci_compare(s.c_str(), b); } }; • <compare> header needed when user manually provides <=> implementation TYPE RETURNED FROM OPERATOR<=>() A<B SUPPORTED A<B NOT SUPPORTED a==b => f(a)==f(b) std::strong_ordering std::strong_equality a==b => f(a)!=f(b) std::weak_ordering std::weak_equality 4Developers 2018 | Beyond C++17 P0515 P0768 P0905 CONSISTENT COMPARISON <=> operator nearly ended in a header named "=" ;-) 30
  • 44. class totally_ordered : base { std::string tax_id_; std::string first_name_; std::string last_name_; public: std::strong_ordering operator<=>(const totally_ordered& other) const { if(auto cmp = (base&)(*this) <=> (base&)other; cmp != 0) return cmp; if(auto cmp = last_name_ <=> other.last_name_; cmp != 0) return cmp; if(auto cmp = first_name_ <=> other.first_name_; cmp != 0) return cmp; return tax_id_ <=> other.tax_id_; } // ... non-comparison functions ... }; 4Developers 2018 | Beyond C++17 P0515 P0768 P0905 CONSISTENT COMPARISON 31
  • 45. class totally_ordered : base { std::string tax_id_; std::string first_name_; std::string last_name_; public: std::strong_ordering operator<=>(const totally_ordered& other) const { if(auto cmp = (base&)(*this) <=> (base&)other; cmp != 0) return cmp; if(auto cmp = last_name_ <=> other.last_name_; cmp != 0) return cmp; if(auto cmp = first_name_ <=> other.first_name_; cmp != 0) return cmp; return tax_id_ <=> other.tax_id_; } // ... non-comparison functions ... }; 4Developers 2018 | Beyond C++17 P0515 P0768 P0905 CONSISTENT COMPARISON Compile-time error if a member does not have a strong_ordering 31
  • 46. TYPE CATEGORY bool, integral, pointer types std::strong_ordering floating point types std::partial_ordering enumerations the same as underlying type std::nullptr_t std::strong_ordering copyable arrays T[N] the same as T other arrays no <=> void no <=> All built-in <=> comparisons are constexpr beside pointers into the di erent object/allocation 4Developers 2018 | Beyond C++17 P0515 P0768 P0905 CONSISTENT COMPARISON 32
  • 47. class std::weak_equality; class std::strong_equality; class std::partial_ordering; class std::weak_ordering; class std::strong_ordering; 4Developers 2018 | Beyond C++17 P0515 P0768 P0905 CONSISTENT COMPARISON 33
  • 48. class std::weak_equality; class std::strong_equality; class std::partial_ordering; class std::weak_ordering; class std::strong_ordering; constexpr bool std::is_eq (std::weak_equality cmp) noexcept { return cmp == 0; } constexpr bool std::is_neq (std::weak_equality cmp) noexcept { return cmp != 0; } constexpr bool std::is_lt (std::partial_ordering cmp) noexcept { return cmp < 0; } constexpr bool std::is_lteq(std::partial_ordering cmp) noexcept { return cmp <= 0; } constexpr bool std::is_gt (std::partial_ordering cmp) noexcept { return cmp > 0; } constexpr bool std::is_gteq(std::partial_ordering cmp) noexcept { return cmp >= 0; } 4Developers 2018 | Beyond C++17 P0515 P0768 P0905 CONSISTENT COMPARISON 33
  • 49. class std::weak_equality; class std::strong_equality; class std::partial_ordering; class std::weak_ordering; class std::strong_ordering; constexpr bool std::is_eq (std::weak_equality cmp) noexcept { return cmp == 0; } constexpr bool std::is_neq (std::weak_equality cmp) noexcept { return cmp != 0; } constexpr bool std::is_lt (std::partial_ordering cmp) noexcept { return cmp < 0; } constexpr bool std::is_lteq(std::partial_ordering cmp) noexcept { return cmp <= 0; } constexpr bool std::is_gt (std::partial_ordering cmp) noexcept { return cmp > 0; } constexpr bool std::is_gteq(std::partial_ordering cmp) noexcept { return cmp >= 0; } template<class T> constexpr std::strong_ordering std::strong_order (const T& a, const T& b); template<class T> constexpr std::weak_ordering std::weak_order (const T& a, const T& b); template<class T> constexpr std::partial_ordering std::partial_order(const T& a, const T& b); template<class T> constexpr std::strong_equality std::strong_equal (const T& a, const T& b); template<class T> constexpr std::weak_equality std::weak_equal (const T& a, const T& b); 4Developers 2018 | Beyond C++17 P0515 P0768 P0905 CONSISTENT COMPARISON 33
  • 50. template<class T, class U> constexpr auto std::compare_3way(const T& a, const U& b); template<class InputIterator1, class InputIterator2> constexpr auto std::lexicographical_compare_3way(InputIterator1 b1, InputIterator1 e1, InputIterator2 b2, InputIterator2 e2); template<class InputIterator1, class InputIterator2, class Cmp> constexpr auto std::lexicographical_compare_3way(InputIterator1 b1, InputIterator1 e1, InputIterator2 b2, InputIterator2 e2, Cmp comp) -> std::common_comparison_category_t<decltype(comp(*b1,*b2)), std::strong_ordering>; 4Developers 2018 | Beyond C++17 P0515 P0768 P0905 CONSISTENT COMPARISON 34
  • 51. template<class T, class U> constexpr auto std::compare_3way(const T& a, const U& b); template<class InputIterator1, class InputIterator2> constexpr auto std::lexicographical_compare_3way(InputIterator1 b1, InputIterator1 e1, InputIterator2 b2, InputIterator2 e2); template<class InputIterator1, class InputIterator2, class Cmp> constexpr auto std::lexicographical_compare_3way(InputIterator1 b1, InputIterator1 e1, InputIterator2 b2, InputIterator2 e2, Cmp comp) -> std::common_comparison_category_t<decltype(comp(*b1,*b2)), std::strong_ordering>; 4Developers 2018 | Beyond C++17 P0515 P0768 P0905 CONSISTENT COMPARISON std::rel_ops are now deprecated 34
  • 52. 1 <=> provides total ordering, 2-way operators are changed accordingly 2 2-way unchanged, <=> provides total ordering - inconsistent 3 2-way unchanged, <=> compatible with 2-way, total order not guaranteed 4Developers 2018 | Beyond C++17 P0515 P0768 P0905 CONSISTENT COMPARISON ISSUE: COMPARING OBJECT POINTERS Option (3) selected as for today and waiting for more proposals 35
  • 53. • Atomically transfers the contents of an internal stream bu er to a basic_ostream’s stream bu er on destruction of the basic_osyncstream { std::osyncstream out{std::cout}; out << "Hello, " << "World!" << ’n’; } std::osyncstream{std::cout} << "The answer is " << 6*7 << std::endl; 4Developers 2018 | Beyond C++17 P0053 SYNCHRONIZED BUFFERED OSTREAMS 36
  • 54. template<class charT, class traits, class Allocator> class basic_syncbuf : public basic_streambuf<charT, traits> { public: bool emit(); streambuf_type* get_wrapped() const noexcept; void set_emit_on_sync(bool) noexcept; protected: int sync() override; // ... }; using syncbuf = basic_syncbuf<char>; using wsyncbuf = basic_syncbuf<wchar_t>; • emit() atomically transfers the contents of the internal bu er to the wrapped stream bu er, so that they appear in the output stream as a contiguous sequence of characters • sync() records that the wrapped stream bu er is to be flushed, then, if emit_on_sync == true, calls emit() 4Developers 2018 | Beyond C++17 P0053 SYNCHRONIZED BUFFERED OSTREAMS 37
  • 55. template<class charT, class traits, class Allocator> class basic_osyncstream : public basic_ostream<charT, traits> { basic_syncbuf<charT, traits, Allocator> sb_; public: void emit() { sb_.emit(); } streambuf_type* get_wrapped() const noexcept { return sb_.get_wrapped(); } syncbuf_type* rdbuf() const noexcept { return &sb_; } // ... }; using osyncstream = basic_osyncstream<char>; using wosyncstream = basic_osyncstream<wchar_t>; 4Developers 2018 | Beyond C++17 P0053 SYNCHRONIZED BUFFERED OSTREAMS 38
  • 56. { std::osyncstream out{std::cout}; out << "Hello," << ’n’; // no flush out.emit(); // characters transferred; cout not flushed out << "World!" << std::endl; // flush noted; out not flushed out.emit(); // characters transferred; cout flushed out << "Greetings." << ’n’; // no flush } // characters transferred; cout not flushed 4Developers 2018 | Beyond C++17 P0053 SYNCHRONIZED BUFFERED OSTREAMS EXAMPLE: A FLUSH ON A BASIC_OSYNCSTREAM DOES NOT FLUSH IMMEDIATELY 39
  • 57. { std::osyncstream out1{std::cout}; out1 << "Hello, "; { std::osyncstream(out1.get_wrapped()) << "Goodbye, " << "Planet!" << ’n’; } out1 << "World!" << ’n’; } Goodbye, Planet! Hello, World! 4Developers 2018 | Beyond C++17 P0053 SYNCHRONIZED BUFFERED OSTREAMS EXAMPLE: OBTAINING THE WRAPPED STREAM BUFFER WITH GET_WRAPPED() ALLOWS WRAPPING IT AGAIN WITH AN OSYNCSTREAM 40
  • 58. Users of basic_osyncstream known only via ostream& down the call chain do not have the possibility to modify their flushing behavior. 4Developers 2018 | Beyond C++17 P0753 MANIPULATORS FOR C++ SYNCHRONIZED BUFFERED OSTREAM MOTIVATION 41
  • 59. Users of basic_osyncstream known only via ostream& down the call chain do not have the possibility to modify their flushing behavior. Add the following manipulators for ostream template <class charT, class traits> basic_ostream<charT, traits>& emit_on_flush(basic_ostream<charT, traits>& os); template <class charT, class traits> basic_ostream<charT, traits>& noemit_on_flush(basic_ostream<charT, traits>& os); template <class charT, class traits> basic_ostream<charT, traits>& flush_emit(basic_ostream<charT, traits>& os); 4Developers 2018 | Beyond C++17 P0753 MANIPULATORS FOR C++ SYNCHRONIZED BUFFERED OSTREAM MOTIVATION SOLUTION 41
  • 60. • The C++ standard provides an API to access and manipulate specific shared_ptr objects atomically auto ptr = std::make_shared<int>(0); runThreads(5, [&](int i) { std::atomic_store(&ptr, std::make_shared<int>(i)); return *ptr; }); 4Developers 2018 | Beyond C++17 P0718 std::atomic<std::shared_ptr<T>> MOTIVATION 42
  • 61. • The C++ standard provides an API to access and manipulate specific shared_ptr objects atomically auto ptr = std::make_shared<int>(0); runThreads(5, [&](int i) { std::atomic_store(&ptr, std::make_shared<int>(i)); return *ptr; }); • Fragile and error-prone – shared_ptr objects manipulated through this API are indistinguishable from other shared_ptr objects – They may be manipulated/accessed only through this API (i.e. you cannot dereference such a shared_ptr without first loading it into another shared_ptr object, and then dereferencing through the second object) 4Developers 2018 | Beyond C++17 P0718 std::atomic<std::shared_ptr<T>> MOTIVATION 42
  • 62. • Merge atomic_shared_ptr from Concurrency TS into IS • Refactor to be std::atomic specializations for smart pointers template<class T> struct std::atomic<std::shared_ptr<T>>; template<class T> struct std::atomic<std::weak_ptr<T>>; 4Developers 2018 | Beyond C++17 P0718 std::atomic<std::shared_ptr<T>> 43
  • 63. • Merge atomic_shared_ptr from Concurrency TS into IS • Refactor to be std::atomic specializations for smart pointers template<class T> struct std::atomic<std::shared_ptr<T>>; template<class T> struct std::atomic<std::weak_ptr<T>>; • The C++11 Atomic Interface for shared_ptr is deprecated 4Developers 2018 | Beyond C++17 P0718 std::atomic<std::shared_ptr<T>> 43
  • 64. • Adds support for atomic addition on an object conforming to the std::atomic<T> where T is a floating-point type • Capability critical for parallel high performance computing (HPC) applications • Explicit specialization for float, double, long double to provide additional atomic operations appropriate to floating-point types 4Developers 2018 | Beyond C++17 P0020 FLOATING POINT ATOMIC 44
  • 65. EBO idiom introduces a number of problems 4Developers 2018 | Beyond C++17 P0840 LANGUAGE SUPPORT FOR EMPTY OBJECTS MOTIVATION 45
  • 66. EBO idiom introduces a number of problems • Limited applicability – EBO is not available for final classes, nor for classes with virtual bases that have non-public destructors 4Developers 2018 | Beyond C++17 P0840 LANGUAGE SUPPORT FOR EMPTY OBJECTS MOTIVATION 45
  • 67. EBO idiom introduces a number of problems • Limited applicability – EBO is not available for final classes, nor for classes with virtual bases that have non-public destructors • Name leakage – member names of base classes are visible to users of the derived class (unless shadowed), even if the base class is inaccessible – unqualified lookups in code deriving from the class employing EBO is a ected by names in the EBO base class 4Developers 2018 | Beyond C++17 P0840 LANGUAGE SUPPORT FOR EMPTY OBJECTS MOTIVATION 45
  • 68. EBO idiom introduces a number of problems • Limited applicability – EBO is not available for final classes, nor for classes with virtual bases that have non-public destructors • Name leakage – member names of base classes are visible to users of the derived class (unless shadowed), even if the base class is inaccessible – unqualified lookups in code deriving from the class employing EBO is a ected by names in the EBO base class • Implementation awkwardness – EBO requires state that would naturally be represented as a data member to be moved into a base class 4Developers 2018 | Beyond C++17 P0840 LANGUAGE SUPPORT FOR EMPTY OBJECTS MOTIVATION 45
  • 69. • Unique address is not required for an non-static data member of a class • A non-static data member with this attribute may share its address with another object, if it could when used as a base class • It is meant to replace EBO Idiom 4Developers 2018 | Beyond C++17 P0840 LANGUAGE SUPPORT FOR EMPTY OBJECTS SOLUTION 46
  • 70. • Unique address is not required for an non-static data member of a class • A non-static data member with this attribute may share its address with another object, if it could when used as a base class • It is meant to replace EBO Idiom template<typename Key, typename Value, typename Hash, typename Pred, typename Allocator> class hash_map { [[no_unique_address]] Hash hasher; [[no_unique_address]] Pred pred; [[no_unique_address]] Allocator alloc; Bucket *buckets; // ... public: // ... }; 4Developers 2018 | Beyond C++17 P0840 LANGUAGE SUPPORT FOR EMPTY OBJECTS SOLUTION 46
  • 71. • Compiler's optimizers o en have no information relating to branch probability which can lead to suboptimal code generation • In many cases the excellent dynamic branch predictors on modern processors can make up for this lack of information • However in some cases code may execute more slowly than necessary even though the programmer knew the probability of particular branches being executed • Currently code developers do not have an easy way to communicate this to the compiler 4Developers 2018 | Beyond C++17 P0479 PROPOSED WORDING FOR likely AND unlikely ATTRIBUTES MOTIVATION 47
  • 72. • The attribute-tokens likely and unlikely may be applied to statements • They shall appear at most once in each attribute-list and no attribute-argument-clause shall be present • The likely attribute is not allowed to appear in the same attribute-list as the unlikely attribute 4Developers 2018 | Beyond C++17 P0479 PROPOSED WORDING FOR likely AND unlikely ATTRIBUTES SOLUTION 48
  • 73. • When a [[likely]] attribute appears in an if statement, implementations are encouraged to optimize for the case where that statement is executed if (foo()) [[likely]] { baz(); } 4Developers 2018 | Beyond C++17 P0479 PROPOSED WORDING FOR likely AND unlikely ATTRIBUTES 49
  • 74. • When a [[likely]] attribute appears in an if statement, implementations are encouraged to optimize for the case where that statement is executed if (foo()) [[likely]] { baz(); } • When a [[likely]] attributes appears in a nested if statement, implementations are encouraged to optimize for the case where that statement is executed if (foo()) { if (bar()) [[likely]] { baz(); } } 4Developers 2018 | Beyond C++17 P0479 PROPOSED WORDING FOR likely AND unlikely ATTRIBUTES 49
  • 75. • When a [[likely]] attribute appears inside of a switch case statement, implementations are encouraged to optimize for that case being executed switch (a) { case 1: [[likely]] foo(); break; case 2: bar(); break; default: baz(); break; } 4Developers 2018 | Beyond C++17 P0479 PROPOSED WORDING FOR likely AND unlikely ATTRIBUTES 50
  • 76. • When an [[unlikely]] attribute appears inside of a loop, implementations are encouraged to optimize for the case where that statement is not executed while (foo()) { [[unlikely]] baz(); } 4Developers 2018 | Beyond C++17 P0479 PROPOSED WORDING FOR likely AND unlikely ATTRIBUTES 51
  • 77. • When an [[unlikely]] attribute appears inside of a loop, implementations are encouraged to optimize for the case where that statement is not executed while (foo()) { [[unlikely]] baz(); } 4Developers 2018 | Beyond C++17 P0479 PROPOSED WORDING FOR likely AND unlikely ATTRIBUTES Excessive usage of either of these attributes is liable to result in performance degradation 51
  • 78. enum class endian { little = __ORDER_LITTLE_ENDIAN__, big = __ORDER_BIG_ENDIAN__, native = __BYTE_ORDER__ }; 4Developers 2018 | Beyond C++17 P0463 ENDIAN, JUST ENDIAN TYPE_TRAITS 52
  • 79. enum class endian { little = __ORDER_LITTLE_ENDIAN__, big = __ORDER_BIG_ENDIAN__, native = __BYTE_ORDER__ }; if(endian::native == endian::big) // handle big endian else if(endian::native == endian::little) // handle little endian else // handle mixed endian 4Developers 2018 | Beyond C++17 P0463 ENDIAN, JUST ENDIAN TYPE_TRAITS 52
  • 80. struct A { int x; int y; int z; }; A a{.x = 1, .z = 2}; // OK: a.y initialized to 0 A b{.y = 2, .x = 1}; // Error: designator order does not match declaration order 4Developers 2018 | Beyond C++17 P0329 DESIGNATED INITIALIZATION 53
  • 81. struct A { int x; int y; int z; }; A a{.x = 1, .z = 2}; // OK: a.y initialized to 0 A b{.y = 2, .x = 1}; // Error: designator order does not match declaration order struct A { string a; int b = 42; int c = -1; }; A a{.c = 21}; // a.a initialized to string{}, a.b to 42, a.c to 21 4Developers 2018 | Beyond C++17 P0329 DESIGNATED INITIALIZATION 53
  • 82. union u { int a; const char* b; }; u a = { 1 }; u d = { 0, "asdf" }; // Error u e = { "asdf" }; // Error u f = { .b = "asdf" }; u g = { .a = 1, .b = "asdf" }; // Error 4Developers 2018 | Beyond C++17 P0329 DESIGNATED INITIALIZATION 54
  • 83. struct S { int x : 8 = 42; }; 4Developers 2018 | Beyond C++17 P0683 DEFAULT MEMBER INITIALIZERS FOR BIT-FIELDS 55
  • 84. { T thing = f(); for(auto& x : thing.items()) { mutate(&x); log(x); } } { for(auto& x : f().items()) { // WRONG mutate(&x); log(x); } } 4Developers 2018 | Beyond C++17 P0614 RANGE-BASED FOR STATEMENTS WITH INITIALIZER C++17 56
  • 85. { T thing = f(); for(auto& x : thing.items()) { mutate(&x); log(x); } } { for(auto& x : f().items()) { // WRONG mutate(&x); log(x); } } for(T thing = f(); auto& x : thing.items()) { mutate(&x); log(x); } 4Developers 2018 | Beyond C++17 P0614 RANGE-BASED FOR STATEMENTS WITH INITIALIZER C++17 C++20 56
  • 86. { std::size_t i = 0; for(const auto& x : foo()) { bar(x, i); ++i; } } 4Developers 2018 | Beyond C++17 P0614 RANGE-BASED FOR STATEMENTS WITH INITIALIZER C++17 57
  • 87. { std::size_t i = 0; for(const auto& x : foo()) { bar(x, i); ++i; } } for(std::size_t i = 0; const auto& x : foo()) { bar(x, i); ++i; } 4Developers 2018 | Beyond C++17 P0614 RANGE-BASED FOR STATEMENTS WITH INITIALIZER C++17 C++20 57
  • 88. { std::size_t i = 0; for(const auto& x : foo()) { bar(x, i); ++i; } } for(std::size_t i = 0; const auto& x : foo()) { bar(x, i); ++i; } • Enables and encourages locally scoped variables without the programmer having to introduce a scope manually 4Developers 2018 | Beyond C++17 P0614 RANGE-BASED FOR STATEMENTS WITH INITIALIZER C++17 C++20 57
  • 89. • Adds member functions starts_with and ends_with to class templates std::basic_string and std::basic_string_view • Check, whether or not a string starts with a given prefix or ends with a given su ix 4Developers 2018 | Beyond C++17 P0457 STRING PREFIX AND SUFFIX CHECKING 58
  • 90. • Adds member functions starts_with and ends_with to class templates std::basic_string and std::basic_string_view • Check, whether or not a string starts with a given prefix or ends with a given su ix constexpr bool starts_with(basic_string_view x) const noexcept; constexpr bool starts_with(charT x) const noexcept; constexpr bool starts_with(const charT* x) const; constexpr bool ends_with(basic_string_view x) const noexcept; constexpr bool ends_with(charT x) const noexcept; constexpr bool ends_with(const charT* x) const; 4Developers 2018 | Beyond C++17 P0457 STRING PREFIX AND SUFFIX CHECKING 58
  • 91. • New TransformationTrait for the <type_traits> header • Like std::decay, it removes any cv and reference qualifiers • Unlike std::decay, it does not mimic any array-to-pointer or function-to-pointer conversion 4Developers 2018 | Beyond C++17 P0550 std::remove_cvref<T> 59
  • 92. • New TransformationTrait for the <type_traits> header • Like std::decay, it removes any cv and reference qualifiers • Unlike std::decay, it does not mimic any array-to-pointer or function-to-pointer conversion template<typename T> class optional { public: template<typename U = T, enable_if_t<conjunction_v<negation<is_same<optional<T>, remove_cvref_t<U>>>, negation<is_same<in_place_t, remove_cvref_t<U>>>, is_constructible<T, U&&>, is_convertible<U&&, T> >, bool> = true> constexpr optional(U&& t); // ... }; 4Developers 2018 | Beyond C++17 P0550 std::remove_cvref<T> 59
  • 93. • New TransformationTrait for the <type_traits> header • Like std::decay, it removes any cv and reference qualifiers • Unlike std::decay, it does not mimic any array-to-pointer or function-to-pointer conversion template<typename T> class optional { public: template<typename U = T, enable_if_t<conjunction_v<negation<is_same<optional<T>, remove_cvref_t<U>>>, negation<is_same<in_place_t, remove_cvref_t<U>>>, is_constructible<T, U&&>, is_convertible<U&&, T> >, bool> = true> constexpr optional(U&& t); // ... }; • Above and more wrong std::decay usages fixed with P0777 4Developers 2018 | Beyond C++17 P0550 std::remove_cvref<T> 59
  • 94. [[nodiscard]] attribute applied to • async() • allocate() • operator new • launder() • empty() 4Developers 2018 | Beyond C++17 P0600 [[nodiscard]] ATTRIBUTE IN THE STANDARD LIBRARY 60
  • 95. • std::addressof(*p) is not well-defined when p does not reference storage that has an object constructed in it auto p = a.allocate(1); std::allocator_traits<A>::construct(a, std::addressof(*p), v); // WRONG auto p = a.allocate(1); std::allocator_traits<A>::construct(a, std::to_address(p), v); 4Developers 2018 | Beyond C++17 P0653 UTILITY TO CONVERT A POINTER TO A RAW POINTER C++17 C++20 61
  • 96. template<class Ptr> auto to_address(const Ptr& p) noexcept { return to_address(p.operator->()); } template<class T> T* to_address(T* p) noexcept { return p; } 4Developers 2018 | Beyond C++17 P0653 UTILITY TO CONVERT A POINTER TO A RAW POINTER EXAMPLE IMPLEMENTATION 62
  • 97. Intend to make the iterators of some classes usable in constant expressions. Introducing the constexpr iterator requirement that will will easily allow to make constexpr usable iterators by only adding a few words to the iterator requirements of a container 4Developers 2018 | Beyond C++17 P0858 CONSTEXPR ITERATOR REQUIREMENTS MOTIVATION SOLUTION 63
  • 98. #define F(...) f(0 __VA_OPT__(,) __VA_ARGS__) F(a, b, c) // replaced by f(0, a, b, c) F() // replaced by f(0) 4Developers 2018 | Beyond C++17 P0306 COMMA OMISSION AND COMMA DELETION 64
  • 100. std::unordered_map<std::string, int> map = /* ... */; auto it1 = map.find("abc"); auto it2 = map.find("def"sv); 4Developers 2018 | Beyond C++17 P0919 HETEROGENEOUS LOOKUP FOR UNORDERED CONTAINERS C++17 66
  • 101. std::unordered_map<std::string, int> map = /* ... */; auto it1 = map.find("abc"); auto it2 = map.find("def"sv); struct string_hash { using transparent_key_equal = std::equal_to<>; // Pred to use using hash_type = std::hash<std::string_view>; // just a helper local type size_t operator()(std::string_view txt) const { return hash_type{}(txt); } size_t operator()(const std::string& txt) const { return hash_type{}(txt); } size_t operator()(const char* txt) const { return hash_type{}(txt); } }; std::unordered_map<std::string, int, string_hash> map = /* ... */; map.find("abc"); map.find("def"sv); 4Developers 2018 | Beyond C++17 P0919 HETEROGENEOUS LOOKUP FOR UNORDERED CONTAINERS C++17 C++20 66
  • 102. • The behavior of a program that uses operator== or operator!= on unordered containers is undefined unless the Hash and Pred function objects respectively have the same behavior for both containers and the equality comparison function for Key is a refinement of the partition into equivalent-key groups produced by Pred. • The UB definition for heterogenous containers should not apply merely because of inequity among hashers - and in practice, this may be valuable because of hash seeding and randomization 4Developers 2018 | Beyond C++17 P0809 COMPARING UNORDERED CONTAINERS MOTIVATION 67
  • 103. • The behavior of a program that uses operator== or operator!= on unordered containers is undefined unless the Hash and Pred function objects respectively have the same behavior for both containers and the equality comparison function for Key is a refinement of the partition into equivalent-key groups produced by Pred. • The UB definition for heterogenous containers should not apply merely because of inequity among hashers - and in practice, this may be valuable because of hash seeding and randomization • The behavior of a program that uses operator== or operator!= on unordered containers is undefined unless the Pred function object has the same behavior for both containers and the equality comparison operator for Key... 4Developers 2018 | Beyond C++17 P0809 COMPARING UNORDERED CONTAINERS MOTIVATION SOLUTION 67
  • 104. []<typename T>(T x) { /* ... */ } []<typename T, int N>(T (&a)[N]) { /* ... */ } 4Developers 2018 | Beyond C++17 P0428 FAMILIAR TEMPLATE SYNTAX FOR GENERIC LAMBDAS 68
  • 105. auto f = [](auto vector) { using T = typename decltype(vector)::value_type; // ... }; []<typename T>(T x) { /* ... */ } []<typename T, int N>(T (&a)[N]) { /* ... */ } 4Developers 2018 | Beyond C++17 P0428 FAMILIAR TEMPLATE SYNTAX FOR GENERIC LAMBDAS 68
  • 106. template<typename T> struct is_std_vector : std::false_type { }; template<typename T> struct is_std_vector<std::vector<T>> : std::true_type { }; auto f = [](auto vector) { static_assert( is_std_vector<decltype(vector)>::value); using T = typename decltype(vector)::value_type; // ... }; []<typename T>(T x) { /* ... */ } []<typename T, int N>(T (&a)[N]) { /* ... */ } 4Developers 2018 | Beyond C++17 P0428 FAMILIAR TEMPLATE SYNTAX FOR GENERIC LAMBDAS 68
  • 107. template<typename T> struct is_std_vector : std::false_type { }; template<typename T> struct is_std_vector<std::vector<T>> : std::true_type { }; auto f = [](auto vector) { static_assert( is_std_vector<decltype(vector)>::value); using T = typename decltype(vector)::value_type; // ... }; []<typename T>(T x) { /* ... */ } []<typename T, int N>(T (&a)[N]) { /* ... */ } auto f = []<typename T>(std::vector<T> vector) { // ... }; 4Developers 2018 | Beyond C++17 P0428 FAMILIAR TEMPLATE SYNTAX FOR GENERIC LAMBDAS 68
  • 108. struct S { void f(int i) { [&, i]{ }; // OK [&, this, i]{ }; // OK: equivalent to [&, i] [=, *this]{ }; // OK [=, this]{ }; // OK: equivalent to [=] [this, *this]{ }; // Error: this appears twice } }; 4Developers 2018 | Beyond C++17 P0409 ALLOW LAMBDA CAPTURE [=, THIS] 69
  • 109. auto greater = [](auto x, auto y) { return x > y; }; // No need to care whether 'greater' is a lambda or a function object std::map<std::string, int, decltype(greater)> map1; 4Developers 2018 | Beyond C++17 P0624 DEFAULT CONSTRUCTIBLE AND ASSIGNABLE STATELESS LAMBDAS LIBRARY.H USER.CPP 70
  • 110. auto greater = [](auto x, auto y) { return x > y; }; // No need to care whether 'greater' is a lambda or a function object std::map<std::string, int, decltype(greater)> map1; std::map<std::string, int, decltype(greater)> map2{/* ... */}; map1 = map2; 4Developers 2018 | Beyond C++17 P0624 DEFAULT CONSTRUCTIBLE AND ASSIGNABLE STATELESS LAMBDAS LIBRARY.H USER.CPP 70
  • 111. In C++17 template parameter packs can only be captured in lambda by copy, by reference, or by... std::tuple. There is no possibility to do a simple move. 4Developers 2018 | Beyond C++17 P0780 ALLOW PACK EXPANSION IN LAMBDA INIT-CAPTURE MOTIVATION 71
  • 112. template <class... Args> auto delay_invoke_foo(Args... args) { return [args...]() -> decltype(auto) { return foo(args...); }; } In C++17 template parameter packs can only be captured in lambda by copy, by reference, or by... std::tuple. There is no possibility to do a simple move. 4Developers 2018 | Beyond C++17 P0780 ALLOW PACK EXPANSION IN LAMBDA INIT-CAPTURE MOTIVATION BY COPY 71
  • 113. template <class... Args> auto delay_invoke_foo(Args... args) { return [args...]() -> decltype(auto) { return foo(args...); }; } template <class... Args> auto delay_invoke_foo(Args... args) { return [tup=std::make_tuple(std::move(args)...)]() -> decltype(auto) { return std::apply([](auto const&... args) -> decltype(auto) { return foo(args...); }, tup); }; } In C++17 template parameter packs can only be captured in lambda by copy, by reference, or by... std::tuple. There is no possibility to do a simple move. 4Developers 2018 | Beyond C++17 P0780 ALLOW PACK EXPANSION IN LAMBDA INIT-CAPTURE MOTIVATION BY COPY BY MOVE 71
  • 114. Remove the restriction on pack expansions in init-capture, which requires defining a new form of parameter pack in the language. 4Developers 2018 | Beyond C++17 P0780 ALLOW PACK EXPANSION IN LAMBDA INIT-CAPTURE SOLUTION 72
  • 115. template <class... Args> auto delay_invoke_foo(Args... args) { return [tup=std::make_tuple(std::move(args)...)]() -> decltype(auto) { return std::apply([](auto const&... args) -> decltype(auto) { return foo(args...); }, tup); }; } template <class... Args> auto delay_invoke_foo(Args... args) { return [args=std::move(args)...]() -> decltype(auto) { return foo(args...); }; } Remove the restriction on pack expansions in init-capture, which requires defining a new form of parameter pack in the language. 4Developers 2018 | Beyond C++17 P0780 ALLOW PACK EXPANSION IN LAMBDA INIT-CAPTURE SOLUTION C++17 C++20 72
  • 116. // OK constexpr std::complex<double> c1{1.0, 0.0}; constexpr std::complex<double> c2{}; // Failure: arithmetic operations on complex are not constexpr constexpr auto c3 = -c1 + c2 / 100.0; 4Developers 2018 | Beyond C++17 P0415 constexpr FOR std::complex MOTIVATION 73
  • 117. constexpr std::array<char, 6> a { 'H', 'e', 'l', 'l', 'o' }; // OK constexpr auto it = std::find(a.rbegin(), a.rend(), 'H'); // ERROR: std::find is not constexpr 4Developers 2018 | Beyond C++17 P0202 ADD constexpr MODIFIERS TO FUNCTIONS IN <algorithm> AND <utility> HEADERS MOTIVATION 74
  • 118. constexpr std::array<char, 6> a { 'H', 'e', 'l', 'l', 'o' }; // OK constexpr auto it = std::find(a.rbegin(), a.rend(), 'H'); // ERROR: std::find is not constexpr • Add constexpr to all algorithms that – do not use std::swap – do not allocate memory (std::stable_partition, std::inplace_merge, and std::stable_sort) – do not rely upon std::uniform_int_distribution (std::shuffle and std::sample) 4Developers 2018 | Beyond C++17 P0202 ADD constexpr MODIFIERS TO FUNCTIONS IN <algorithm> AND <utility> HEADERS MOTIVATION 74
  • 119. std::vector<std::string> v(10000,"hello"s); std::string s{"start"}; //s.reserve(s.size() + v.size() * v[0].size()); //useless std::accumulate(begin(v), end(v), s); 4Developers 2018 | Beyond C++17 P0616 DE-PESSIMIZE LEGACY <numeric> ALGORITHMS WITH std::move MOTIVATION 75
  • 120. std::vector<std::string> v(10000,"hello"s); std::string s{"start"}; //s.reserve(s.size() + v.size() * v[0].size()); //useless std::accumulate(begin(v), end(v), s); • std::accumulate() and std::partial_sum() acc = std::move(acc) + *i; • std::inner_product() acc = std::move(acc) + (*i1) * (*i2); • std::adjacent_difference() 4Developers 2018 | Beyond C++17 P0616 DE-PESSIMIZE LEGACY <numeric> ALGORITHMS WITH std::move MOTIVATION 75
  • 121. • basic_string::reserve optionally shrinks to fit • Performance trap - can add unexpected and costly dynamic reallocations • Portability barrier - feature optionality may cause di erent behavior when run against di erent library implementations • Complicates generic code - generic code which accepts vector or basic_string as a template argument must add code to avoid calling reserve(n) when n is less than capacity • Duplicates functionality - basic_string::shrink_to_fit • Inconsistent with vector::reserve which does not shrink-to-fit 4Developers 2018 | Beyond C++17 P0966 string::reserve SHOULD NOT SHRINK MOTIVATION 76
  • 122. • basic_string::reserve optionally shrinks to fit • Performance trap - can add unexpected and costly dynamic reallocations • Portability barrier - feature optionality may cause di erent behavior when run against di erent library implementations • Complicates generic code - generic code which accepts vector or basic_string as a template argument must add code to avoid calling reserve(n) when n is less than capacity • Duplicates functionality - basic_string::shrink_to_fit • Inconsistent with vector::reserve which does not shrink-to-fit • Rewording of basic_string::reserve to mirror vector::reserve 4Developers 2018 | Beyond C++17 P0966 string::reserve SHOULD NOT SHRINK MOTIVATION SOLUTION 76
  • 123. • Specializing function templates has proven problematic in practice template<class T> void g(const T&); // function template template<> void g(const int&); // explicit specialization void g(double); // function 4Developers 2018 | Beyond C++17 P0551 THOU SHALT NOT SPECIALIZE STD FUNCTION TEMPLATES! MOTIVATION 77
  • 124. • Specializing function templates has proven problematic in practice template<class T> void g(const T&); // function template template<> void g(const int&); // explicit specialization void g(double); // function The overload set described above would consist of at most only two candidates • The function g(double) • g<T>(const T&), a compiler-synthesized function template specialization of the primary template, with the type T deduced from the type of the call’s argument 4Developers 2018 | Beyond C++17 P0551 THOU SHALT NOT SPECIALIZE STD FUNCTION TEMPLATES! MOTIVATION 77
  • 125. Change wording to • Allow specialization of class templates in namespace std provided that the added declaration depends on at least one user-defined type • Disallow specializations of function templates in namespace std 4Developers 2018 | Beyond C++17 P0551 THOU SHALT NOT SPECIALIZE STD FUNCTION TEMPLATES! SOLUTION 78
  • 126. In a template declaration or a definition, a dependent name that is not a member of the current instantiation is not considered to be a type unless the disambiguation keyword typename is used or unless it was already established as a type name. 4Developers 2018 | Beyond C++17 P0634 DOWN WITH TYPENAME! MOTIVATION 79
  • 127. In a template declaration or a definition, a dependent name that is not a member of the current instantiation is not considered to be a type unless the disambiguation keyword typename is used or unless it was already established as a type name. template<class T, class Allocator = std::allocator<T>> class my_vector { public: using pointer = typename std::allocator_traits<Allocator>::pointer; // ... }; 4Developers 2018 | Beyond C++17 P0634 DOWN WITH TYPENAME! MOTIVATION 79
  • 128. In a template declaration or a definition, a dependent name that is not a member of the current instantiation is not considered to be a type unless the disambiguation keyword typename is used or unless it was already established as a type name. template<class T, class Allocator = std::allocator<T>> class my_vector { public: using pointer = typename std::allocator_traits<Allocator>::pointer; // ... }; but... template<class T> struct D : T::B { // no typename required here }; 4Developers 2018 | Beyond C++17 P0634 DOWN WITH TYPENAME! MOTIVATION 79
  • 129. Makes typename optional in a number of commonplace contexts that are known to only permit type names 4Developers 2018 | Beyond C++17 P0634 DOWN WITH TYPENAME! SOLUTION 80
  • 130. template<class T> typename T::R f(typename T::P); template<class T> struct S { using Ptr = typename PtrTraits<T>::Ptr; typename T::R f(typename T::P p) { return static_cast<typename T::R>(p); } auto g() -> typename S<T*>::Ptr; }; Makes typename optional in a number of commonplace contexts that are known to only permit type names 4Developers 2018 | Beyond C++17 P0634 DOWN WITH TYPENAME! SOLUTION C++17 80
  • 131. template<class T> typename T::R f(typename T::P); template<class T> struct S { using Ptr = typename PtrTraits<T>::Ptr; typename T::R f(typename T::P p) { return static_cast<typename T::R>(p); } auto g() -> typename S<T*>::Ptr; }; template<class T> T::R f(T::P); template<class T> struct S { using Ptr = PtrTraits<T>::Ptr; T::R f(T::P p) { return static_cast<T::R>(p); } auto g() -> S<T*>::Ptr; }; Makes typename optional in a number of commonplace contexts that are known to only permit type names 4Developers 2018 | Beyond C++17 P0634 DOWN WITH TYPENAME! SOLUTION C++17 C++20 80
  • 132. std::shared_ptr<double[]> p = std::make_shared<double[]>(1024); 4Developers 2018 | Beyond C++17 P0674 EXTENDING MAKE_SHARED TO SUPPORT ARRAYS 81
  • 133. tuple t{tuple{1, 2}}; // Deduces tuple<int, int> vector v1{vector{1, 2}}; // C++17 - Deduces vector<vector<int>> vector v2{vector{1, 2}}; // C++20 - Deduces vector<int> 4Developers 2018 | Beyond C++17 P0702 LANGUAGE SUPPORT FOR CONSTRUCTOR TEMPLATE ARGUMENT DEDUCTION 82
  • 134. mutex m; scoped_lock l{adopt_lock, m}; // make this work variant<int, double> v1{3}; variant v2 = v1; // make this work 4Developers 2018 | Beyond C++17 P0739 IMPROVE CLASS TEMPLATE ARGUMENT DEDUCTION IN THE STANDARD LIBRARY 83
  • 135. • Provides the ability to specialize templates on their private and protected nested class-types template<class T> struct trait; class X { class impl; }; template<> struct trait<X::impl>; 4Developers 2018 | Beyond C++17 P0692 ACCESS CHECKING ON SPECIALIZATIONS 84
  • 136. struct X : std::stringstream { /*...*/ }; std::istream_iterator<char> begin(X& x) { return std::istream_iterator<char>(x); } std::istream_iterator<char> end(X& x) { return std::istream_iterator<char>(); } int main() { X x; for (auto&& i : x) { // works in C++20 // ... } } Range-based for loop can handle ranges that have • both member rng.begin()/rng.end() functions • both non-member begin(rng)/end(rng) functions Problem arises when a class has only one of needed member functions (i.e. end() in std::ios_base). 4Developers 2018 | Beyond C++17 P0962 RELAXING THE RANGE-FOR LOOP CUSTOMIZATION POINT FINDING RULES MOTIVATION 85
  • 137. struct X : std::stringstream { /*...*/ }; std::istream_iterator<char> begin(X& x) { return std::istream_iterator<char>(x); } std::istream_iterator<char> end(X& x) { return std::istream_iterator<char>(); } int main() { X x; for (auto&& i : x) { // works in C++20 // ... } } Range-based for loop can handle ranges that have • both member rng.begin()/rng.end() functions • both non-member begin(rng)/end(rng) functions Problem arises when a class has only one of needed member functions (i.e. end() in std::ios_base). Use non-member functions pair if only one member functions is found. 4Developers 2018 | Beyond C++17 P0962 RELAXING THE RANGE-FOR LOOP CUSTOMIZATION POINT FINDING RULES MOTIVATION SOLUTION 85
  • 138. In C++17 we can use structured bindings to bind to class members as long as they are public. 4Developers 2018 | Beyond C++17 P0969 ALLOW STRUCTURES BINDINGS TO ACCESSIBLE MEMBERS MOTIVATION 86
  • 139. class Foo { int a_, b_; void bar(const Foo& other) { auto [x, y] = other; // now OK // ... } }; In C++17 we can use structured bindings to bind to class members as long as they are public. 4Developers 2018 | Beyond C++17 P0969 ALLOW STRUCTURES BINDINGS TO ACCESSIBLE MEMBERS MOTIVATION 86
  • 140. class Foo { int a_, b_; void bar(const Foo& other) { auto [x, y] = other; // now OK // ... } }; class X { int i_; int j_; public: friend void f(); }; void f() { X x; auto [myi, myj] = x; // now OK } In C++17 we can use structured bindings to bind to class members as long as they are public. 4Developers 2018 | Beyond C++17 P0969 ALLOW STRUCTURES BINDINGS TO ACCESSIBLE MEMBERS MOTIVATION 86
  • 141. • POD is a widely-used term • The fundamental problem with POD is that it means a large di erent things to di erent people 4Developers 2018 | Beyond C++17 P0767 POD AND std::is_pod<> IS DEPRECATED 87
  • 142. • POD is a widely-used term • The fundamental problem with POD is that it means a large di erent things to di erent people – Can I memcpy this thing? • std::is_pod<T> or std::is_trivially_copyable<T> are both wrong answers in some cases • the correct answer is is_trivially_copy_constructible_v<T> && is_trivially_copy_assignable_v<T> 4Developers 2018 | Beyond C++17 P0767 POD AND std::is_pod<> IS DEPRECATED 87
  • 143. • POD is a widely-used term • The fundamental problem with POD is that it means a large di erent things to di erent people – Can I memcpy this thing? • std::is_pod<T> or std::is_trivially_copyable<T> are both wrong answers in some cases • the correct answer is is_trivially_copy_constructible_v<T> && is_trivially_copy_assignable_v<T> – POD is a struct that can be parsed by both C and C++ compilers? class Point { public: int x; int y; }; static_assert(std::is_pod_v<Point>); 4Developers 2018 | Beyond C++17 P0767 POD AND std::is_pod<> IS DEPRECATED 87
  • 144. namespace std { typedef enum memory_order { memory_order_relaxed, memory_order_consume, memory_order_acquire, memory_order_release, memory_order_acq_rel, memory_order_seq_cst } memory_order; } namespace std { enum class memory_order : unspecified { relaxed, consume, acquire, release, acq_rel, seq_cst }; inline constexpr memory_order memory_order_relaxed = memory_order::relaxed; inline constexpr memory_order memory_order_consume = memory_order::consume; inline constexpr memory_order memory_order_acquire = memory_order::acquire; inline constexpr memory_order memory_order_release = memory_order::release; inline constexpr memory_order memory_order_acq_rel = memory_order::acq_rel; inline constexpr memory_order memory_order_seq_cst = memory_order::seq_cst; } 4Developers 2018 | Beyond C++17 P0439 MAKE std::memory_order A SCOPED ENUMERATION C++17 C++20 88
  • 145. • <ciso646> header despite being specified to have no e ect is used to determine the library version 4Developers 2018 | Beyond C++17 P0754 <version> MOTIVATION 89
  • 146. • <ciso646> header despite being specified to have no e ect is used to determine the library version • Standardize a dedicated <version> C++ header for this purpose • Contains only the implementation-defined boilerplate comments which specify various properties of the library such as version and copyright notice • Provides a place to put other implementation-defined library meta-information which an environment or human reader might find useful • Ideal place to define the feature test macros 4Developers 2018 | Beyond C++17 P0754 <version> MOTIVATION SOLUTION 89
  • 147.
  • 148.
  • 150. • The first part of compile-time reflection is in wording review void func(int); using func_overload_m = reflexpr(func); using func_m = get_element_t<0, get_overloads_t<func_overload_m>>; using param0_m = get_element_t<0, get_parameters_t<func_m>>; std::cout << get_name_v<get_type_t<param0_m>> << 'n'; // prints "int" • Possible next steps being discussed (P0633) – code synthesis (raw string injection, token sequence injection, programmatic API, metaclasses) – control flow (classic template metaprogramming, heterogenous value metaprogramming, constexpr programming) 4Developers 2018 | Beyond C++17 REFLECTION 93
  • 151. interface IShape { int area() const; void scale_by(double factor); // ... etc. }; 4Developers 2018 | Beyond C++17 REFLECTION - METACLASSES INPUT 94
  • 152. interface IShape { int area() const; void scale_by(double factor); // ... etc. }; class IShape { public: virtual int area() const = 0; virtual void scale_by(double factor) = 0; // ... etc. virtual ~IShape() noexcept { }; // be careful not to write // nonpublic/nonvirtual function // or copy/move function or // data member }; 4Developers 2018 | Beyond C++17 REFLECTION - METACLASSES INPUT OUTPUT 94
  • 153. interface IShape { int area() const; void scale_by(double factor); // ... etc. }; class IShape { public: virtual int area() const = 0; virtual void scale_by(double factor) = 0; // ... etc. virtual ~IShape() noexcept { }; // be careful not to write // nonpublic/nonvirtual function // or copy/move function or // data member }; • Code transformation based on metaclass definition – defaults – constraints, user friendly error reporting – generated functions • Remove the need for Qt moc, C++/CX, C++/WinRT IDL and others 4Developers 2018 | Beyond C++17 REFLECTION - METACLASSES INPUT OUTPUT 94
  • 154. [[contract-attribute modifier identifier: expression]] 4Developers 2018 | Beyond C++17 P0542 CONTRACTS 95
  • 155. [[contract-attribute modifier identifier: expression]] • contract-attribute is one of the – expects - function precondition – ensures - function postcondition – assert - statement verification 4Developers 2018 | Beyond C++17 P0542 CONTRACTS 95
  • 156. [[contract-attribute modifier identifier: expression]] • contract-attribute is one of the – expects - function precondition – ensures - function postcondition – assert - statement verification • Attribute modifier defines assertion level – default - the cost of run-time checking is assumed to be small – audit - the cost of run-time checking is assumed to be large – axiom - formal comments and are not evaluated at run-time – always - cannot be disabled 4Developers 2018 | Beyond C++17 P0542 CONTRACTS 95
  • 157. [[contract-attribute modifier identifier: expression]] • contract-attribute is one of the – expects - function precondition – ensures - function postcondition – assert - statement verification • Attribute modifier defines assertion level – default - the cost of run-time checking is assumed to be small – audit - the cost of run-time checking is assumed to be large – axiom - formal comments and are not evaluated at run-time – always - cannot be disabled • identifier used only for function return value in postconditions 4Developers 2018 | Beyond C++17 P0542 CONTRACTS 95
  • 158. • If a contract violation is detected, a violation handler will be invoked void(const std::contract_violation &); // violation handler signature namespace std { class contract_violation { public: int line_number() const noexcept; const char* file_name() const noexcept; const char* function_name() const noexcept; const char* comment() const noexcept; const char* contract_violation() const noexcept; }; } • Establishing violation handler and setting its argument is implementation defined • Violation continuation mode can be o or on 4Developers 2018 | Beyond C++17 P0542 CONTRACTS 96
  • 159. int f(int x) [[expects audit: x>0]] [[ensures axiom res: res>1]]; void g() { int x = f(5); int y = f(12); [[assert: x+y>0]] //... } 4Developers 2018 | Beyond C++17 P0542 CONTRACTS 97
  • 160. int f(int x) [[expects audit: x>0]] [[ensures axiom res: res>1]]; void g() { int x = f(5); int y = f(12); [[assert: x+y>0]] //... } bool positive(int* p) [[expects: p!=nullptr]] { return *p > 0; } bool g(int* p) [[expects: positive(p)]]; void test() { g(nullptr); // Contract violation } 4Developers 2018 | Beyond C++17 P0542 CONTRACTS 97
  • 161. Redeclaration of a function either has the contract or completely omits it int f(int x) [[expects: x>0]] [[ensures r: r>0]]; 4Developers 2018 | Beyond C++17 P0542 CONTRACTS 98
  • 162. Redeclaration of a function either has the contract or completely omits it int f(int x) [[expects: x>0]] [[ensures r: r>0]]; int f(int x); // OK: no contract int f(int x) [[expects: x>=0]]; // Error: missing ensures and different expects condition int f(int y) [[expects: y>0]] [[ensures res: res>0]]; // OK: same contract even though names differ 4Developers 2018 | Beyond C++17 P0542 CONTRACTS 98
  • 163. using CT = utf8_encoding::character_type; auto tv = make_text_view<utf8_encoding>(u8"Ju00F8erg"); auto it = tv.begin(); assert(*it++ == CT{0x004A}); // 'J' assert(*it++ == CT{0x00F8}); // 'ø' - encoded as UTF-8 using two code units (xC3xB8) assert(*it++ == CT{0x0065}); // 'e' 4Developers 2018 | Beyond C++17 P0244 TEXT_VIEW: CHARACTER ENCODING AND CODE POINT ENUMERATION LIBRARY 99
  • 164. using CT = utf8_encoding::character_type; auto tv = make_text_view<utf8_encoding>(u8"Ju00F8erg"); auto it = tv.begin(); assert(*it++ == CT{0x004A}); // 'J' assert(*it++ == CT{0x00F8}); // 'ø' - encoded as UTF-8 using two code units (xC3xB8) assert(*it++ == CT{0x0065}); // 'e' it = std::find(tv.begin(), tv.end(), CT{0x00F8}); assert(it != tv.end()); 4Developers 2018 | Beyond C++17 P0244 TEXT_VIEW: CHARACTER ENCODING AND CODE POINT ENUMERATION LIBRARY 99
  • 165. using CT = utf8_encoding::character_type; auto tv = make_text_view<utf8_encoding>(u8"Ju00F8erg"); auto it = tv.begin(); assert(*it++ == CT{0x004A}); // 'J' assert(*it++ == CT{0x00F8}); // 'ø' - encoded as UTF-8 using two code units (xC3xB8) assert(*it++ == CT{0x0065}); // 'e' it = std::find(tv.begin(), tv.end(), CT{0x00F8}); assert(it != tv.end()); auto base_it = it.base_range().begin(); assert(*base_it++ == 'xC3'); assert(*base_it++ == 'xB8'); assert(base_it == it.base_range().end()); 4Developers 2018 | Beyond C++17 P0244 TEXT_VIEW: CHARACTER ENCODING AND CODE POINT ENUMERATION LIBRARY 99
  • 166. string message = fmt::format("The answer is {}.", 42); fmt::format("{:*^30}", "centered"); // ***********centered*********** 4Developers 2018 | Beyond C++17 P0645 TEXT FORMATTING 100
  • 167. • async(...) • for_each(...) • define_task_block(...) • invoke(...) • your_favorite_control_structure(...) • OS threads • Thread pool schedulers • OpenMP runtime • SIMD vector units • GPU runtime • Fibers 4Developers 2018 | Beyond C++17 EXECUTORS: PURPOSE DIVERSE CONTROL STRUCTURES DIVERSE EXECUTION RESOURCES Executors as an answer to mutliplicative explosion. 101
  • 168. for_each(par.on(ex), begin, end, function); 4Developers 2018 | Beyond C++17 EXECUTORS: PURPOSE CONTROL WHERE/HOW EXECUTION SHOULD OCCUR 102
  • 169. for_each(par.on(ex), begin, end, function); async(executor, function); 4Developers 2018 | Beyond C++17 EXECUTORS: PURPOSE CONTROL WHERE/HOW EXECUTION SHOULD OCCUR CONTROL RELATIONSHIP WITH CALLING THREAD 102
  • 170. for_each(par.on(ex), begin, end, function); async(executor, function); for_each(P.on(executor), ...); async(executor, ...); invoke(executor, ...); my_asynchronous_op(executor, ...); 4Developers 2018 | Beyond C++17 EXECUTORS: PURPOSE CONTROL WHERE/HOW EXECUTION SHOULD OCCUR CONTROL RELATIONSHIP WITH CALLING THREAD UNIFORM INTERFACE FOR EXECUTION SEMANTICS ACROSS CONTROL STRUCTURES 102
  • 171. Executors are handles to underlying execution contexts 4Developers 2018 | Beyond C++17 EXECUTORS: DESIGN 103
  • 172. Executors are handles to underlying execution contexts Execution contexts manage lifetime of units of work called execution agents (e.g. static_thread_pool) 4Developers 2018 | Beyond C++17 EXECUTORS: DESIGN 103
  • 173. Executors are handles to underlying execution contexts Execution contexts manage lifetime of units of work called execution agents (e.g. static_thread_pool) Executors, in some cases, may be self-contexts (e.g. inline_executor) 4Developers 2018 | Beyond C++17 EXECUTORS: DESIGN 103
  • 174. ONE-WAY TWO-WAY THEN Single execute() twoway_execute() then_execute() Bulk bulk_execute() bulk_twoway_execute() bulk_then_execute() 4Developers 2018 | Beyond C++17 EXECUTORS: DESIGN 104
  • 175. ONE-WAY TWO-WAY THEN Single execute() twoway_execute() then_execute() Bulk bulk_execute() bulk_twoway_execute() bulk_then_execute() auto my_task = []{...}; ex.execute(my_task); • Creates a single execution agent • Fire-And-Forget 4Developers 2018 | Beyond C++17 EXECUTORS: DESIGN EXECUTE() 105
  • 176. ONE-WAY TWO-WAY THEN Single execute() twoway_execute() then_execute() Bulk bulk_execute() bulk_twoway_execute() bulk_then_execute() auto my_task = []{...}; auto future = ex.twoway_execute(my_task); • Creates a single execution agent • Returns a future 4Developers 2018 | Beyond C++17 EXECUTORS: DESIGN TWOWAY_EXECUTE() 106
  • 177. ONE-WAY TWO-WAY THEN Single execute() twoway_execute() then_execute() Bulk bulk_execute() bulk_twoway_execute() bulk_then_execute() future<int> predecessor = ...; auto my_task = [](int &pred){...}; auto future = ex.then_execute(my_task, predecessor); • Creates a single execution agent • Depends on a predecessor future • Returns a future 4Developers 2018 | Beyond C++17 EXECUTORS: DESIGN THEN_EXECUTE() 107
  • 178. ONE-WAY TWO-WAY THEN Single execute() twoway_execute() then_execute() Bulk bulk_execute() bulk_twoway_execute() bulk_then_execute() auto my_task = [](size_t idx, int& shared){...}; auto shared_factory = []{ return 42; }; ex.bulk_execute(my_task, n, shared_factory); • Creates multiple execution agents • Fire-And-Forget 4Developers 2018 | Beyond C++17 EXECUTORS: DESIGN BULK_EXECUTE() 108
  • 179. ONE-WAY TWO-WAY THEN Single execute() twoway_execute() then_execute() Bulk bulk_execute() bulk_twoway_execute() bulk_then_execute() auto my_task = [](size_t idx, int& result, int& shared){...}; auto result_factory = []{ return 7; } auto shared_factory = []{ return 42; }; auto future = ex.bulk_twoway_execute(my_task, n, result_factory, shared_factory); • Creates multiple execution agents • Returns a future 4Developers 2018 | Beyond C++17 EXECUTORS: DESIGN BULK_TWOWAY_EXECUTE() 109
  • 180. ONE-WAY TWO-WAY THEN Single execute() twoway_execute() then_execute() Bulk bulk_execute() bulk_twoway_execute() bulk_then_execute() future<int> predecessor = ...; auto my_task = [](size_t idx, int& pred, int& result, int& shared){...}; auto result_factory = []{ return 7; } auto shared_factory = []{ return 42; }; auto future = ex.bulk_then_execute(my_task, n, predecessor, result_factory, shared_factory); • Creates multiple execution agents • Depends on a predecessor future • Returns a future 4Developers 2018 | Beyond C++17 EXECUTORS: DESIGN BULK_THEN_EXECUTE() 110
  • 181. Executor properties are objects associated with executors that imply a behavior (e.g. never_blocking, bulk, continuation) • Allow generic code to reason about executor behavior in a uniform way • Enable executor adaptations 4Developers 2018 | Beyond C++17 EXECUTORS: PROPERTY-BASED DESIGN 111
  • 182. Executor properties are manipulated via customization points to express requirements and preferences • require(ex, props...) - a binding requirement for particular properties • prefer(ex, props...) - a non-binding requirement for particular properties • Return another executor 4Developers 2018 | Beyond C++17 EXECUTORS: CUSTOMIZATION POINTS 112
  • 183. auto non_blocking_ex = execution::require(ex, never_blocking); non_blocking_ex.execute(task); • May fail if ex only supports always_blocking • May fail if ex.require(user_property_t) = delete 4Developers 2018 | Beyond C++17 EXECUTORS: execution::require() 113
  • 184. auto best_ex = execution::prefer(ex, continuation); best_ex.execute(task); • Always compiles • prefer() simply calls require() when possible 4Developers 2018 | Beyond C++17 EXECUTORS: execution::prefer() 114
  • 185. int p = execution::query(ex, priority); • Introspects executor properties • Can inspect the result of execution::prefer(ex, props...) 4Developers 2018 | Beyond C++17 EXECUTORS: execution::query() 115
  • 186. struct inline_executor { template<class F> void execute(F f) const { try { f(); } catch(...) { std::terminate(); } } const inline_executor& context() const noexcept { return *this; } bool operator==(const inline_executor&) const { return true; } bool operator!=(const inline_executor&) const { return false; } }; • Executes work immediately, “inline” 4Developers 2018 | Beyond C++17 EXECUTORS: SIMPLEST COMPLETE EXECUTOR 116
  • 187. struct static_thread_pool_executor { // execution functions template<class F> void execute(F&& f) const; // ... static_thread_pool& context() const noexcept; // require overloads static_thread_pool_executor require(oneway_t) const; // ... // adapting require overloads adapted-executor require(never_blocking_t) const; // ... // equality bool operator==(const static_thread_pool&); bool operator!=(const static_thread_pool&); }; 4Developers 2018 | Beyond C++17 EXECUTORS: static_thread_pool EXECUTOR 117
  • 188. namespace custom { // a custom property struct logging { bool on; }; // a fancy logging executor template<class Executor> class logging_executor { ... }; // adapts executors without native logging property template<class Executor> std::enable_if_t<!has_require_members_v<Executor, logging>, logging_executor<Executor>> require(Executor ex, logging l) { return logging_executor<Executor>(ex, l); } } // custom 4Developers 2018 | Beyond C++17 EXECUTORS: ADAPTING AN EXECUTOR 118