SlideShare a Scribd company logo
‹ E ,7FRPPXQLFDWLRQFRP 

1LFRODL 0 -RVXWWLV
,7FRPPXQLFDWLRQFRP

0RGHUQ 

‹ E ,7FRPPXQLFDWLRQFRP 

1LFRODL 0 -RVXWWLV
‡ ,QGHSHQGHQW FRQVXOWDQW
± FRQWLQXRXVO OHDUQLQJ VLQFH 
‡ 6VWHPV $UFKLWHFW 7HFKQLFDO 0DQDJHU
± ILQDQFH PDQXIDFWXULQJ DXWRPRELOH
WHOHFRPPXQLFDWLRQ
‡ 7RSLFV
± 
± 62$ 6HUYLFH 2ULHQWHG $UFKLWHFWXUH
± 7HFKQLFDO 3URMHFW 0DQDJHPHQW
± 3ULYDF FRQWULEXWRU RI (QLJPDLO
Nico Josuttis C++17
@CodeHard 1
‹ E ,7FRPPXQLFDWLRQFRP 

 'LVFODLPHU
‡  LV EUDQG QHZ
± /LPLWHG H[SHULPHQWDO FRPSLOHU VXSSRUW
± :H ZLOO ILQG IODZV LQ 
‡ 7KHVH VOLGHV DUH EUDQG QHZ
± RX ZLOO ILQG IODZV
± 6RPH IHDWXUHV DUH SUREDEO PLVVLQJ
± 6RPH IHDWXUHV DUH QRW ZHOO HQRXJK
GHVFULEHG
± , VWLOO OHDUQ
‡ )HHGEDFN ZHOFRPH
‹ E ,7FRPPXQLFDWLRQFRP 


0RGHUQ 
Nico Josuttis C++17
@CodeHard 2
‹ E ,7FRPPXQLFDWLRQFRP 

 7LPHIUDPH
KWWSLVRFSSRUJVWGVWDWXV
PHGLXP
0RGHUQ 
‹ E ,7FRPPXQLFDWLRQFRP 

 7LPHIUDPH
KWWSLVRFSSRUJVWGVWDWXV
Nico Josuttis C++17
@CodeHard 3
‹ E ,7FRPPXQLFDWLRQFRP 

 6WDQGDUGL]DWLRQ
‡ E ,62
± IRUPDO YRWHV E QDWLRQDO ERGLHV HJ
‡ $16, IRU 86$
‡ ',1 IRU *HUPDQ
‡ (PDLO UHIOHFWRUV IRU GLIIHUHQW ZRUNLQJ DQG VWXG JURXSV
± FRUH OLEUDU FRQFXUUHQF 
‡  RU  MRLQHG PHHWLQJV RI $16, DQG ,62 SHU HDU
± RSHQ WR WKH SXEOLF
‡ (YHUERG LV ZHOFRPH WR
± MRLQ PHHWLQJV
± SURSRVH QHZ IHDWXUHV
± GLVFXVV
‡ ,QIRUPDO ZHE VLWH KWWSLVRFSSRUJVWG
‡ )RUPDO ZHE VLWH KWWSZZZRSHQVWGRUJMWFVFZJ
‹ E ,7FRPPXQLFDWLRQFRP 

 :RUNLQJ DQG 6WXG *URXSV
KWWSLVRFSSRUJVWGWKHFRPPLWWHH
Nico Josuttis C++17
@CodeHard 4
‹ E ,7FRPPXQLFDWLRQFRP 

$YDLODELOLW RI WKH  6WDQGDUG
‡ 'RFXPHQW QXPEHU
± ,62,( 
‡ $YDLODEOH DW QDWLRQV ERGLHV $16, ',1
DQG ,1,76
‡ 3ULFHV YDU
± ,62,(   PHPEHUV
± ',1   ¼
± %6 ,62,(  … PHPEHUV …
± 
‡ 9HUVLRQ FORVH WR ILQDO YHUVLRQ DV GRFXPHQW 1SGI
IRU IUHH DW
± KWWSVZJOLQNQ
‡ KWWSZZZRSHQVWGRUJMWFVFZJGRFVSDSHUVQSGI
‹ E ,7FRPPXQLFDWLRQFRP 

 'RFXPHQWV DQG 3DSHUV
‡ $OO ZRUNLQJ GRFXPHQWV DUH SXEOLF DQG DYDLODEOH
± KWWSVZJOLQN
‡ 'LIIHUHQW SDSHU QXPEHUV VFKHPHV
± 1xxxx
± 3yyyy5 3yyyy5 
‡ ,VVXH /LVWV
± FZJxxx HZJxxx
± OZJxxx OHZJxxx IVxxx
‡ )RU H[DPSOH
± KWWSVZJOLQNQ  GUDIW VWDQGDUG
± KWWSVZJOLQNSU 3URSRVHG ZRUGLQJ IRU 6WUXFWXUHG %LQGLQJV
± KWWSVZJOLQNOZJ ,VVXH IRU std::is_aggregate
Nico Josuttis C++17
@CodeHard 5
‹ E ,7FRPPXQLFDWLRQFRP 

 6XSSRUW
‡ JFFJ 
± VXSSRUWV DOO ODQJXDJH IHDWXUHV
± VXSSRUWV VHYHUDO OLEUDU IHDWXUHV
± 2SWLRQ -std=c++17
‡ ODQJ 
± VXSSRUWV DOO ODQJXDJH IHDWXUHV FODQJ  DQG  PDQ
± 2SWLRQ -std=c++0z RU -std:c++17
‡ 9LVXDO 6WXGLR 
± RPSLOHU YHUVLRQ !  ELQDU FRPSDWLEOH WR 96
± VXSSRUWV VRPH ODQJXDJH IHDWXUHV
± IUHTXHQW XSGDWHV
± 2SWLRQ /std:c++latest RU /std:c++17
‹ E ,7FRPPXQLFDWLRQFRP 

 DQG 9LVXDO 
‡ 9LVXDO 6WXGLR  9LVXDO  DGDSWV  PRUH DQG PRUH
± 6RPH  IHDWXUHV LQ 96
± 0RUH DQG PRUH  IHDWXUHV LQ 96
‡ 96 QRZ KDV FRPSLOHU VZLWFK IRU  6WDQGDUG YHUVLRQ
± /std:c++14 /std:c++17 /std:c++latest
‡ 96 LV ELQDU FRPSDWLEOH WR 96
‡ 96  KDV PXOWLSOH IODYRUV FRPSLOHU YHUVLRQ[
‡ 5HOHDVH FKDQQHO
‡ 96 XSGDWH     VLJQLILFDQWO PRUH
‡ 3UHYLHZ FKDQQHO
‡ 96 XSGDWH  SUHYLHZ  VLQFH 6HS 
‡ 6HH
± KWWSVEORJVPVGQPLFURVRIWFRPYFEORJFIHDWXUHVLQYV
Nico Josuttis C++17
@CodeHard 6
‹ E ,7FRPPXQLFDWLRQFRP 

 ZLWK J
‡ $V RI

‹ E ,7FRPPXQLFDWLRQFRP 

JFODQJ 2QOLQH RPSLOHU
KWWSPHOSRQRUJZDQGER[
XVHV 6HUYHU6LGH (YHQWV
66(
VR RXU ILUHZDOO
VKRXOG QRW EORFN
text/event-stream
Nico Josuttis C++17
@CodeHard 7
‹ E ,7FRPPXQLFDWLRQFRP 

 ZLWK
96
‡ $V RI

 RUH
/LE !
96[
96
‹ E ,7FRPPXQLFDWLRQFRP 

 6XSSRUW E 9LVXDO 6WXGLR  DQG 
‡ 9LVXDO 6WXGLR 
± 6XSSRUW IRU LQFRPSOHWH WSHV LQ YHFWRU OLVW DQG IRUZDUGBOLVW
‡ 9LVXDO 6WXGLR 
± JOREDO VWGVL]H
VWGHPSW
VWGGDWD
± VWGLQYRNH
± VWGXQFDXJKWBH[FHSWLRQV
± VWGERROBFRQVWDQW VWGYRLGBW
‡ 9LVXDO 6WXGLR  8SGDWH 
± JOREDO VWGDVBFRQVW
± 7SH WUDLWV VXIIL[ BY
± VWGVFRSHGBORFN
± IORRU
FHLO
URXQG
DEV
IRU FKURQR!
± 7SH WUDLWV FRQMXQFWLRQ! GLVMXQFWLRQ! QHJDWLRQ!
Nico Josuttis C++17
@CodeHard 8
‹ E ,7FRPPXQLFDWLRQFRP 

/DQJXDJH )HDWXUHV

‹ E ,7FRPPXQLFDWLRQFRP 

 6WUXFWXUHG %LQGLQJV
‡ ,QLWLDOL]H PXOWLSOH LGHQWLILHUVQDPHV IURP
± FODVVVWUXFWXQLRQ REMHFWV
± VWGSDLU! VWGWXSOH! VWGDUUD!
± UDZ DUUDV
‡ 7SHV DUH GHGXFHG IURP PHPEHUVHOHPHQWV
struct MyStruct {
int i;
std::string s;
};
MyStruct ms;

auto [u,v] = ms;  FUHDWH LPSOLFLW HQWLW ZKHUH u v UHSUHVHQW i s
std::cout  u  ' '  SULQW PHPEHUV DVVLJQHG WR XY@
 v  'n';
(TXLYDOHQW WR
auto e = ms;
std::cout  e.i  ' '
 e.s  'n';
Nico Josuttis C++17
@CodeHard 9
‹ E ,7FRPPXQLFDWLRQFRP 

 8VLQJ 6WUXFWXUHG %LQGLQJV
std::mapstd::string, double coll;
 
for (const auto elem : coll) {  HOHPV DUH VWGSDLUFRQVW VWGVWULQJ GRXEOH!
std::cout  elem.first  : 
 elem.second  'n';
}
 VLQFH 
for (const auto [key,val] : coll) {  DFFHVV HOHPV E UHDGRQO UHIHUHQFH
std::cout  key  : 
 val  'n';
}
for (auto [key,val] : coll) {  DFFHVV HOHPV E UHIHUHQFH
if (key != ignore) {
val *= 2;
}
}
‹ E ,7FRPPXQLFDWLRQFRP 

 6WUXFWXUHG %LQGLQJV IRU 5HWXUQ 9DOXHV
struct MyStruct {
int i;
std::string s;
};
MyStruct f1();
auto [u,v] = f1();  XY KDYH WSH DQG YDOXH RI PHPEHUV RI UHWXUQHG REMHFW
auto [w] = f1();  (UURU QXPEHU RI HOHPHQWV GRHV QRW ILW
auto f2() - int()[2];  I
UHWXUQV UHIHUHQFH WR LQW DUUD
auto [x, y] = f2();  [ DQG  DUH intV LQLWLDOL]HG E HOHPV RI UHWXUQHG DUUD
std::arrayint,4 f3();
auto [i,j,k,l] = f3();  LMNO QDPH WKH  HOHPHQWV RI WKH FRSLHG UHWXUQ YDOXH
std::tuplechar,float,std::string f4();
auto [a,b,c] = f4();  DEF KDYH WSHV DQG YDOXHV RI UHWXUQHG WXSOH
Nico Josuttis C++17
@CodeHard 10
‹ E ,7FRPPXQLFDWLRQFRP 

 6WUXFWXUHG %LQGLQJV DQG 4XDOLILHUV
‡ 6WUXFWXUHG ELQGLQJV GHFODUDWLRQ FDQ KDYH WKH XVXDO
TXDOLILHUV  const alignas 
± $OZDV DSSO WR WKH LPSOLFLWO FUHDWHG HQWLW DV D ZKROH
int a[] = { 7, 11 };

auto [ r, s ] = a;  U DQG V DUH LGHQWLILHV WR HOHPHQWV RI D UHIHUHQFH WR D
r = 42;  PRGLI ILUVW HOHPHQW LQ D
std::cout  a[0]  'n';  SULQWV 
struct MyStruct {
std::string name;
int val;
};
MyStruct ms = {Jim, 42};
auto [n,v] = ms;  Q DQG Y DUH HOHPHQWV RI UHIHUHQFH WR PV
std::cout  name:   ms.name  'n';  SULQWV -LP
std::string s = std::move(n);  PRYH PVQDPH WR V
MyStruct f1();
const auto [nm,vl] = f1();  H[WHQGV OLIHWLPH RI UHWXUQHG WHPSRUDU
alignas(16) auto[s,i] = f1();  HQWLW LV EWH DOLJQHG QRW L
‹ E ,7FRPPXQLFDWLRQFRP 

 $GGUHVVHV RI 6WUXFWXUHG %LQGLQJV (OHPHQWV
‡ 6WUXFWXUHG ELQGLQJ GHFODUDWLRQV JXDUDQWHH WKDW WKH REMHFW
ZKRVH PHPEHUV DUH GHQRWHG DUH NHSW WRJHWKHU
auto f() - int ()[2];
auto [x, y] = f();
assert(x + 1 == y);  2.
struct S {  FODVV ZLWK VWDQGDUGODRXW
int no;
double price;
std::string msg;
};
auto [n,p,s] = S{};
assert(((S*)n)-msg == s);  2.
Nico Josuttis C++17
@CodeHard 11
‹ E ,7FRPPXQLFDWLRQFRP 

6WUXFWXUHV %LQGLQJV 0LJKW 1RW 'HFD 0HPEHUV
‡ auto GRHV QRW GHFD VWUXFWXUHG ELQGLQJV
± EHFDXVH LW DSSOLHV WR WKH REMHFW DV D ZKROH
struct S {
int x[3];
int y[3];
};
S s1{};  LQLWLDOL]H DOO PHPEHU DUUDV ZLWK HOHPHQWV EHLQJ 

auto [a, b] = s1;  a DQG b KDYH VDPH PHPEHU WSHV
std::is_samedecltype(a), int[3]::value  LHOGV true
for (int elem : a) {  2. a LV VWLOO DUUD
std::cout  elem  'n';
}
auto p = a;
std::is_samedecltype(p), int*::value  LHOGV true
for (int elem : p) {  (5525 p LV QR DUUD

}
(TXLYDOHQW WR
auto e = s1;
auto a = e.x;
auto b = e.y;
‹ E ,7FRPPXQLFDWLRQFRP 

 6WUXFWXUHG %LQGLQJV YLD 7XSOHOLNH $3,V
class Customer {

public:
std::string getFirst() const { return first; }
std::string getLast() const { return last; }
long getValue() const { return val; }
};
#include utility  IRU WXSOHOLNH $3,
 SURYLGH D WXSOHOLNH $3, IRU FODVV XVWRPHU IRU VWUXFWXUHG ELQGLQJV
template
struct std::tuple_sizeCustomer {
static constexpr int value = 3;  ZH KDYH  DWWULEXWHV
};
template
struct std::tuple_element2, Customer {
using type = long;  ODVW DWWULEXWH LV D ORQJ
};
templatestd::size_t Idx
struct std::tuple_elementIdx, Customer {
using type = std::string;  WKH RWKHU DWWULEXWHV DUH VWULQJV
};
 GHILQH VSHFLILF JHWWHUV
templateint auto get(const Customer c);
template auto get0(const Customer c) { return c.getFirst(); }
template auto get1(const Customer c) { return c.getLast(); }
template auto get2(const Customer c) { return c.getValue(); }
Customer c(Tim, Lee, 42);
auto [f,l,v] = c;
 SULQWV 7LP /HH  
std::cout  f  ' '
 l  : 
 v  'n';
$OO IXOO VSHFLDOL]DWLRQV RI
IXQFWLRQ WHPSODWHV KDYH
WR XVH WKH VDPH VLJQDWXUH
LQFOXGLQJ WKH H[DFW VDPH
UHWXUQ WSH auto
Nico Josuttis C++17
@CodeHard 12
‹ E ,7FRPPXQLFDWLRQFRP 

 if ZLWK ,QLWLDOL]HUV 1HHG 1DPHV
{
std::lock_guardstd::mutex lg(mv);
if (!v.empty()) {
std::cout  v.front()  'n';
}
}
if (std::lock_guardstd::mutex lg(mx); !v.empty()) {  2.
std::cout  v.front()  'n';
}
if (std::lock_guard lg{mx}; !v.empty()) {  2. GXH WR FODVV WHPSODWH DUJ GHGXFWLRQ
std::cout  v.front()  'n';
}
if (std::lock_guardstd::mutex(mx); !v.empty()) {  (5525 ORFN HQGV EHIRUH 
;

std::cout  v.front()  'n';
}
if (std::lock_guard{mx}; !v.empty()) {  (5525 ORFN HQGV EHIRUH 
;

std::cout  v.front()  'n';
}
if (std::lock_guardstd::mutex _(mx); !v.empty()) {  2. EXW
std::cout  v.front()  'n';
}
‹ E ,7FRPPXQLFDWLRQFRP 

 if DQG switch ZLWK ,QLWLDOL]HUV
‡ 1HZ DGGLWLRQDO VQWD[ IRU if DQG switch
if (init; condition)
switch (init; condition)
if (status s = check(); s != status::ok) {
return s;
}
if (std::lock_guardstd::mutex lg(mx);
!v.empty()) {
std::cout  v.front()  'n';
}
switch (Foo gadget(args);
auto s = gadget.status()) {
case OK: gadget.zip(); break;
case Bad: throw BadFoo(s.message());
}
{
status s = check();
if (s != status::ok) {
return s;
}
}
{
std::lock_guardstd::mutex lg(mv);
if (!v.empty()) {
std::cout  v.front()  'n';
}
}
{
Foo gadget(args);
switch (auto s = gadget.status()) {
case OK: gadget.zip(); break;
case Bad: throw BadFoo(s.message());
}
}
Nico Josuttis C++17
@CodeHard 13
‹ E ,7FRPPXQLFDWLRQFRP 

 6WUXFWXUHG %LQGLQJV DQG if ZLWK ,QLWLDOL]HU
‡ RPELQLQJ
± ,QLWLDOL]H PXOWLSOH REMHFWV E PXOWLSOH UHWXUQ YDOXHV
± XVLQJ WKH VXSSOHPHQWDU LQLWLDOL]DWLRQ VQWD[ IRU if
‡ )RU
std::mapstd::string, int coll;
RX FDQ UHSODFH
‡ E
if (auto [pos,ok] = coll.insert({new,42}); !ok) {
 LI LQVHUW IDLOHG KDQGOH HUURU XVLQJ LWHUDWRU pos IRU HOHP DOUHDG WKHUH
const auto [key,val] = *pos;
std::cout  ''  key   exists with key:   val  'n';
}
auto ret = coll.insert({new,42});
if (!ret.second){
 LI LQVHUW IDLOHG SULQW ZK XVLQJ LWHUDWRU ret.first IRU HOHP DOUHDG WKHUH
const auto elem = *(ret.first);
std::cout  ''  elem.first   exists with key: 
 elem.second  'n';
}
2U LQ RQH H[SUHVVLRQ
ret.first-second
‹ E ,7FRPPXQLFDWLRQFRP 

 if ZLWK ,QLWLDOL]HUV 1HHG 1DPHV
‡ $Q WHPSRUDU ZLWKRXW D QDPH LQ WKH LQLWLDOL]DWLRQ
RQO H[LVWV WKHUH QRW LQ WKH ZKROH VWDWHPHQW
‡ 6DPH DV ZLWK for ORRSV
if (std::lock_guardstd::mutex lg(mx); !v.empty()) {  2.
std::cout  v.front()  'n';
}
if (std::lock_guardstd::mutex _(mx); !v.empty()) {  2. EXW
std::cout  v.front()  'n';
}
if (std::lock_guardstd::mutex(mx); !v.empty()) {  (5525 ORFN HQGV EHIRUH 
;

std::cout  v.front()  'n';
}
if (std::lock_guard lg(mx); !v.empty()) {  2. GXH WR FODVV WHPSODWH DUJ GHGXFWLRQ
std::cout  v.front()  'n';
}
Nico Josuttis C++17
@CodeHard 14
‹ E ,7FRPPXQLFDWLRQFRP 

 if ZLWK ,QLWLDOL]HUV 0DNHV +LGGHQ KHFNV 9LVLEOH
‡ %H FDUHIXO ZKHQ FRQYHUWLQJ H[LVWLQJ if ZLWK LQLWLDOL]DWLRQ
‡ 1DLYH PRGLILFDWLRQV WR XVH QHZ IHDWXUH
void f(const Expression* expr)
{
if (const auto* unaryExpr = expr-AsUnaryExpression()) {
if (unaryExpr-Kind() == TokenKind::Plus) {

}
}
}
void f(const Expression* expr)
{
if (const auto* unaryExpr = expr-AsUnaryExpression();
unaryExpr-Kind() == TokenKind::Plus) {

}
}
PLVVLQJ LPSOLFLW
if (unaryExpr)
7KDQNV WR -RQDWKDQ DYHV IRU WKLV H[DPSOH
‹ E ,7FRPPXQLFDWLRQFRP 

 ,QOLQH 9DULDEOHV
‡ 6WDWLF YDULDEOHV PDUNHG ZLWK inline FRXQW DV GHILQLWLRQV
± *XDUDQWHHG WR H[LVW RQO RQFH LQ WKH SURJUDP
± 1R QHHG IRU 33 ILOHV WR GHILQH VWDWLFJOREDO REMHFWV
class Monitor {
public:
Monitor() {  }
void log(const std::string msg) {  }
}
 'HFODUH THE JOREDO PRQLWRU LQ WKH KHDGHU ILOH
  PLJKW EH LQFOXGHG E PXOWLSOH WUDQVODWLRQ XQLWV
inline Monitor progMonitor
PRQLWRUKSS
#include monitor.hpp

progMonitor.log(main());
#include monitor.hpp

progMonitor.log(init());

Nico Josuttis C++17
@CodeHard 15
‹ E ,7FRPPXQLFDWLRQFRP 

 ,QOLQH 9DULDEOHV
‡ 6WDWLF YDULDEOHV PDUNHG ZLWK inline FRXQW DV GHILQLWLRQV
± *XDUDQWHHG WR H[LVW RQO RQFH LQ WKH SURJUDP
‡ HYHQ LI LQFOXGHG PXOWLSOH WLPHV LQ PXOWLSOH WUDQVODWLRQ XQLWV
± 1R QHHG IRU 33 ILOHV WR GHILQH VWDWLFJOREDO REMHFWV
class C
{
private:
static inline bool lg = false;
public:
static void log (bool b) {
lg = b;
}
C() {
if (lg) std::cout  C::C()n;
}

};
#include c.hpp
int main()
{
C::log(true);
C c1;

}
FKSS
#include c.hpp
void foo()
{
C c2;

}
‹ E ,7FRPPXQLFDWLRQFRP 

 $ +HDGHU2QO ::new 7UDFNHU
class TrackNew
{
private:
inline static int numMalloc = 0;  QXPEHU RI QHZ RU QHZ@ FDOOV
inline static long sumSize = 0;  EWHV DOORFDWHG VR IDU
inline static bool doTrace = false;  WUDFLQJ HQDEOHG
public:
static void trace(bool b) {  HQDEOHGLVDEOH WUDFLQJ
doTrace = b;
}
static void status() {  SULQW FXUUHQW VWDWH
std::cerr  numMalloc   mallocs for   sumSize   Bytes  'n';
}
static void* allocate(std::size_t size, const char* call) {  LPSOHPHQWDWLRQ RI WUDFNHG DOORFDWLRQ
++numMalloc;
sumSize += size
if (doTrace) 
return std::malloc(size);
}
};
inline void* operator new (std::size_t size) {
return TrackNew::allocate(size, ::new);
}
inline void* operator new[] (std::size_t size) {
return TrackNew::allocate(size, ::new[]);
}
 LQFOXGLQJ WKH KHDGHU LV HQRXJK
#include tracknew.hpp
int main()
{
 RSWLRQDOO
TrackNew::trace(true);

TrackNew::status();
}
Nico Josuttis C++17
@CodeHard 16
‹ E ,7FRPPXQLFDWLRQFRP 

 ,QOLQH 9DULDEOHV
‡ PLJKW EH LQLWLDOL]HG EHIRUH PDLQ
RU EHIRUH ILUVW XVH
‡ FDQ EH thread_local
‡ constexpr LPSOLHV inline
class Monitor {
public:
Monitor() {  }
void log(const std::string msg) {  }
}
 'HFODUH THE JOREDO PRQLWRU LQ WKH KHDGHU ILOH
  PLJKW EH LQFOXGHG E PXOWLSOH WUDQVODWLRQ XQLWV
inline thread_local Monitor threadLocalMonitor
PRQLWRUKSS
‹ E ,7FRPPXQLFDWLRQFRP 

 static constexpr 'DWD 0HPEHUV DUH inline
‡ 6WDWLF constexpr GDWD PHPEHUV DUH inline VLQFH 
± 'HFODUDWLRQV DUH GHILQLWLRQV
± %HIRUH  WKH GHILQLWLRQV RIWHQ ZHUH QRW QHFHVVDU
‡ 2SWLPL]HG DZD
‡ 'HILQLWLRQ QRW QHHGHG HJ SDVVHG E YDOXH
struct A {
static constexpr int n = 5;   GHFODUDWLRQ
};
std::cout  A::n;  2. ostream::operator(int) JHWV A::n E YDOXH
int inc(const int i);  QRWH WDNHV DUJXPHQW E UHIHUHQFH
std::cout  inc(A::n);  PD IDLO ZLWKRXW GHILQLWLRQ 2. ZLWK JFF ±2 9LVXDO6WXGLR
const int* p = n;  SUREDEO IDLOV ZLWKRXW GHILQLWLRQ 2. ZLWK 9LVXDO6WXGLR
SRVVLEOH GHILQLWLRQ LQ RQH WUDQVODWLRQ XQLW
constexpr int A::n;
Nico Josuttis C++17
@CodeHard 17
‹ E ,7FRPPXQLFDWLRQFRP 

 static constexpr 'DWD 0HPEHUV DUH inline
‡ 6WDWLF constexpr GDWD PHPEHUV DUH inline VLQFH 
± 'HFODUDWLRQV DUH GHILQLWLRQV
± %HIRUH  WKH GHILQLWLRQV RIWHQ ZHUH QRW QHFHVVDU
‡ 2SWLPL]HG DZD
‡ 'HILQLWLRQ QRW QHHGHG HJ SDVVHG E YDOXH
struct A {
static constexpr int n = 5;   GHFODUDWLRQ
 VLQFH  LQOLQH GHILQLWLRQ
};
std::cout  A::n;  2. ostream::operator(int) JHWV A::n E YDOXH
int inc(const int i);  QRWH WDNHV DUJXPHQW E UHIHUHQFH
std::cout  inc(A::n);  PD IDLO ZLWKRXW GHILQLWLRQ 2. ZLWK JFF ±2 9LVXDO6WXGLR
const int* p = n;  SUREDEO IDLOV ZLWKRXW GHILQLWLRQ 2. ZLWK 9LVXDO6WXGLR
SRVVLEOH GHILQLWLRQ LQ RQH WUDQVODWLRQ XQLW
constexpr int A::n;   GHILQLWLRQ
 VLQFH  UHGXQGDQW GHFODUDWLRQ GHSUHFDWHG
‡ $OZDV 2. VLQFH 
‹ E ,7FRPPXQLFDWLRQFRP 

struct Data {
std::string name;
double value;
};
struct Dv : Data {
bool used;
void print() const;
};
Dv u;  2. EXW valuedone ZLWK XQGHILQHG YDOXHV
Dv z{};  2. valuedone ZLWK 0false
bool b = std::is_aggregateAggr::value;  WUXH
Dv x{{item, 6.7}, false};  2. VLQFH 
Dv y{item, 6.7, false};  2. VLQFH  XQOHVV HPSW VXEREMHFWEDVH
%HIRUH  WKLV LV D FODVV
ZLWK LPSOLFLW GHIDXOW FRQVWUXFWRU
6LQFH  WKLV LV D FODVV
WKDW LV DQ DJJUHJDWH
 $JJUHJDWHV ZLWK %DVH ODVVHV
‡ $JJUHJDWHV QRZ FDQ KDYH SXEOLF EDVH FODVVHV
‡ ,QLWLDOL]DWLRQ ZLWK QHVWHG ^` SRVVLEOH
‡ 1HZ WSH WUDLW VWGLVBDJJUHJDWH!
%HIRUH 
struct Dv : Data {
bool used;
Dv (string s, double d, bool b) {
: Data{s,d}, used{b} {
}

};
QHFHVVDU WR HQDEOH
Dv x{hi, 6.7, false};
Nico Josuttis C++17
@CodeHard 18
‹ E ,7FRPPXQLFDWLRQFRP 

 $JJUHJDWH ,QLWLDOL]DWLRQ
‡ /LVW LQLWLDOL]DWLRQ LV ]HUR LQLWLDOL]DWLRQ LI QR YDOXH LV SDVVHG
± 'HIDXOW FRQVWUXFWRU IRU FODVV WSHV
± 0 false nullptr IRU IXQGDPHQWDO GDWD WSHV )'7
struct Data {
std::string name;
double value;
};
struct PData : Data {
bool flag;
};
PData a{{test1, 1.1}, false};  LQLWLDOL]H DOO HOHPHQWV
PData b{test2, 2.2, false};  LQLWLDOL]H DOO HOHPHQWV
PData c{};  VDPH DV {{,0.0},false}
PData d{{msg}};  VDPH DV {{msg,0.0},false}
PData e{{}, true};  VDPH DV {{,0.0},true}
PData f;  QXPHULF HOHPHQWV KDYH XQVSHFLILHG YDOXH
‹ E ,7FRPPXQLFDWLRQFRP 

 $JJUHJDWHV ,QFRPSDWLELOLWLHV
‡ $JJUHJDWHV DUH DUUDV RU FODVV WSHV ZLWK
± QR XVHUGHFODUHG RU H[SOLFLW FRQVWUXFWRU
± QR FRQVWUXFWRU LQKHULWHG E D XVLQJ GHFODUDWLRQ
± QR SULYDWH RU SURWHFWHG QRQVWDWLF GDWD PHPEHUV
± QR YLUWXDO IXQFWLRQV
± QR YLUWXDO SULYDWH RU SURWHFWHG EDVH FODVVHV
‡ $JJUHJDWH LQLWLDOL]DWLRQ PXVW QRW XVH SULYDWH RU SURWHFWHG
EDVH FODVV PHPEHUVFRQVWUXFWRUV
struct Derived;
struct Base {
friend struct Derived;
private:
Base() {  SULYDWH GHIDXOW FRQVWUXFWRU
}
};
struct Derived : Base {
};
Derived d1;  VWLOO 2.
Derived d2{};  (5525 VLQFH 
 1R DJJUHJDWH
 DOOV LPSOLFLW GHIDXOW FRQVWUXFWRU
 $JJUHJDWH
 DOO RI SULYDWH EDVH FRQVWUXFWRU
LV QRW DOORZHG
Nico Josuttis C++17
@CodeHard 19
‹ E ,7FRPPXQLFDWLRQFRP 

 $JJUHJDWHV ,QFRPSDWLELOLWLHV
‡ $JJUHJDWHV DUH DUUDV RU FODVV WSHV ZLWK
± QR XVHUGHFODUHG RU H[SOLFLW FRQVWUXFWRU
± QR FRQVWUXFWRU LQKHULWHG E D XVLQJ GHFODUDWLRQ
± QR SULYDWH RU SURWHFWHG QRQVWDWLF GDWD PHPEHUV
± QR YLUWXDO IXQFWLRQV
± QR YLUWXDO SULYDWH RU SURWHFWHG EDVH FODVVHV
‡ 1RWH $ GHOHWHG GHIDXOW FRQVWUXFWRU GRHVQ
W GLVDEOH
1RWH DJJUHJDWH LQLWLDOL]DWLRQ KWWSVZJOLQNFZJ
struct CData {
int val;
int elems[3];
};
class CppData : public CData {
public:
CppData() = delete;
void print() const;
};
CppData cd1;  (5525
CppData cd2{};  (5525 ZLWK  2. VLQFH
CppData cd3{3, 0, 8, 15};  (5525 ZLWK  2. VLQFH
1R DJJUHJDWH
 RQVWUXFWRU GLVDEOHV DQ
LQLWLDOL]DWLRQ
 $JJUHJDWH
 $JJUHJDWH LQLWLDOL]DWLRQ VWLOO 2.
‹ E ,7FRPPXQLFDWLRQFRP 

 0DQGDWRU 592 DQG RS (OLVLRQ
‡ RS HOLVLRQ IRU LQLWLDOL]DWLRQ IURP WHPSRUDULHV
SUYDOXHV
LV UHTXLUHG VLQFH 
‡ DOODEOH FRSPRYH FRQVWUXFWRU QR ORQJHU UHTXLUHG
class NoCpMv
{
public:
NoCpMv() = default;
 QR FRSPRYH FRQVWUXFWRU
NoCpMv(const NoCpMv) = delete;
NoCpMv(NoCpMv) = delete;

};
void call(NoCpMv obj)
{
}
call(NoCpMv());  2. VLQFH 
 QR FRSPRYH
NoCpMv ret()
{
return NoCpMv();  2. VLQFH 
}  QR FRSPRYH
NoCpMv x = ret();  2. VLQFH 
call(ret());  2. VLQFH 
call(x);  VWLOO (5525
Nico Josuttis C++17
@CodeHard 20
‹ E ,7FRPPXQLFDWLRQFRP 

 %HQHILWV IURP 0DQGDWRU RS (OLVLRQ
‡ 5HTXLUHG FRS HOLVLRQ KHOSV WR
± SURYLGH IDFWRULHV IRU DQ WSH
± GHDOLQJ ZLWK WSHV ZLWK GHOHWHG PRYH
#include utility
 JHQHULF IDFWRU
template typename T, typename... Args
T create(Args... args)
{

return T{std::forwardArgs(args)...};
}
#include atomic
 2. VLQFH 
 1RWH FDQ
W FRSPRYH VWGDWRPLF! REMHFWV
auto ai = createstd::atomicint(42);
class CopyOnly {
public:
CoypeOnly() {
}
CopyOnly(int) {
}
CopyOnly(const CopyOnly) = default;
CopyOnly(CopyOnly) = delete;
};
CopyOnly ret() {
return CopyOnly{};  2. VLQFH 
}
CopyOnly x = 42;  2. VLQFH 
5HPHPEHU
RS FRQVWUXFWRU LV QR IDOOEDFN LI PRYH
FRQVWUXFWRU LV H[SOLFLWO GHOHWHG
‹ E ,7FRPPXQLFDWLRQFRP 

9DOXH DWHJRULHV VLQFH 

(YHU H[SUHVVLRQ LV RQH RI
‡ /9DOXH /RFDOL]DEOH YDOXH
± 9DULDEOH GDWD PHPEHU IXQFWLRQ VWULQJ OLWHUDO UHWXUQHG OYDOXH UHIHUHQFH
± DQ EH RQ WKH OHIW VLGH RI DQ DVVLJQPHQW RQO LI LW
V PRGLILDEOH
‡ 359DOXH 3XUH 59DOXH IRUPHU 59DOXH
± $OO /LWHUDOV H[FHSW VWULQJ OLWHUDOV 42 true nullptr
this ODPEGD UHWXUQHG QRQUHIHUHQFH UHVXOW RI FRQVWUXFWRU FDOO T()
‡ ;9DOXH H;SLULQJ YDOXH
± 5HWXUQHG UYDOXH UHIHUHQFH HJ E VWGPRYH
Beware of C++17
FDVW WR UYDOXH UHIHUHQFH
*HQHUDO FDWHJRULHV */9DOXH *HQHUDOL]HG /9DOXH 59DOXH JHQHUDOL]HG 59DOXH
H[SUHVVLRQ
UYDOXHJOYDOXH
OYDOXH [YDOXH SUYDOXH
Nico Josuttis C++17
@CodeHard 21
‹ E ,7FRPPXQLFDWLRQFRP 


‡ SUYDOXHV SHUIRUP LQLWLDOL]DWLRQ
± QR WHPSRUDU REMHFW HW
‡ JOYDOXHV SURGXFH ORFDWLRQV
‡ Materialization DV D WHPSRUDU REMHFW
± SUYDOXHWR[YDOXH FRQYHUVLRQ
‡ ZKHQ ERXQG WR D UHIHUHQFH
‡ ZLWK PHPEHU DFFHVV
‡ ZLWK FRQYHUVLRQ WR EDVH
9DOXH DWHJRULHV VLQFH 
MyClass ret() {
return MyClass();  UHWXUQV SUYDOXH QR WHPSRUDU REMHFW HW
}
MyClass x = ret();  XVHV SUYDOXH IRU LQLWLDOL]DWLRQ
void callV(MyClass obj);  DFFHSWV DQ YDOXH FDWHJRU
void callR(const MyClass r);  UHTXLUHV JOYDOXH
void callM(MyClass r);  UHTXLUHV [YDOXH PD EH PDWHULDOL]HG IURP SUYDOXH
callV(ret());  SDVVHV SUYDOXH DQG XVHV LW IRU LQLWLDOL]DWLRQ RI obj
callR(ret());  SDVVHV SUYDOXH PDWHULDOL]HG DV [YDOXH
WR r
callM(ret());  SDVVHV SUYDOXH PDWHULDOL]HG DV [YDOXH
WR r
H[SUHVVLRQ
UYDOXHJOYDOXH
OYDOXH [YDOXH SUYDOXH
temporary
materialization
conversion
‹ E ,7FRPPXQLFDWLRQFRP 

 FRQVWH[SU /DPEGDV
‡ /DPEGDV DUH E GHIDXOW FRQVWH[SU QRZ LI SRVVLEOH
± DQ EH IRUFHG ZLWK FRQVWH[SU
auto squared = [](auto val) {  LPSOLFLWO FRQVWH[SU VLQFH 
return val*val;
};
std::arrayint,squared(5) a;  2. VLQFH  ! VWGDUUDLQW!
auto squared2 = [](auto val) constexpr {  2. VLQFH 
return val*val;
};
auto squared3 = [](auto val) constexpr {  (5525
static int calls=0;  FDQ
W EH FRQVWH[SU GXH WR VWDWLF

return val*val;
};
Nico Josuttis C++17
@CodeHard 22
‹ E ,7FRPPXQLFDWLRQFRP 

/DPEGDV DSWXULQJ this
‡ ,Q PHPEHU IXQFWLRQV FDQ DOVR SDVV this DV FDSWXUH
± LPSOLFLWO GRQH ZLWK [=] DQG []
‡ 6LQFH  *this DOORZV WR SDVV *this E YDOXH
class C
{
private:
std::string name;
public:

void foo() {
 [] { std::cout  name  'n'; }   (UURU
 [] { std::cout  name  'n'; }   2.
 [=] { std::cout  name  'n'; }   2.
 [this] { std::cout  name  'n'; }   2.
 [*this] {std::cout  name  'n'; }   2. VLQFH 
 ORFDO FRS RI 
WKLV
}
};
‹ E ,7FRPPXQLFDWLRQFRP 

 $WWULEXWHV
‡ 1HZ $WWULEXWHV IRUPDO DQQRWDWLRQV
[[ nodiscard ]]
[[ maybe_unused ]]
[[ fallthrough ]]
‡ $WWULEXWHV IRU QDPHVSDFHV DQG HQXPHUDWLRQV
enum E {
foobar = 0,
foobat [[deprecated]] = foobar
};
namespace [[deprecated]] xyz {

}
‡ 8VLQJ GHFODUDWLRQV IRU DWWULEXWHV
[[ using xyz :  ]]
Nico Josuttis C++17
@CodeHard 23
‹ E ,7FRPPXQLFDWLRQFRP 

 1HZ $WWULEXWHV
‡  GHILQHV QHZ $WWULEXWHV IRUPDO DQQRWDWLRQV
[[nodiscard]]
± IRUFH ZDUQLQJ LI UHWXUQ YDOXHV DUH QRW XVHG
± SRUWDEOH [[gnu::warn_unused_result]]
± 3RVVLEOH H[DPSOH
template class F, class... Args
[[nodiscard]] future async(F f, Args... args);
[[ maybe_unused ]]
± GLVDEOHG ZDUQLQJV DERXW QDPHV DQG HQWLWLHV WKDW DUH LQWHQWLRQDOO QRW XVHG
± )RU H[DPSOH
[[maybe_unused]] int y = foo();
[[ fallthrough ]]
± IRU LQWHQWLRQDO VZLWFK caseV KDYLQJ VWDWHPHQWV EXW QR break;
%XW RQO VLQFH 
XVHG LQ WKH OLEUDU
‹ E ,7FRPPXQLFDWLRQFRP 

 1HVWHG 1DPHVSDFH 'HILQLWLRQV
‡ 1HZ VQWD[ IRU QHVWHG QDPHVSDFH GHILQLWLRQV
± ,QVWHDG RI
RX FDQ ZULWH VLQFH 
‡ 1R VXSSRUW IRU QHVWHG LQOLQH QDPHVSDFHV
namespace A {
namespace B {
namespace C {
…
}
}
}
namespace A::B::C {
…
}
)LUVW SURSRVHG
LQ 
Nico Josuttis C++17
@CodeHard 24
‹ E ,7FRPPXQLFDWLRQFRP 

 +HDS $OORFDWLRQ ZLWK $OLJQPHQW
‡ 6LQFH  RSHUDWRU QHZ SURYLGHV DQ LQWHUIDFH WR GHDO
ZLWK DOLJQHG GDWDWSHV
± XVHV LQ std enum class align_val_t : size_t {};
‡ 6HYHUDO QHZ RYHUORDGV IRU RSHUDWRUV
± QHZ QHZ@
± GHOHWH GHOHWH@
new T
 UHVXOWV LQWR FDOOLQJ RQH RI ZKLFKHYHU LV SURYLGHG
operator new(sizeof(T))
operator new(sizeof(T), std::align_val_t(alignof(T)))
new(adr) std::string
 UHVXOWV LQWR FDOOLQJ RQH RI ZKLFKHYHU LV SURYLGHG
operator new(sizeof(std::string), adr)
operator new(sizeof(std::string),
std::align_val_t(alignof(std::string)), adr)
‹ E ,7FRPPXQLFDWLRQFRP 

 ([DPSOH IRU +HDS $OORFDWLRQ ZLWK $OLJQPHQW
#include new  IRU align_val_t
struct alignas(512) Aligned {
int i;
alignas(128) double d;
alignas(512) char c;
 DOORFDWH PHPRU IRU VLQJOH REMHFW ZLWK GHIDXOW DOLJQPHQW
static void* operator new (std::size_t size) {
std::cout  Aligned::new called with size:   size  n;
return ::new char[size];
}
 DOORFDWH PHPRU IRU VLQJOH REMHFW ZLWK H[WHQGHG DOLJQPHQW
static void* operator new (std::size_t size, std::align_val_t align) {
std::cout  Aligned::new called with size:   size
  and align:   static_castint(align)  n;
return ::new char[size];
}
};
Aligned a;  DOLJQHG IRU  DGGUHVV VLQFH
Aligned* ap = new Aligned{};  UHTXHVWV KHDS DOLJQPHQW IRU  DGGUHVV VLQFH 
XVHG DV IDOOEDFN
PD[ LQQHU DOLJQPHQW
IRUFHV RXWHU DOLJQPHQW
VL]HDOLJQ 
LQVWHDG RI HJ
Nico Josuttis C++17
@CodeHard 25
‹ E ,7FRPPXQLFDWLRQFRP 

 _ _has_include
_ _has_include:
‡ 7HVW IRU H[LVWHQFH RI D KHDGHU
‡ +HOSV WR ZULWH SRUWDEOH FRGH
‡ )RU H[DPSOH
#if _ _has_include(optional)
# include optional
# define HAS_OPTIONAL 1
#elif _ _has_include(experimental/optional)
# include experimental/optional
# define HAS_OPTIONAL 1
# define OPTIONAL_IS_EXPERIMENTAL 1
#else
# define HAS_OPTIONAL 0
#endif
‹ E ,7FRPPXQLFDWLRQFRP 

 87) KDUDFWHU /LWHUDOV
‡ (QFRGLQJ SUHIL[ X LHOGV char ZLWK 87) YDOXH
± VLQFH 
‡ L'6' IRU ZFKDUBW OLWHUDOV WZR RU IRXU EWHV QR VSHFLILF FKDUDFWHU VHW
± VLQFH 
‡ u'6' IRU FKDUBW OLWHUDOV WZREWH 87)
‡ U'6' IRU FKDUBW OLWHUDOV IRXUEWH 87)
± VLQFH 
‡ u8'6' IRU 87) FKDUDFWHU OLWHUDOV
± $OUHDG IRU VWULQJ OLWHUDOV VLQFH 
‡ SURYLGHG
± WKH 87) OLWHUDO RQO KDV D VLQJOH FKDUDFWHU
± LWV YDOXH LV UHSUHVHQWDEOH ZLWK D VLQJOH 87) FRGH XQLW
LH LV D 86$6,, FKDUDFWHU
u8'ö'  (5525 WZR EWHVFRGHXQLWV LQ 87)  KH[  %
2QO QHFHVVDU ZKHQ WKH
VRXUFHH[HFXWLRQ FKDUDFWHU VHW
LV QRW 86$6,, HJ FRPSLOLQJ
XQGHU DQ (%', FKDUDFWHU VHW
Nico Josuttis C++17
@CodeHard 26
‹ E ,7FRPPXQLFDWLRQFRP 

 +H[DGHFLPDO )ORDWLQJ3RLQW /LWHUDOV
‡ 0x DOVR IRU IORDWLQJSRLQW OLWHUDOV
± VLJQLILFDQG LV JLYHQ LQ KH[DGHFLPDO
± H[SRQHQW LV JLYHQ LQ GHFLPDO DQG LQWHUSUHWHG ZLWK UHVSHFW WR EDVH 
‡ $V DOUHDG LQ 
‡ $V WKH std::hexfloat LRVWUHDP IRUPDW VLQFH
std::initializer_listdouble values {
0x1p4,  
0xA,  
0xAp2,  
5e0,  
0x1.4p+2,  
1e5,  
0x1.86Ap+16,  
0xC.68p+2,  
};
for (double d : values) {
std::cout  dec:   std::setw(6)  std::defaultfloat  d
  hex:   std::hexfloat  d  'n';
}
2XWSXW
dec: 16 hex: 0x1p+4
dec: 10 hex: 0x1.4p+3
dec: 40 hex: 0x1.4p+5
dec: 5 hex: 0x1.4p+2
dec: 5 hex: 0x1.4p+2
dec: 100000 hex: 0x1.86ap+16
dec: 100000 hex: 0x1.86ap+16
dec: 49.625 hex: 0x1.8dp+5
‹ E ,7FRPPXQLFDWLRQFRP 

 6WDWLFBDVVHUW
ZLWKRXW 0HVVDJHV
‡ VWDWLFBDVVHUW
QR ORQJHU UHTXLUHV WR SDVV D WH[W PHVVDJH
± 3ULQWLQJ D GHIDXOW WH[W PHVVDJH LI DVVHUWLRQ LV YLRODWHG
static_assert(sizeof(int)=4, integers are too small);  2. VLQFH 
static_assert(sizeof(int)=4);  2. VLQFH 
template typename T
class C
{
static_assert(std::is_default_constructibleT::value,
class C: element type T must be default-constructible);
static_assert(std::is_default_constructibleT::value);  2. VLQFH 

};
Nico Josuttis C++17
@CodeHard 27
‹ E ,7FRPPXQLFDWLRQFRP 

7HPSODWH )HDWXUHV

‹ E ,7FRPPXQLFDWLRQFRP 

 0RUH RQYHQLHQFH IRU 7SH 7UDLWV UHWXUQLQJ 9DOXHV
‡ 6LQFH  VKRUWFXWV ZLOO EH SURYLGHG IRU WSH WUDLWV
UHWXUQLQJ YDOXHV
± ,QVWHDG RI
std::is_constT::value
RX FDQ XVH
std::is_const_vT
‡ 7KLV LV GRQH YLD YDULDEOH WHPSODWHV
± DYDLODEOH VLQFH 
namespace std {
template typename T
constexpr bool is_const_v = is_constT::value;
}
Nico Josuttis C++17
@CodeHard 28
‹ E ,7FRPPXQLFDWLRQFRP 

 RPSLOH7LPH if
‡  SURYLGHV D FRPSLOHWLPH LI
± FRQVWH[SU LI
± 7KH then RU else SDUW PD EHFRPH D discarded statement
template typename T
std::string asString(T x)
{
if constexpr(std::is_arithmetic_vT) {
return std::to_string(x);
}
else if constexpr(std::is_same_vT, std::string) {
return x;
}
else {
return std::string(x);
}
}
std::cout  asString(42)  'n';
std::cout  asString(std::string(hello))  'n';
std::cout  asString(hello)  'n';
$OO H[DPSOH FDOOV
ZRXOG EH LQYDOLG
ZKHQ XVLQJ UXQWLPH LI
‹ E ,7FRPPXQLFDWLRQFRP 

 RPSLOH7LPH if ZLWK ,QLWLDOL]HUV
template typename Coll, typename Mutex
void process(const Coll coll, Mutex m)
{

if constexpr (std::lock_guard lg{m};
std::is_pointer_vtypename Coll::value_type) {
  LPSOHPHQW SURFHVVLQJ IRU SRLQWHU HOHPHQWV
}
else {
  LPSOHPHQW SURFHVVLQJ IRU RWKHU HOHPHQWV
}

}
std::vectorint vi;
std::mutex viMutex;

process(vi, viMutex);
std::vectorint* vp;
std::mutex vpMutex;

process(vp, vpMutex);
,QLWLDOL]DWLRQ PLJKW EH
HYDOXDWHG DW UXQWLPH
Nico Josuttis C++17
@CodeHard 29
‹ E ,7FRPPXQLFDWLRQFRP 

 RPSLOH7LPH if 2XWVLGH 7HPSODWHV
‡ if constexpr DOVR FDQ EH XVHG LQ QRQWHPSODWH FRGH
‡ $OO FRGH LQ GLVFDUGHG VWDWHPHQWV PXVW EH YDOLG
template typename T
void foo(T t);
int main()
{
if constexpr(std::numeric_limitschar::is_signed) {
foo(42);  2.
static_assert(std::numeric_limitschar::is_signed,
char is unsigned?);  DOZDV IDLOV LI FKDU LV XQVLJQHG
}
else {
undeclared(42);  DOZDV HUURU LI XQGHFODUHG
QRW GHFODUHG
static_assert(!std::numeric_limitschar::is_signed,
char is signed?);  DOZDV IDLOV LI FKDU LV VLJQHG
}
}
7KLV SURJUDP QHYHU
VXFFHVVIXOO FRPSLOHV
‹ E ,7FRPPXQLFDWLRQFRP 

 RPSLOH7LPH if
‡ 7KH discarded statement PXVW VWLOO EH YDOLG
± 3HUIRUPV WKH ILUVW SKDVH RI WHPSODWH WUDQVODWLRQ GHILQLWLRQ SKDVH
± DOOV QRW GHSHQGLQJ RQ WHPSODWH SDUDPHWHUV DUH LQVWDQWLDWHG
template typename T
void foo(T t)
{
if constexpr(std::is_integral_vT) {
if (t  0) {
foo(t-1);  UHFXUVLYH FDOO 2.
}
}
else {
undeclared();  DOZDV (5525 LI QRW GHFODUHG HYHQ LI GLVFDUGHG
undeclared(t);  (5525 LI QRW GHFODUHG DQG QRW GLVFDUGHG LH T LV QRW LQWHJUDO
static_assert(sizeof(int)4, small int);  PD DVVHUW HYHQ LI GLVFDUGHG
static_assert(sizeof(T)4, small T);  PD DVVHUW RQO LI QRW GLVFDUGHG
}
}
‡ RPSLOHWLPH HUURU
HYHQ LI foo()
QHYHU FDOOHG
 ([FHSW ZLWK 9
Nico Josuttis C++17
@CodeHard 30
‹ E ,7FRPPXQLFDWLRQFRP 

7HPSODWHV 7ZR3KDVH 7UDQVODWLRQ
 :LWKRXW LQVWDQWLDWLRQ DW definition time
± 6QWD[ HUURUV DUH GLVFRYHUHG VXFK DV PLVVLQJ VHPLFRORQV
± )RU FRGH WKDW GRHV QRW GHSHQG RQ WHPSODWH SDUDPHWHUV
‡ XVH RI XQNQRZQ QDPHV WSH QDPHV IXQFWLRQ QDPHV
LV GLVFRYHUHG
‡ VWDWLF DVVHUWLRQV DUH FKHFNHG
 $W instantiation time
± $OO FRGH GHSHQGLQJ RQ WHPSODWH SDUDPHWHUV LV GRXEOHFKHFNHG
templatetypename T
void foo(T t)
{
undeclared();  VW SKDVH HUURU LI undeclared() XQNQRZQ
undeclared(t);  QG SKDVH HUURU LI undeclared(T) XQNQRZQ
static_assert(sizeof(int)4, small int);  VW SKDVH HUURU LI VL]HRILQW
! 
static_assert(sizeof(T)4, small T);  QG SKDVH HUURU LI VL]HRI7
! 
static_assert(false, oops);  DOZDV IDLOV ZKHQ WHPSODWH LV FRPSLOHG HYHQ LI QRW FDOOHG
}
‡  FRPSLOHWLPH HUURUV HYHQ
LI foo() QHYHU FDOOHG
 ([FHSW ZLWK 9
‹ E ,7FRPPXQLFDWLRQFRP 

7HPSODWHV 7ZR3KDVH 7UDQVODWLRQ DQG 9LVXDO 
‡ 9LVXDO  E GHIDXOW
GRHV QR ILUVWSKDVH ORRNXS DW DOO
‡ 9LVXDO 6WXLR  VLQFH
DOORZV ILUVWSKDVH ORRNXS ZLWK
/permissive-
± KWWSVEORJVPVGQPLFURVRIWFRPYFEORJWZRSKDVHQDPHORRNXSVXSSRUWFRPHVWRPVYF
± 8QGHFODUHG IXQFWLRQV DQG static_assert() VWLOO DOZDV LJQRUHG
void func(void*) {
std::cout  calls func(void*) (first-phase lookup)n;
}
templatetypename T
void callfunc(T) {
func(0);  ILUVWSKDVH ORRNXS VKRXOG ILQG RQO func(void*) KHUH
}
void func(int) {
std::cout  calls func(int) (second-phase lookup)n;
}
int main()
{
callfunc(42);  FDOOV IXQFYRLG
ZLWK FRUUHFW WZRSKDVH ORRNXS
}
‡ JFF FODQJ DQG
96 ZLWK /permissive-
 FDOOV func(void*)
VW SKDVH ORRNXS
‡ 96 96 96
ZLWKRXW /permissive-
FDOOV func(int)
QG SKDVH ORRNXS
Nico Josuttis C++17
@CodeHard 31

More Related Content

What's hot (18)

PDF
Perfil frutas mermela_organica_uk
luzymi
 
DOCX
5 ( 9 $ 1 8 $ 5 3 urihv
AASTHA76
 
PDF
Teoriaartegotico
manu avila marin
 
PDF
Amicus brief
Honolulu Civil Beat
 
PDF
Amicus brief
Honolulu Civil Beat
 
PDF
Elgriegoenfichas 1bachillerato-sin membrete-1 copia
Francisco Antonio Callejón Rodríguez
 
PDF
Assembly
Mohammed Alramadi
 
PDF
Automatic Configuration of Component-Based Distributed Systems
Fabio Kon
 
PDF
Manual VRF LG
GrupoGPS
 
PDF
6th ps 2nd_term_01_chavin
St. George's College
 
PDF
Misting Systems Catalog 2013 rev beo (anglais)
e-Toile Communication
 
PDF
Seguridad Computacional
Adixs Cabrejos
 
PDF
CV
jmsorens
 
PDF
Mecanismos de falla
Edy Huanca
 
PDF
Student Usability in Educational Software and Games: Improving Experiences
Carina Soledad Gonzalez
 
PDF
Dr Rahul & Heena Tiwari- How to Write an Article and Publish it - Complete Book
Rahul Vinay Chandra Tiwari
 
PDF
US-40
Johnny Chiu
 
PDF
Le troisieme testament
Taromancie, Guidance intuitive
 
Perfil frutas mermela_organica_uk
luzymi
 
5 ( 9 $ 1 8 $ 5 3 urihv
AASTHA76
 
Teoriaartegotico
manu avila marin
 
Amicus brief
Honolulu Civil Beat
 
Amicus brief
Honolulu Civil Beat
 
Elgriegoenfichas 1bachillerato-sin membrete-1 copia
Francisco Antonio Callejón Rodríguez
 
Automatic Configuration of Component-Based Distributed Systems
Fabio Kon
 
Manual VRF LG
GrupoGPS
 
6th ps 2nd_term_01_chavin
St. George's College
 
Misting Systems Catalog 2013 rev beo (anglais)
e-Toile Communication
 
Seguridad Computacional
Adixs Cabrejos
 
Mecanismos de falla
Edy Huanca
 
Student Usability in Educational Software and Games: Improving Experiences
Carina Soledad Gonzalez
 
Dr Rahul & Heena Tiwari- How to Write an Article and Publish it - Complete Book
Rahul Vinay Chandra Tiwari
 
Le troisieme testament
Taromancie, Guidance intuitive
 

Similar to Beware of C++17 (20)

PDF
SEO - Optimizacion en buscadores
KanvasMedia
 
PDF
Pulmonary resection in basrah: personal experience
Abdulsalam Taha
 
PDF
G2 bsc commissioning manual release b7.2
chungminh1108
 
PDF
Hyster D001 (H25XM) Forklift Service Repair Manual.pdf
fujsekdmdmd
 
PDF
Hyster D001 (H40XMS) Forklift Service Repair Manual.pdf
fujsekdmdmd
 
PDF
Hyster D001 (H30XM) Forklift Service Repair Manual.pdf
fujsekdmdmd
 
PDF
Hyster D001 (H35XM) Forklift Service Repair Manual.pdf
fujsekdmdmd
 
PDF
New Holland VL660 Grape Harvester Service Repair Manual.pdf
fujsekdmmdm
 
PDF
New Holland VM460 Grape Harvester Service Repair Manual.pdf
fujsekdmmdm
 
PDF
New Holland VL600 Grape Harvester Service Repair Manual.pdf
fujsekdmmdm
 
PDF
New Holland VM370 Grape Harvester Service Repair Manual.pdf
fujsekdmmdm
 
PDF
New Holland VL610 Grape Harvester Service Repair Manual.pdf
fujsekdmmdm
 
PDF
New Holland VL620 Grape Harvester Service Repair Manual.pdf
fujsekdmmdm
 
PDF
New Holland VL570 Grape Harvester Service Repair Manual.pdf
fujsekdmmdm
 
PDF
Factores Determinantes del Éxito de la Gestión de la Seguridad Laboral
Safety Control Peru
 
PDF
New Holland SB56 Grape Harvester Service Repair Manual.pdf
fujskekdmmd
 
PDF
Padova: Integrated climate strategies
Union of the Baltic Cities Sustainable Cities Commission
 
PDF
-Un-secreto-en-mi-colegio-Zig-Zag-2xhoja83-Angelica-Dossetti-pdf.pdf
ClaudiaAraceli2
 
PDF
Programme du colloque
Radio Mosaique FM Tunisia
 
PDF
New holland sb60 grape harvester service repair manual
fjjsjefkskemme
 
SEO - Optimizacion en buscadores
KanvasMedia
 
Pulmonary resection in basrah: personal experience
Abdulsalam Taha
 
G2 bsc commissioning manual release b7.2
chungminh1108
 
Hyster D001 (H25XM) Forklift Service Repair Manual.pdf
fujsekdmdmd
 
Hyster D001 (H40XMS) Forklift Service Repair Manual.pdf
fujsekdmdmd
 
Hyster D001 (H30XM) Forklift Service Repair Manual.pdf
fujsekdmdmd
 
Hyster D001 (H35XM) Forklift Service Repair Manual.pdf
fujsekdmdmd
 
New Holland VL660 Grape Harvester Service Repair Manual.pdf
fujsekdmmdm
 
New Holland VM460 Grape Harvester Service Repair Manual.pdf
fujsekdmmdm
 
New Holland VL600 Grape Harvester Service Repair Manual.pdf
fujsekdmmdm
 
New Holland VM370 Grape Harvester Service Repair Manual.pdf
fujsekdmmdm
 
New Holland VL610 Grape Harvester Service Repair Manual.pdf
fujsekdmmdm
 
New Holland VL620 Grape Harvester Service Repair Manual.pdf
fujsekdmmdm
 
New Holland VL570 Grape Harvester Service Repair Manual.pdf
fujsekdmmdm
 
Factores Determinantes del Éxito de la Gestión de la Seguridad Laboral
Safety Control Peru
 
New Holland SB56 Grape Harvester Service Repair Manual.pdf
fujskekdmmd
 
Padova: Integrated climate strategies
Union of the Baltic Cities Sustainable Cities Commission
 
-Un-secreto-en-mi-colegio-Zig-Zag-2xhoja83-Angelica-Dossetti-pdf.pdf
ClaudiaAraceli2
 
Programme du colloque
Radio Mosaique FM Tunisia
 
New holland sb60 grape harvester service repair manual
fjjsjefkskemme
 
Ad

More from corehard_by (20)

PPTX
C++ CoreHard Autumn 2018. Создание пакетов для открытых библиотек через conan...
corehard_by
 
PPTX
C++ CoreHard Autumn 2018. Что должен знать каждый C++ программист или Как про...
corehard_by
 
PDF
C++ CoreHard Autumn 2018. Actors vs CSP vs Tasks vs ... - Евгений Охотников
corehard_by
 
PPTX
C++ CoreHard Autumn 2018. Знай свое "железо": иерархия памяти - Александр Титов
corehard_by
 
PPTX
C++ CoreHard Autumn 2018. Информационная безопасность и разработка ПО - Евген...
corehard_by
 
PPTX
C++ CoreHard Autumn 2018. Заглядываем под капот «Поясов по C++» - Илья Шишков
corehard_by
 
PPTX
C++ CoreHard Autumn 2018. Ускорение сборки C++ проектов, способы и последстви...
corehard_by
 
PPTX
C++ CoreHard Autumn 2018. Метаклассы: воплощаем мечты в реальность - Сергей С...
corehard_by
 
PPTX
C++ CoreHard Autumn 2018. Что не умеет оптимизировать компилятор - Александр ...
corehard_by
 
PPTX
C++ CoreHard Autumn 2018. Кодогенерация C++ кроссплатформенно. Продолжение - ...
corehard_by
 
PDF
C++ CoreHard Autumn 2018. Concurrency and Parallelism in C++17 and C++20/23 -...
corehard_by
 
PPTX
C++ CoreHard Autumn 2018. Обработка списков на C++ в функциональном стиле - В...
corehard_by
 
PPTX
C++ Corehard Autumn 2018. Обучаем на Python, применяем на C++ - Павел Филонов
corehard_by
 
PDF
C++ CoreHard Autumn 2018. Asynchronous programming with ranges - Ivan Čukić
corehard_by
 
PDF
C++ CoreHard Autumn 2018. Debug C++ Without Running - Anastasia Kazakova
corehard_by
 
PDF
C++ CoreHard Autumn 2018. Полезный constexpr - Антон Полухин
corehard_by
 
PDF
C++ CoreHard Autumn 2018. Text Formatting For a Future Range-Based Standard L...
corehard_by
 
PPTX
Исключительная модель памяти. Алексей Ткаченко ➠ CoreHard Autumn 2019
corehard_by
 
PDF
Как помочь и как помешать компилятору. Андрей Олейников ➠ CoreHard Autumn 2019
corehard_by
 
PDF
Автоматизируй это. Кирилл Тихонов ➠ CoreHard Autumn 2019
corehard_by
 
C++ CoreHard Autumn 2018. Создание пакетов для открытых библиотек через conan...
corehard_by
 
C++ CoreHard Autumn 2018. Что должен знать каждый C++ программист или Как про...
corehard_by
 
C++ CoreHard Autumn 2018. Actors vs CSP vs Tasks vs ... - Евгений Охотников
corehard_by
 
C++ CoreHard Autumn 2018. Знай свое "железо": иерархия памяти - Александр Титов
corehard_by
 
C++ CoreHard Autumn 2018. Информационная безопасность и разработка ПО - Евген...
corehard_by
 
C++ CoreHard Autumn 2018. Заглядываем под капот «Поясов по C++» - Илья Шишков
corehard_by
 
C++ CoreHard Autumn 2018. Ускорение сборки C++ проектов, способы и последстви...
corehard_by
 
C++ CoreHard Autumn 2018. Метаклассы: воплощаем мечты в реальность - Сергей С...
corehard_by
 
C++ CoreHard Autumn 2018. Что не умеет оптимизировать компилятор - Александр ...
corehard_by
 
C++ CoreHard Autumn 2018. Кодогенерация C++ кроссплатформенно. Продолжение - ...
corehard_by
 
C++ CoreHard Autumn 2018. Concurrency and Parallelism in C++17 and C++20/23 -...
corehard_by
 
C++ CoreHard Autumn 2018. Обработка списков на C++ в функциональном стиле - В...
corehard_by
 
C++ Corehard Autumn 2018. Обучаем на Python, применяем на C++ - Павел Филонов
corehard_by
 
C++ CoreHard Autumn 2018. Asynchronous programming with ranges - Ivan Čukić
corehard_by
 
C++ CoreHard Autumn 2018. Debug C++ Without Running - Anastasia Kazakova
corehard_by
 
C++ CoreHard Autumn 2018. Полезный constexpr - Антон Полухин
corehard_by
 
C++ CoreHard Autumn 2018. Text Formatting For a Future Range-Based Standard L...
corehard_by
 
Исключительная модель памяти. Алексей Ткаченко ➠ CoreHard Autumn 2019
corehard_by
 
Как помочь и как помешать компилятору. Андрей Олейников ➠ CoreHard Autumn 2019
corehard_by
 
Автоматизируй это. Кирилл Тихонов ➠ CoreHard Autumn 2019
corehard_by
 
Ad

Recently uploaded (20)

PPTX
Applied-Statistics-Mastering-Data-Driven-Decisions.pptx
parmaryashparmaryash
 
PDF
Per Axbom: The spectacular lies of maps
Nexer Digital
 
PPTX
cloud computing vai.pptx for the project
vaibhavdobariyal79
 
PDF
MASTERDECK GRAPHSUMMIT SYDNEY (Public).pdf
Neo4j
 
PPTX
OA presentation.pptx OA presentation.pptx
pateldhruv002338
 
PDF
A Strategic Analysis of the MVNO Wave in Emerging Markets.pdf
IPLOOK Networks
 
PDF
How Open Source Changed My Career by abdelrahman ismail
a0m0rajab1
 
PDF
Make GenAI investments go further with the Dell AI Factory
Principled Technologies
 
PDF
Google I/O Extended 2025 Baku - all ppts
HusseinMalikMammadli
 
PDF
Economic Impact of Data Centres to the Malaysian Economy
flintglobalapac
 
PDF
State-Dependent Conformal Perception Bounds for Neuro-Symbolic Verification
Ivan Ruchkin
 
PDF
Research-Fundamentals-and-Topic-Development.pdf
ayesha butalia
 
PPTX
What-is-the-World-Wide-Web -- Introduction
tonifi9488
 
PDF
Structs to JSON: How Go Powers REST APIs
Emily Achieng
 
PDF
RAT Builders - How to Catch Them All [DeepSec 2024]
malmoeb
 
PDF
AI Unleashed - Shaping the Future -Starting Today - AIOUG Yatra 2025 - For Co...
Sandesh Rao
 
PPTX
Farrell_Programming Logic and Design slides_10e_ch02_PowerPoint.pptx
bashnahara11
 
PDF
Generative AI vs Predictive AI-The Ultimate Comparison Guide
Lily Clark
 
PDF
CIFDAQ's Market Wrap : Bears Back in Control?
CIFDAQ
 
PDF
Peak of Data & AI Encore - Real-Time Insights & Scalable Editing with ArcGIS
Safe Software
 
Applied-Statistics-Mastering-Data-Driven-Decisions.pptx
parmaryashparmaryash
 
Per Axbom: The spectacular lies of maps
Nexer Digital
 
cloud computing vai.pptx for the project
vaibhavdobariyal79
 
MASTERDECK GRAPHSUMMIT SYDNEY (Public).pdf
Neo4j
 
OA presentation.pptx OA presentation.pptx
pateldhruv002338
 
A Strategic Analysis of the MVNO Wave in Emerging Markets.pdf
IPLOOK Networks
 
How Open Source Changed My Career by abdelrahman ismail
a0m0rajab1
 
Make GenAI investments go further with the Dell AI Factory
Principled Technologies
 
Google I/O Extended 2025 Baku - all ppts
HusseinMalikMammadli
 
Economic Impact of Data Centres to the Malaysian Economy
flintglobalapac
 
State-Dependent Conformal Perception Bounds for Neuro-Symbolic Verification
Ivan Ruchkin
 
Research-Fundamentals-and-Topic-Development.pdf
ayesha butalia
 
What-is-the-World-Wide-Web -- Introduction
tonifi9488
 
Structs to JSON: How Go Powers REST APIs
Emily Achieng
 
RAT Builders - How to Catch Them All [DeepSec 2024]
malmoeb
 
AI Unleashed - Shaping the Future -Starting Today - AIOUG Yatra 2025 - For Co...
Sandesh Rao
 
Farrell_Programming Logic and Design slides_10e_ch02_PowerPoint.pptx
bashnahara11
 
Generative AI vs Predictive AI-The Ultimate Comparison Guide
Lily Clark
 
CIFDAQ's Market Wrap : Bears Back in Control?
CIFDAQ
 
Peak of Data & AI Encore - Real-Time Insights & Scalable Editing with ArcGIS
Safe Software
 

Beware of C++17

  • 1. ‹ E ,7FRPPXQLFDWLRQFRP 1LFRODL 0 -RVXWWLV ,7FRPPXQLFDWLRQFRP 0RGHUQ ‹ E ,7FRPPXQLFDWLRQFRP 1LFRODL 0 -RVXWWLV ‡ ,QGHSHQGHQW FRQVXOWDQW ± FRQWLQXRXVO OHDUQLQJ VLQFH ‡ 6VWHPV $UFKLWHFW 7HFKQLFDO 0DQDJHU ± ILQDQFH PDQXIDFWXULQJ DXWRPRELOH WHOHFRPPXQLFDWLRQ ‡ 7RSLFV ± ± 62$ 6HUYLFH 2ULHQWHG $UFKLWHFWXUH
  • 2. ± 7HFKQLFDO 3URMHFW 0DQDJHPHQW ± 3ULYDF FRQWULEXWRU RI (QLJPDLO
  • 4. ‹ E ,7FRPPXQLFDWLRQFRP 'LVFODLPHU ‡ LV EUDQG QHZ ± /LPLWHG H[SHULPHQWDO FRPSLOHU VXSSRUW ± :H ZLOO ILQG IODZV LQ ‡ 7KHVH VOLGHV DUH EUDQG QHZ ± RX ZLOO ILQG IODZV ± 6RPH IHDWXUHV DUH SUREDEO PLVVLQJ ± 6RPH IHDWXUHV DUH QRW ZHOO HQRXJK
  • 5. GHVFULEHG ± , VWLOO OHDUQ ‡ )HHGEDFN ZHOFRPH ‹ E ,7FRPPXQLFDWLRQFRP 0RGHUQ Nico Josuttis C++17 @CodeHard 2
  • 6. ‹ E ,7FRPPXQLFDWLRQFRP 7LPHIUDPH KWWSLVRFSSRUJVWGVWDWXV PHGLXP
  • 7. 0RGHUQ ‹ E ,7FRPPXQLFDWLRQFRP 7LPHIUDPH KWWSLVRFSSRUJVWGVWDWXV Nico Josuttis C++17 @CodeHard 3
  • 8. ‹ E ,7FRPPXQLFDWLRQFRP 6WDQGDUGL]DWLRQ ‡ E ,62 ± IRUPDO YRWHV E QDWLRQDO ERGLHV HJ ‡ $16, IRU 86$ ‡ ',1 IRU *HUPDQ ‡ (PDLO UHIOHFWRUV IRU GLIIHUHQW ZRUNLQJ DQG VWXG JURXSV ± FRUH OLEUDU FRQFXUUHQF ‡ RU MRLQHG PHHWLQJV RI $16, DQG ,62 SHU HDU ± RSHQ WR WKH SXEOLF ‡ (YHUERG LV ZHOFRPH WR ± MRLQ PHHWLQJV ± SURSRVH QHZ IHDWXUHV ± GLVFXVV ‡ ,QIRUPDO ZHE VLWH KWWSLVRFSSRUJVWG ‡ )RUPDO ZHE VLWH KWWSZZZRSHQVWGRUJMWFVFZJ ‹ E ,7FRPPXQLFDWLRQFRP :RUNLQJ DQG 6WXG *URXSV KWWSLVRFSSRUJVWGWKHFRPPLWWHH Nico Josuttis C++17 @CodeHard 4
  • 9. ‹ E ,7FRPPXQLFDWLRQFRP $YDLODELOLW RI WKH 6WDQGDUG ‡ 'RFXPHQW QXPEHU ± ,62,( ‡ $YDLODEOH DW QDWLRQV ERGLHV $16, ',1
  • 10. DQG ,1,76 ‡ 3ULFHV YDU ± ,62,( PHPEHUV
  • 11. ± ',1 ¼ ± %6 ,62,( … PHPEHUV …
  • 12. ± ‡ 9HUVLRQ FORVH WR ILQDO YHUVLRQ DV GRFXPHQW 1SGI IRU IUHH DW ± KWWSVZJOLQNQ ‡ KWWSZZZRSHQVWGRUJMWFVFZJGRFVSDSHUVQSGI ‹ E ,7FRPPXQLFDWLRQFRP 'RFXPHQWV DQG 3DSHUV ‡ $OO ZRUNLQJ GRFXPHQWV DUH SXEOLF DQG DYDLODEOH ± KWWSVZJOLQN ‡ 'LIIHUHQW SDSHU QXPEHUV VFKHPHV ± 1xxxx ± 3yyyy5 3yyyy5 ‡ ,VVXH /LVWV ± FZJxxx HZJxxx ± OZJxxx OHZJxxx IVxxx ‡ )RU H[DPSOH ± KWWSVZJOLQNQ GUDIW VWDQGDUG ± KWWSVZJOLQNSU 3URSRVHG ZRUGLQJ IRU 6WUXFWXUHG %LQGLQJV ± KWWSVZJOLQNOZJ ,VVXH IRU std::is_aggregate Nico Josuttis C++17 @CodeHard 5
  • 13. ‹ E ,7FRPPXQLFDWLRQFRP 6XSSRUW ‡ JFFJ ± VXSSRUWV DOO ODQJXDJH IHDWXUHV ± VXSSRUWV VHYHUDO OLEUDU IHDWXUHV ± 2SWLRQ -std=c++17 ‡ ODQJ ± VXSSRUWV DOO ODQJXDJH IHDWXUHV FODQJ DQG PDQ
  • 14. ± 2SWLRQ -std=c++0z RU -std:c++17 ‡ 9LVXDO 6WXGLR ± RPSLOHU YHUVLRQ ! ELQDU FRPSDWLEOH WR 96
  • 15. ± VXSSRUWV VRPH ODQJXDJH IHDWXUHV ± IUHTXHQW XSGDWHV ± 2SWLRQ /std:c++latest RU /std:c++17 ‹ E ,7FRPPXQLFDWLRQFRP DQG 9LVXDO ‡ 9LVXDO 6WXGLR 9LVXDO DGDSWV PRUH DQG PRUH ± 6RPH IHDWXUHV LQ 96 ± 0RUH DQG PRUH IHDWXUHV LQ 96 ‡ 96 QRZ KDV FRPSLOHU VZLWFK IRU 6WDQGDUG YHUVLRQ ± /std:c++14 /std:c++17 /std:c++latest ‡ 96 LV ELQDU FRPSDWLEOH WR 96 ‡ 96 KDV PXOWLSOH IODYRUV FRPSLOHU YHUVLRQ[
  • 16. ‡ 5HOHDVH FKDQQHO ‡ 96 XSGDWH VLJQLILFDQWO PRUH
  • 17. ‡ 3UHYLHZ FKDQQHO ‡ 96 XSGDWH SUHYLHZ VLQFH 6HS ‡ 6HH ± KWWSVEORJVPVGQPLFURVRIWFRPYFEORJFIHDWXUHVLQYV Nico Josuttis C++17 @CodeHard 6
  • 18. ‹ E ,7FRPPXQLFDWLRQFRP ZLWK J ‡ $V RI ‹ E ,7FRPPXQLFDWLRQFRP JFODQJ 2QOLQH RPSLOHU KWWSPHOSRQRUJZDQGER[ XVHV 6HUYHU6LGH (YHQWV 66(
  • 19. VR RXU ILUHZDOO VKRXOG QRW EORFN text/event-stream Nico Josuttis C++17 @CodeHard 7
  • 20. ‹ E ,7FRPPXQLFDWLRQFRP ZLWK 96 ‡ $V RI RUH /LE ! 96[ 96 ‹ E ,7FRPPXQLFDWLRQFRP 6XSSRUW E 9LVXDO 6WXGLR DQG ‡ 9LVXDO 6WXGLR ± 6XSSRUW IRU LQFRPSOHWH WSHV LQ YHFWRU OLVW DQG IRUZDUGBOLVW ‡ 9LVXDO 6WXGLR ± JOREDO VWGVL]H
  • 25. ± VWGERROBFRQVWDQW VWGYRLGBW ‡ 9LVXDO 6WXGLR 8SGDWH ± JOREDO VWGDVBFRQVW
  • 26. ± 7SH WUDLWV VXIIL[ BY ± VWGVFRSHGBORFN ± IORRU
  • 27. FHLO
  • 28. URXQG
  • 29. DEV
  • 30. IRU FKURQR! ± 7SH WUDLWV FRQMXQFWLRQ! GLVMXQFWLRQ! QHJDWLRQ! Nico Josuttis C++17 @CodeHard 8
  • 31. ‹ E ,7FRPPXQLFDWLRQFRP /DQJXDJH )HDWXUHV ‹ E ,7FRPPXQLFDWLRQFRP 6WUXFWXUHG %LQGLQJV ‡ ,QLWLDOL]H PXOWLSOH LGHQWLILHUVQDPHV IURP ± FODVVVWUXFWXQLRQ REMHFWV ± VWGSDLU! VWGWXSOH! VWGDUUD! ± UDZ DUUDV ‡ 7SHV DUH GHGXFHG IURP PHPEHUVHOHPHQWV struct MyStruct { int i; std::string s; }; MyStruct ms; auto [u,v] = ms; FUHDWH LPSOLFLW HQWLW ZKHUH u v UHSUHVHQW i s std::cout u ' ' SULQW PHPEHUV DVVLJQHG WR XY@ v 'n'; (TXLYDOHQW WR auto e = ms; std::cout e.i ' ' e.s 'n'; Nico Josuttis C++17 @CodeHard 9
  • 32. ‹ E ,7FRPPXQLFDWLRQFRP 8VLQJ 6WUXFWXUHG %LQGLQJV std::mapstd::string, double coll; for (const auto elem : coll) { HOHPV DUH VWGSDLUFRQVW VWGVWULQJ GRXEOH! std::cout elem.first : elem.second 'n'; } VLQFH for (const auto [key,val] : coll) { DFFHVV HOHPV E UHDGRQO UHIHUHQFH std::cout key : val 'n'; } for (auto [key,val] : coll) { DFFHVV HOHPV E UHIHUHQFH if (key != ignore) { val *= 2; } } ‹ E ,7FRPPXQLFDWLRQFRP 6WUXFWXUHG %LQGLQJV IRU 5HWXUQ 9DOXHV struct MyStruct { int i; std::string s; }; MyStruct f1(); auto [u,v] = f1(); XY KDYH WSH DQG YDOXH RI PHPEHUV RI UHWXUQHG REMHFW auto [w] = f1(); (UURU QXPEHU RI HOHPHQWV GRHV QRW ILW auto f2() - int()[2]; I
  • 33. UHWXUQV UHIHUHQFH WR LQW DUUD auto [x, y] = f2(); [ DQG DUH intV LQLWLDOL]HG E HOHPV RI UHWXUQHG DUUD std::arrayint,4 f3(); auto [i,j,k,l] = f3(); LMNO QDPH WKH HOHPHQWV RI WKH FRSLHG UHWXUQ YDOXH std::tuplechar,float,std::string f4(); auto [a,b,c] = f4(); DEF KDYH WSHV DQG YDOXHV RI UHWXUQHG WXSOH Nico Josuttis C++17 @CodeHard 10
  • 34. ‹ E ,7FRPPXQLFDWLRQFRP 6WUXFWXUHG %LQGLQJV DQG 4XDOLILHUV ‡ 6WUXFWXUHG ELQGLQJV GHFODUDWLRQ FDQ KDYH WKH XVXDO TXDOLILHUV const alignas ± $OZDV DSSO WR WKH LPSOLFLWO FUHDWHG HQWLW DV D ZKROH int a[] = { 7, 11 }; auto [ r, s ] = a; U DQG V DUH LGHQWLILHV WR HOHPHQWV RI D UHIHUHQFH WR D r = 42; PRGLI ILUVW HOHPHQW LQ D std::cout a[0] 'n'; SULQWV struct MyStruct { std::string name; int val; }; MyStruct ms = {Jim, 42}; auto [n,v] = ms; Q DQG Y DUH HOHPHQWV RI UHIHUHQFH WR PV std::cout name: ms.name 'n'; SULQWV -LP std::string s = std::move(n); PRYH PVQDPH WR V MyStruct f1(); const auto [nm,vl] = f1(); H[WHQGV OLIHWLPH RI UHWXUQHG WHPSRUDU alignas(16) auto[s,i] = f1(); HQWLW LV EWH DOLJQHG QRW L ‹ E ,7FRPPXQLFDWLRQFRP $GGUHVVHV RI 6WUXFWXUHG %LQGLQJV (OHPHQWV ‡ 6WUXFWXUHG ELQGLQJ GHFODUDWLRQV JXDUDQWHH WKDW WKH REMHFW ZKRVH PHPEHUV DUH GHQRWHG DUH NHSW WRJHWKHU auto f() - int ()[2]; auto [x, y] = f(); assert(x + 1 == y); 2. struct S { FODVV ZLWK VWDQGDUGODRXW int no; double price; std::string msg; }; auto [n,p,s] = S{}; assert(((S*)n)-msg == s); 2. Nico Josuttis C++17 @CodeHard 11
  • 35. ‹ E ,7FRPPXQLFDWLRQFRP 6WUXFWXUHV %LQGLQJV 0LJKW 1RW 'HFD 0HPEHUV ‡ auto GRHV QRW GHFD VWUXFWXUHG ELQGLQJV ± EHFDXVH LW DSSOLHV WR WKH REMHFW DV D ZKROH struct S { int x[3]; int y[3]; }; S s1{}; LQLWLDOL]H DOO PHPEHU DUUDV ZLWK HOHPHQWV EHLQJ auto [a, b] = s1; a DQG b KDYH VDPH PHPEHU WSHV std::is_samedecltype(a), int[3]::value LHOGV true for (int elem : a) { 2. a LV VWLOO DUUD std::cout elem 'n'; } auto p = a; std::is_samedecltype(p), int*::value LHOGV true for (int elem : p) { (5525 p LV QR DUUD } (TXLYDOHQW WR auto e = s1; auto a = e.x; auto b = e.y; ‹ E ,7FRPPXQLFDWLRQFRP 6WUXFWXUHG %LQGLQJV YLD 7XSOHOLNH $3,V class Customer { public: std::string getFirst() const { return first; } std::string getLast() const { return last; } long getValue() const { return val; } }; #include utility IRU WXSOHOLNH $3, SURYLGH D WXSOHOLNH $3, IRU FODVV XVWRPHU IRU VWUXFWXUHG ELQGLQJV template struct std::tuple_sizeCustomer { static constexpr int value = 3; ZH KDYH DWWULEXWHV }; template struct std::tuple_element2, Customer { using type = long; ODVW DWWULEXWH LV D ORQJ }; templatestd::size_t Idx struct std::tuple_elementIdx, Customer { using type = std::string; WKH RWKHU DWWULEXWHV DUH VWULQJV }; GHILQH VSHFLILF JHWWHUV templateint auto get(const Customer c); template auto get0(const Customer c) { return c.getFirst(); } template auto get1(const Customer c) { return c.getLast(); } template auto get2(const Customer c) { return c.getValue(); } Customer c(Tim, Lee, 42); auto [f,l,v] = c; SULQWV 7LP /HH std::cout f ' ' l : v 'n'; $OO IXOO VSHFLDOL]DWLRQV RI IXQFWLRQ WHPSODWHV KDYH WR XVH WKH VDPH VLJQDWXUH LQFOXGLQJ WKH H[DFW VDPH UHWXUQ WSH auto
  • 37. ‹ E ,7FRPPXQLFDWLRQFRP if ZLWK ,QLWLDOL]HUV 1HHG 1DPHV { std::lock_guardstd::mutex lg(mv); if (!v.empty()) { std::cout v.front() 'n'; } } if (std::lock_guardstd::mutex lg(mx); !v.empty()) { 2. std::cout v.front() 'n'; } if (std::lock_guard lg{mx}; !v.empty()) { 2. GXH WR FODVV WHPSODWH DUJ GHGXFWLRQ std::cout v.front() 'n'; } if (std::lock_guardstd::mutex(mx); !v.empty()) { (5525 ORFN HQGV EHIRUH ; std::cout v.front() 'n'; } if (std::lock_guard{mx}; !v.empty()) { (5525 ORFN HQGV EHIRUH ; std::cout v.front() 'n'; } if (std::lock_guardstd::mutex _(mx); !v.empty()) { 2. EXW std::cout v.front() 'n'; } ‹ E ,7FRPPXQLFDWLRQFRP if DQG switch ZLWK ,QLWLDOL]HUV ‡ 1HZ DGGLWLRQDO VQWD[ IRU if DQG switch if (init; condition) switch (init; condition) if (status s = check(); s != status::ok) { return s; } if (std::lock_guardstd::mutex lg(mx); !v.empty()) { std::cout v.front() 'n'; } switch (Foo gadget(args); auto s = gadget.status()) { case OK: gadget.zip(); break; case Bad: throw BadFoo(s.message()); } { status s = check(); if (s != status::ok) { return s; } } { std::lock_guardstd::mutex lg(mv); if (!v.empty()) { std::cout v.front() 'n'; } } { Foo gadget(args); switch (auto s = gadget.status()) { case OK: gadget.zip(); break; case Bad: throw BadFoo(s.message()); } } Nico Josuttis C++17 @CodeHard 13
  • 38. ‹ E ,7FRPPXQLFDWLRQFRP 6WUXFWXUHG %LQGLQJV DQG if ZLWK ,QLWLDOL]HU ‡ RPELQLQJ ± ,QLWLDOL]H PXOWLSOH REMHFWV E PXOWLSOH UHWXUQ YDOXHV ± XVLQJ WKH VXSSOHPHQWDU LQLWLDOL]DWLRQ VQWD[ IRU if ‡ )RU std::mapstd::string, int coll; RX FDQ UHSODFH ‡ E if (auto [pos,ok] = coll.insert({new,42}); !ok) { LI LQVHUW IDLOHG KDQGOH HUURU XVLQJ LWHUDWRU pos IRU HOHP DOUHDG WKHUH
  • 39. const auto [key,val] = *pos; std::cout '' key exists with key: val 'n'; } auto ret = coll.insert({new,42}); if (!ret.second){ LI LQVHUW IDLOHG SULQW ZK XVLQJ LWHUDWRU ret.first IRU HOHP DOUHDG WKHUH
  • 40. const auto elem = *(ret.first); std::cout '' elem.first exists with key: elem.second 'n'; } 2U LQ RQH H[SUHVVLRQ ret.first-second ‹ E ,7FRPPXQLFDWLRQFRP if ZLWK ,QLWLDOL]HUV 1HHG 1DPHV ‡ $Q WHPSRUDU ZLWKRXW D QDPH LQ WKH LQLWLDOL]DWLRQ RQO H[LVWV WKHUH QRW LQ WKH ZKROH VWDWHPHQW ‡ 6DPH DV ZLWK for ORRSV if (std::lock_guardstd::mutex lg(mx); !v.empty()) { 2. std::cout v.front() 'n'; } if (std::lock_guardstd::mutex _(mx); !v.empty()) { 2. EXW std::cout v.front() 'n'; } if (std::lock_guardstd::mutex(mx); !v.empty()) { (5525 ORFN HQGV EHIRUH ; std::cout v.front() 'n'; } if (std::lock_guard lg(mx); !v.empty()) { 2. GXH WR FODVV WHPSODWH DUJ GHGXFWLRQ std::cout v.front() 'n'; } Nico Josuttis C++17 @CodeHard 14
  • 41. ‹ E ,7FRPPXQLFDWLRQFRP if ZLWK ,QLWLDOL]HUV 0DNHV +LGGHQ KHFNV 9LVLEOH ‡ %H FDUHIXO ZKHQ FRQYHUWLQJ H[LVWLQJ if ZLWK LQLWLDOL]DWLRQ ‡ 1DLYH PRGLILFDWLRQV WR XVH QHZ IHDWXUH void f(const Expression* expr) { if (const auto* unaryExpr = expr-AsUnaryExpression()) { if (unaryExpr-Kind() == TokenKind::Plus) { } } } void f(const Expression* expr) { if (const auto* unaryExpr = expr-AsUnaryExpression(); unaryExpr-Kind() == TokenKind::Plus) { } } PLVVLQJ LPSOLFLW if (unaryExpr) 7KDQNV WR -RQDWKDQ DYHV IRU WKLV H[DPSOH ‹ E ,7FRPPXQLFDWLRQFRP ,QOLQH 9DULDEOHV ‡ 6WDWLF YDULDEOHV PDUNHG ZLWK inline FRXQW DV GHILQLWLRQV ± *XDUDQWHHG WR H[LVW RQO RQFH LQ WKH SURJUDP ± 1R QHHG IRU 33 ILOHV WR GHILQH VWDWLFJOREDO REMHFWV class Monitor { public: Monitor() { } void log(const std::string msg) { } } 'HFODUH THE JOREDO PRQLWRU LQ WKH KHDGHU ILOH PLJKW EH LQFOXGHG E PXOWLSOH WUDQVODWLRQ XQLWV inline Monitor progMonitor PRQLWRUKSS #include monitor.hpp progMonitor.log(main()); #include monitor.hpp progMonitor.log(init()); Nico Josuttis C++17 @CodeHard 15
  • 42. ‹ E ,7FRPPXQLFDWLRQFRP ,QOLQH 9DULDEOHV ‡ 6WDWLF YDULDEOHV PDUNHG ZLWK inline FRXQW DV GHILQLWLRQV ± *XDUDQWHHG WR H[LVW RQO RQFH LQ WKH SURJUDP ‡ HYHQ LI LQFOXGHG PXOWLSOH WLPHV LQ PXOWLSOH WUDQVODWLRQ XQLWV ± 1R QHHG IRU 33 ILOHV WR GHILQH VWDWLFJOREDO REMHFWV class C { private: static inline bool lg = false; public: static void log (bool b) { lg = b; } C() { if (lg) std::cout C::C()n; } }; #include c.hpp int main() { C::log(true); C c1; } FKSS #include c.hpp void foo() { C c2; } ‹ E ,7FRPPXQLFDWLRQFRP $ +HDGHU2QO ::new 7UDFNHU class TrackNew { private: inline static int numMalloc = 0; QXPEHU RI QHZ RU QHZ@ FDOOV inline static long sumSize = 0; EWHV DOORFDWHG VR IDU inline static bool doTrace = false; WUDFLQJ HQDEOHG public: static void trace(bool b) { HQDEOHGLVDEOH WUDFLQJ doTrace = b; } static void status() { SULQW FXUUHQW VWDWH std::cerr numMalloc mallocs for sumSize Bytes 'n'; } static void* allocate(std::size_t size, const char* call) { LPSOHPHQWDWLRQ RI WUDFNHG DOORFDWLRQ ++numMalloc; sumSize += size if (doTrace) return std::malloc(size); } }; inline void* operator new (std::size_t size) { return TrackNew::allocate(size, ::new); } inline void* operator new[] (std::size_t size) { return TrackNew::allocate(size, ::new[]); } LQFOXGLQJ WKH KHDGHU LV HQRXJK #include tracknew.hpp int main() { RSWLRQDOO TrackNew::trace(true); TrackNew::status(); } Nico Josuttis C++17 @CodeHard 16
  • 43. ‹ E ,7FRPPXQLFDWLRQFRP ,QOLQH 9DULDEOHV ‡ PLJKW EH LQLWLDOL]HG EHIRUH PDLQ
  • 44. RU EHIRUH ILUVW XVH ‡ FDQ EH thread_local ‡ constexpr LPSOLHV inline class Monitor { public: Monitor() { } void log(const std::string msg) { } } 'HFODUH THE JOREDO PRQLWRU LQ WKH KHDGHU ILOH PLJKW EH LQFOXGHG E PXOWLSOH WUDQVODWLRQ XQLWV inline thread_local Monitor threadLocalMonitor PRQLWRUKSS ‹ E ,7FRPPXQLFDWLRQFRP static constexpr 'DWD 0HPEHUV DUH inline ‡ 6WDWLF constexpr GDWD PHPEHUV DUH inline VLQFH ± 'HFODUDWLRQV DUH GHILQLWLRQV ± %HIRUH WKH GHILQLWLRQV RIWHQ ZHUH QRW QHFHVVDU ‡ 2SWLPL]HG DZD ‡ 'HILQLWLRQ QRW QHHGHG HJ SDVVHG E YDOXH
  • 45. struct A { static constexpr int n = 5; GHFODUDWLRQ }; std::cout A::n; 2. ostream::operator(int) JHWV A::n E YDOXH
  • 46. int inc(const int i); QRWH WDNHV DUJXPHQW E UHIHUHQFH std::cout inc(A::n); PD IDLO ZLWKRXW GHILQLWLRQ 2. ZLWK JFF ±2 9LVXDO6WXGLR
  • 47. const int* p = n; SUREDEO IDLOV ZLWKRXW GHILQLWLRQ 2. ZLWK 9LVXDO6WXGLR
  • 48. SRVVLEOH GHILQLWLRQ LQ RQH WUDQVODWLRQ XQLW
  • 49. constexpr int A::n; Nico Josuttis C++17 @CodeHard 17
  • 50. ‹ E ,7FRPPXQLFDWLRQFRP static constexpr 'DWD 0HPEHUV DUH inline ‡ 6WDWLF constexpr GDWD PHPEHUV DUH inline VLQFH ± 'HFODUDWLRQV DUH GHILQLWLRQV ± %HIRUH WKH GHILQLWLRQV RIWHQ ZHUH QRW QHFHVVDU ‡ 2SWLPL]HG DZD ‡ 'HILQLWLRQ QRW QHHGHG HJ SDVVHG E YDOXH
  • 51. struct A { static constexpr int n = 5; GHFODUDWLRQ VLQFH LQOLQH GHILQLWLRQ }; std::cout A::n; 2. ostream::operator(int) JHWV A::n E YDOXH
  • 52. int inc(const int i); QRWH WDNHV DUJXPHQW E UHIHUHQFH std::cout inc(A::n); PD IDLO ZLWKRXW GHILQLWLRQ 2. ZLWK JFF ±2 9LVXDO6WXGLR
  • 53. const int* p = n; SUREDEO IDLOV ZLWKRXW GHILQLWLRQ 2. ZLWK 9LVXDO6WXGLR
  • 54. SRVVLEOH GHILQLWLRQ LQ RQH WUDQVODWLRQ XQLW
  • 55. constexpr int A::n; GHILQLWLRQ VLQFH UHGXQGDQW GHFODUDWLRQ GHSUHFDWHG
  • 56. ‡ $OZDV 2. VLQFH ‹ E ,7FRPPXQLFDWLRQFRP struct Data { std::string name; double value; }; struct Dv : Data { bool used; void print() const; }; Dv u; 2. EXW valuedone ZLWK XQGHILQHG YDOXHV Dv z{}; 2. valuedone ZLWK 0false bool b = std::is_aggregateAggr::value; WUXH Dv x{{item, 6.7}, false}; 2. VLQFH Dv y{item, 6.7, false}; 2. VLQFH XQOHVV HPSW VXEREMHFWEDVH %HIRUH WKLV LV D FODVV ZLWK LPSOLFLW GHIDXOW FRQVWUXFWRU 6LQFH WKLV LV D FODVV WKDW LV DQ DJJUHJDWH $JJUHJDWHV ZLWK %DVH ODVVHV ‡ $JJUHJDWHV QRZ FDQ KDYH SXEOLF EDVH FODVVHV ‡ ,QLWLDOL]DWLRQ ZLWK QHVWHG ^` SRVVLEOH ‡ 1HZ WSH WUDLW VWGLVBDJJUHJDWH! %HIRUH struct Dv : Data { bool used; Dv (string s, double d, bool b) { : Data{s,d}, used{b} { } }; QHFHVVDU WR HQDEOH Dv x{hi, 6.7, false}; Nico Josuttis C++17 @CodeHard 18
  • 57. ‹ E ,7FRPPXQLFDWLRQFRP $JJUHJDWH ,QLWLDOL]DWLRQ ‡ /LVW LQLWLDOL]DWLRQ LV ]HUR LQLWLDOL]DWLRQ LI QR YDOXH LV SDVVHG ± 'HIDXOW FRQVWUXFWRU IRU FODVV WSHV ± 0 false nullptr IRU IXQGDPHQWDO GDWD WSHV )'7
  • 58. struct Data { std::string name; double value; }; struct PData : Data { bool flag; }; PData a{{test1, 1.1}, false}; LQLWLDOL]H DOO HOHPHQWV PData b{test2, 2.2, false}; LQLWLDOL]H DOO HOHPHQWV PData c{}; VDPH DV {{,0.0},false} PData d{{msg}}; VDPH DV {{msg,0.0},false} PData e{{}, true}; VDPH DV {{,0.0},true} PData f; QXPHULF HOHPHQWV KDYH XQVSHFLILHG YDOXH ‹ E ,7FRPPXQLFDWLRQFRP $JJUHJDWHV ,QFRPSDWLELOLWLHV ‡ $JJUHJDWHV DUH DUUDV RU FODVV WSHV ZLWK ± QR XVHUGHFODUHG RU H[SOLFLW FRQVWUXFWRU ± QR FRQVWUXFWRU LQKHULWHG E D XVLQJ GHFODUDWLRQ ± QR SULYDWH RU SURWHFWHG QRQVWDWLF GDWD PHPEHUV ± QR YLUWXDO IXQFWLRQV ± QR YLUWXDO SULYDWH RU SURWHFWHG EDVH FODVVHV ‡ $JJUHJDWH LQLWLDOL]DWLRQ PXVW QRW XVH SULYDWH RU SURWHFWHG EDVH FODVV PHPEHUVFRQVWUXFWRUV struct Derived; struct Base { friend struct Derived; private: Base() { SULYDWH GHIDXOW FRQVWUXFWRU } }; struct Derived : Base { }; Derived d1; VWLOO 2. Derived d2{}; (5525 VLQFH 1R DJJUHJDWH DOOV LPSOLFLW GHIDXOW FRQVWUXFWRU $JJUHJDWH DOO RI SULYDWH EDVH FRQVWUXFWRU LV QRW DOORZHG Nico Josuttis C++17 @CodeHard 19
  • 59. ‹ E ,7FRPPXQLFDWLRQFRP $JJUHJDWHV ,QFRPSDWLELOLWLHV ‡ $JJUHJDWHV DUH DUUDV RU FODVV WSHV ZLWK ± QR XVHUGHFODUHG RU H[SOLFLW FRQVWUXFWRU ± QR FRQVWUXFWRU LQKHULWHG E D XVLQJ GHFODUDWLRQ ± QR SULYDWH RU SURWHFWHG QRQVWDWLF GDWD PHPEHUV ± QR YLUWXDO IXQFWLRQV ± QR YLUWXDO SULYDWH RU SURWHFWHG EDVH FODVVHV ‡ 1RWH $ GHOHWHG GHIDXOW FRQVWUXFWRU GRHVQ W GLVDEOH 1RWH DJJUHJDWH LQLWLDOL]DWLRQ KWWSVZJOLQNFZJ
  • 60. struct CData { int val; int elems[3]; }; class CppData : public CData { public: CppData() = delete; void print() const; }; CppData cd1; (5525 CppData cd2{}; (5525 ZLWK 2. VLQFH
  • 61. CppData cd3{3, 0, 8, 15}; (5525 ZLWK 2. VLQFH
  • 62. 1R DJJUHJDWH RQVWUXFWRU GLVDEOHV DQ LQLWLDOL]DWLRQ $JJUHJDWH $JJUHJDWH LQLWLDOL]DWLRQ VWLOO 2. ‹ E ,7FRPPXQLFDWLRQFRP 0DQGDWRU 592 DQG RS (OLVLRQ ‡ RS HOLVLRQ IRU LQLWLDOL]DWLRQ IURP WHPSRUDULHV SUYDOXHV
  • 63. LV UHTXLUHG VLQFH ‡ DOODEOH FRSPRYH FRQVWUXFWRU QR ORQJHU UHTXLUHG class NoCpMv { public: NoCpMv() = default; QR FRSPRYH FRQVWUXFWRU NoCpMv(const NoCpMv) = delete; NoCpMv(NoCpMv) = delete; }; void call(NoCpMv obj) { } call(NoCpMv()); 2. VLQFH QR FRSPRYH
  • 64. NoCpMv ret() { return NoCpMv(); 2. VLQFH } QR FRSPRYH
  • 65. NoCpMv x = ret(); 2. VLQFH call(ret()); 2. VLQFH call(x); VWLOO (5525 Nico Josuttis C++17 @CodeHard 20
  • 66. ‹ E ,7FRPPXQLFDWLRQFRP %HQHILWV IURP 0DQGDWRU RS (OLVLRQ ‡ 5HTXLUHG FRS HOLVLRQ KHOSV WR ± SURYLGH IDFWRULHV IRU DQ WSH ± GHDOLQJ ZLWK WSHV ZLWK GHOHWHG PRYH #include utility JHQHULF IDFWRU template typename T, typename... Args T create(Args... args) { return T{std::forwardArgs(args)...}; } #include atomic 2. VLQFH 1RWH FDQ W FRSPRYH VWGDWRPLF! REMHFWV
  • 67. auto ai = createstd::atomicint(42); class CopyOnly { public: CoypeOnly() { } CopyOnly(int) { } CopyOnly(const CopyOnly) = default; CopyOnly(CopyOnly) = delete; }; CopyOnly ret() { return CopyOnly{}; 2. VLQFH } CopyOnly x = 42; 2. VLQFH 5HPHPEHU RS FRQVWUXFWRU LV QR IDOOEDFN LI PRYH FRQVWUXFWRU LV H[SOLFLWO GHOHWHG ‹ E ,7FRPPXQLFDWLRQFRP 9DOXH DWHJRULHV VLQFH (YHU H[SUHVVLRQ LV RQH RI ‡ /9DOXH /RFDOL]DEOH YDOXH ± 9DULDEOH GDWD PHPEHU IXQFWLRQ VWULQJ OLWHUDO UHWXUQHG OYDOXH UHIHUHQFH ± DQ EH RQ WKH OHIW VLGH RI DQ DVVLJQPHQW RQO LI LW V PRGLILDEOH ‡ 359DOXH 3XUH 59DOXH IRUPHU 59DOXH
  • 68. ± $OO /LWHUDOV H[FHSW VWULQJ OLWHUDOV 42 true nullptr
  • 69. this ODPEGD UHWXUQHG QRQUHIHUHQFH UHVXOW RI FRQVWUXFWRU FDOO T()
  • 70. ‡ ;9DOXH H;SLULQJ YDOXH ± 5HWXUQHG UYDOXH UHIHUHQFH HJ E VWGPRYH
  • 72. FDVW WR UYDOXH UHIHUHQFH *HQHUDO FDWHJRULHV */9DOXH *HQHUDOL]HG /9DOXH 59DOXH JHQHUDOL]HG 59DOXH H[SUHVVLRQ UYDOXHJOYDOXH OYDOXH [YDOXH SUYDOXH Nico Josuttis C++17 @CodeHard 21
  • 73. ‹ E ,7FRPPXQLFDWLRQFRP ‡ SUYDOXHV SHUIRUP LQLWLDOL]DWLRQ ± QR WHPSRUDU REMHFW HW ‡ JOYDOXHV SURGXFH ORFDWLRQV ‡ Materialization DV D WHPSRUDU REMHFW ± SUYDOXHWR[YDOXH FRQYHUVLRQ ‡ ZKHQ ERXQG WR D UHIHUHQFH ‡ ZLWK PHPEHU DFFHVV ‡ ZLWK FRQYHUVLRQ WR EDVH 9DOXH DWHJRULHV VLQFH MyClass ret() { return MyClass(); UHWXUQV SUYDOXH QR WHPSRUDU REMHFW HW
  • 74. } MyClass x = ret(); XVHV SUYDOXH IRU LQLWLDOL]DWLRQ void callV(MyClass obj); DFFHSWV DQ YDOXH FDWHJRU void callR(const MyClass r); UHTXLUHV JOYDOXH void callM(MyClass r); UHTXLUHV [YDOXH PD EH PDWHULDOL]HG IURP SUYDOXH
  • 75. callV(ret()); SDVVHV SUYDOXH DQG XVHV LW IRU LQLWLDOL]DWLRQ RI obj callR(ret()); SDVVHV SUYDOXH PDWHULDOL]HG DV [YDOXH
  • 76. WR r callM(ret()); SDVVHV SUYDOXH PDWHULDOL]HG DV [YDOXH
  • 77. WR r H[SUHVVLRQ UYDOXHJOYDOXH OYDOXH [YDOXH SUYDOXH temporary materialization conversion ‹ E ,7FRPPXQLFDWLRQFRP FRQVWH[SU /DPEGDV ‡ /DPEGDV DUH E GHIDXOW FRQVWH[SU QRZ LI SRVVLEOH
  • 78. ± DQ EH IRUFHG ZLWK FRQVWH[SU auto squared = [](auto val) { LPSOLFLWO FRQVWH[SU VLQFH return val*val; }; std::arrayint,squared(5) a; 2. VLQFH ! VWGDUUDLQW! auto squared2 = [](auto val) constexpr { 2. VLQFH return val*val; }; auto squared3 = [](auto val) constexpr { (5525 static int calls=0; FDQ W EH FRQVWH[SU GXH WR VWDWLF return val*val; }; Nico Josuttis C++17 @CodeHard 22
  • 79. ‹ E ,7FRPPXQLFDWLRQFRP /DPEGDV DSWXULQJ this ‡ ,Q PHPEHU IXQFWLRQV FDQ DOVR SDVV this DV FDSWXUH ± LPSOLFLWO GRQH ZLWK [=] DQG [] ‡ 6LQFH *this DOORZV WR SDVV *this E YDOXH class C { private: std::string name; public: void foo() { [] { std::cout name 'n'; } (UURU [] { std::cout name 'n'; } 2. [=] { std::cout name 'n'; } 2. [this] { std::cout name 'n'; } 2. [*this] {std::cout name 'n'; } 2. VLQFH ORFDO FRS RI WKLV } }; ‹ E ,7FRPPXQLFDWLRQFRP $WWULEXWHV ‡ 1HZ $WWULEXWHV IRUPDO DQQRWDWLRQV
  • 80. [[ nodiscard ]] [[ maybe_unused ]] [[ fallthrough ]] ‡ $WWULEXWHV IRU QDPHVSDFHV DQG HQXPHUDWLRQV enum E { foobar = 0, foobat [[deprecated]] = foobar }; namespace [[deprecated]] xyz { } ‡ 8VLQJ GHFODUDWLRQV IRU DWWULEXWHV [[ using xyz : ]] Nico Josuttis C++17 @CodeHard 23
  • 81. ‹ E ,7FRPPXQLFDWLRQFRP 1HZ $WWULEXWHV ‡ GHILQHV QHZ $WWULEXWHV IRUPDO DQQRWDWLRQV
  • 82. [[nodiscard]] ± IRUFH ZDUQLQJ LI UHWXUQ YDOXHV DUH QRW XVHG ± SRUWDEOH [[gnu::warn_unused_result]] ± 3RVVLEOH H[DPSOH template class F, class... Args [[nodiscard]] future async(F f, Args... args); [[ maybe_unused ]] ± GLVDEOHG ZDUQLQJV DERXW QDPHV DQG HQWLWLHV WKDW DUH LQWHQWLRQDOO QRW XVHG ± )RU H[DPSOH [[maybe_unused]] int y = foo(); [[ fallthrough ]] ± IRU LQWHQWLRQDO VZLWFK caseV KDYLQJ VWDWHPHQWV EXW QR break; %XW RQO VLQFH XVHG LQ WKH OLEUDU ‹ E ,7FRPPXQLFDWLRQFRP 1HVWHG 1DPHVSDFH 'HILQLWLRQV ‡ 1HZ VQWD[ IRU QHVWHG QDPHVSDFH GHILQLWLRQV ± ,QVWHDG RI RX FDQ ZULWH VLQFH ‡ 1R VXSSRUW IRU QHVWHG LQOLQH QDPHVSDFHV namespace A { namespace B { namespace C { … } } } namespace A::B::C { … } )LUVW SURSRVHG LQ Nico Josuttis C++17 @CodeHard 24
  • 83. ‹ E ,7FRPPXQLFDWLRQFRP +HDS $OORFDWLRQ ZLWK $OLJQPHQW ‡ 6LQFH RSHUDWRU QHZ SURYLGHV DQ LQWHUIDFH WR GHDO ZLWK DOLJQHG GDWDWSHV ± XVHV LQ std enum class align_val_t : size_t {}; ‡ 6HYHUDO QHZ RYHUORDGV IRU RSHUDWRUV ± QHZ QHZ@ ± GHOHWH GHOHWH@ new T UHVXOWV LQWR FDOOLQJ RQH RI ZKLFKHYHU LV SURYLGHG
  • 84. operator new(sizeof(T)) operator new(sizeof(T), std::align_val_t(alignof(T))) new(adr) std::string UHVXOWV LQWR FDOOLQJ RQH RI ZKLFKHYHU LV SURYLGHG
  • 85. operator new(sizeof(std::string), adr) operator new(sizeof(std::string), std::align_val_t(alignof(std::string)), adr) ‹ E ,7FRPPXQLFDWLRQFRP ([DPSOH IRU +HDS $OORFDWLRQ ZLWK $OLJQPHQW #include new IRU align_val_t struct alignas(512) Aligned { int i; alignas(128) double d; alignas(512) char c; DOORFDWH PHPRU IRU VLQJOH REMHFW ZLWK GHIDXOW DOLJQPHQW static void* operator new (std::size_t size) { std::cout Aligned::new called with size: size n; return ::new char[size]; } DOORFDWH PHPRU IRU VLQJOH REMHFW ZLWK H[WHQGHG DOLJQPHQW static void* operator new (std::size_t size, std::align_val_t align) { std::cout Aligned::new called with size: size and align: static_castint(align) n; return ::new char[size]; } }; Aligned a; DOLJQHG IRU DGGUHVV VLQFH
  • 86. Aligned* ap = new Aligned{}; UHTXHVWV KHDS DOLJQPHQW IRU DGGUHVV VLQFH XVHG DV IDOOEDFN PD[ LQQHU DOLJQPHQW IRUFHV RXWHU DOLJQPHQW VL]HDOLJQ LQVWHDG RI HJ
  • 88. ‹ E ,7FRPPXQLFDWLRQFRP _ _has_include _ _has_include: ‡ 7HVW IRU H[LVWHQFH RI D KHDGHU ‡ +HOSV WR ZULWH SRUWDEOH FRGH ‡ )RU H[DPSOH #if _ _has_include(optional) # include optional # define HAS_OPTIONAL 1 #elif _ _has_include(experimental/optional) # include experimental/optional # define HAS_OPTIONAL 1 # define OPTIONAL_IS_EXPERIMENTAL 1 #else # define HAS_OPTIONAL 0 #endif ‹ E ,7FRPPXQLFDWLRQFRP 87) KDUDFWHU /LWHUDOV ‡ (QFRGLQJ SUHIL[ X LHOGV char ZLWK 87) YDOXH ± VLQFH ‡ L'6' IRU ZFKDUBW OLWHUDOV WZR RU IRXU EWHV QR VSHFLILF FKDUDFWHU VHW
  • 89. ± VLQFH ‡ u'6' IRU FKDUBW OLWHUDOV WZREWH 87)
  • 90. ‡ U'6' IRU FKDUBW OLWHUDOV IRXUEWH 87)
  • 91. ± VLQFH ‡ u8'6' IRU 87) FKDUDFWHU OLWHUDOV ± $OUHDG IRU VWULQJ OLWHUDOV VLQFH ‡ SURYLGHG ± WKH 87) OLWHUDO RQO KDV D VLQJOH FKDUDFWHU ± LWV YDOXH LV UHSUHVHQWDEOH ZLWK D VLQJOH 87) FRGH XQLW LH LV D 86$6,, FKDUDFWHU
  • 92. u8'ö' (5525 WZR EWHVFRGHXQLWV LQ 87) KH[ %
  • 93. 2QO QHFHVVDU ZKHQ WKH VRXUFHH[HFXWLRQ FKDUDFWHU VHW LV QRW 86$6,, HJ FRPSLOLQJ XQGHU DQ (%', FKDUDFWHU VHW
  • 95. ‹ E ,7FRPPXQLFDWLRQFRP +H[DGHFLPDO )ORDWLQJ3RLQW /LWHUDOV ‡ 0x DOVR IRU IORDWLQJSRLQW OLWHUDOV ± VLJQLILFDQG LV JLYHQ LQ KH[DGHFLPDO ± H[SRQHQW LV JLYHQ LQ GHFLPDO DQG LQWHUSUHWHG ZLWK UHVSHFW WR EDVH ‡ $V DOUHDG LQ ‡ $V WKH std::hexfloat LRVWUHDP IRUPDW VLQFH
  • 96. std::initializer_listdouble values { 0x1p4, 0xA, 0xAp2, 5e0, 0x1.4p+2, 1e5, 0x1.86Ap+16, 0xC.68p+2, }; for (double d : values) { std::cout dec: std::setw(6) std::defaultfloat d hex: std::hexfloat d 'n'; } 2XWSXW dec: 16 hex: 0x1p+4 dec: 10 hex: 0x1.4p+3 dec: 40 hex: 0x1.4p+5 dec: 5 hex: 0x1.4p+2 dec: 5 hex: 0x1.4p+2 dec: 100000 hex: 0x1.86ap+16 dec: 100000 hex: 0x1.86ap+16 dec: 49.625 hex: 0x1.8dp+5 ‹ E ,7FRPPXQLFDWLRQFRP 6WDWLFBDVVHUW
  • 98. QR ORQJHU UHTXLUHV WR SDVV D WH[W PHVVDJH ± 3ULQWLQJ D GHIDXOW WH[W PHVVDJH LI DVVHUWLRQ LV YLRODWHG static_assert(sizeof(int)=4, integers are too small); 2. VLQFH static_assert(sizeof(int)=4); 2. VLQFH template typename T class C { static_assert(std::is_default_constructibleT::value, class C: element type T must be default-constructible); static_assert(std::is_default_constructibleT::value); 2. VLQFH }; Nico Josuttis C++17 @CodeHard 27
  • 99. ‹ E ,7FRPPXQLFDWLRQFRP 7HPSODWH )HDWXUHV ‹ E ,7FRPPXQLFDWLRQFRP 0RUH RQYHQLHQFH IRU 7SH 7UDLWV UHWXUQLQJ 9DOXHV ‡ 6LQFH VKRUWFXWV ZLOO EH SURYLGHG IRU WSH WUDLWV UHWXUQLQJ YDOXHV ± ,QVWHDG RI std::is_constT::value RX FDQ XVH std::is_const_vT ‡ 7KLV LV GRQH YLD YDULDEOH WHPSODWHV ± DYDLODEOH VLQFH namespace std { template typename T constexpr bool is_const_v = is_constT::value; } Nico Josuttis C++17 @CodeHard 28
  • 100. ‹ E ,7FRPPXQLFDWLRQFRP RPSLOH7LPH if ‡ SURYLGHV D FRPSLOHWLPH LI ± FRQVWH[SU LI ± 7KH then RU else SDUW PD EHFRPH D discarded statement template typename T std::string asString(T x) { if constexpr(std::is_arithmetic_vT) { return std::to_string(x); } else if constexpr(std::is_same_vT, std::string) { return x; } else { return std::string(x); } } std::cout asString(42) 'n'; std::cout asString(std::string(hello)) 'n'; std::cout asString(hello) 'n'; $OO H[DPSOH FDOOV ZRXOG EH LQYDOLG ZKHQ XVLQJ UXQWLPH LI ‹ E ,7FRPPXQLFDWLRQFRP RPSLOH7LPH if ZLWK ,QLWLDOL]HUV template typename Coll, typename Mutex void process(const Coll coll, Mutex m) { if constexpr (std::lock_guard lg{m}; std::is_pointer_vtypename Coll::value_type) { LPSOHPHQW SURFHVVLQJ IRU SRLQWHU HOHPHQWV } else { LPSOHPHQW SURFHVVLQJ IRU RWKHU HOHPHQWV } } std::vectorint vi; std::mutex viMutex; process(vi, viMutex); std::vectorint* vp; std::mutex vpMutex; process(vp, vpMutex); ,QLWLDOL]DWLRQ PLJKW EH HYDOXDWHG DW UXQWLPH Nico Josuttis C++17 @CodeHard 29
  • 101. ‹ E ,7FRPPXQLFDWLRQFRP RPSLOH7LPH if 2XWVLGH 7HPSODWHV ‡ if constexpr DOVR FDQ EH XVHG LQ QRQWHPSODWH FRGH ‡ $OO FRGH LQ GLVFDUGHG VWDWHPHQWV PXVW EH YDOLG template typename T void foo(T t); int main() { if constexpr(std::numeric_limitschar::is_signed) { foo(42); 2. static_assert(std::numeric_limitschar::is_signed, char is unsigned?); DOZDV IDLOV LI FKDU LV XQVLJQHG } else { undeclared(42); DOZDV HUURU LI XQGHFODUHG
  • 102. QRW GHFODUHG static_assert(!std::numeric_limitschar::is_signed, char is signed?); DOZDV IDLOV LI FKDU LV VLJQHG } } 7KLV SURJUDP QHYHU VXFFHVVIXOO FRPSLOHV ‹ E ,7FRPPXQLFDWLRQFRP RPSLOH7LPH if ‡ 7KH discarded statement PXVW VWLOO EH YDOLG ± 3HUIRUPV WKH ILUVW SKDVH RI WHPSODWH WUDQVODWLRQ GHILQLWLRQ SKDVH
  • 103. ± DOOV QRW GHSHQGLQJ RQ WHPSODWH SDUDPHWHUV DUH LQVWDQWLDWHG template typename T void foo(T t) { if constexpr(std::is_integral_vT) { if (t 0) { foo(t-1); UHFXUVLYH FDOO 2. } } else { undeclared(); DOZDV (5525 LI QRW GHFODUHG HYHQ LI GLVFDUGHG
  • 104. undeclared(t); (5525 LI QRW GHFODUHG DQG QRW GLVFDUGHG LH T LV QRW LQWHJUDO
  • 105. static_assert(sizeof(int)4, small int); PD DVVHUW HYHQ LI GLVFDUGHG static_assert(sizeof(T)4, small T); PD DVVHUW RQO LI QRW GLVFDUGHG } } ‡ RPSLOHWLPH HUURU HYHQ LI foo() QHYHU FDOOHG ([FHSW ZLWK 9 Nico Josuttis C++17 @CodeHard 30
  • 106. ‹ E ,7FRPPXQLFDWLRQFRP 7HPSODWHV 7ZR3KDVH 7UDQVODWLRQ :LWKRXW LQVWDQWLDWLRQ DW definition time ± 6QWD[ HUURUV DUH GLVFRYHUHG VXFK DV PLVVLQJ VHPLFRORQV
  • 107. ± )RU FRGH WKDW GRHV QRW GHSHQG RQ WHPSODWH SDUDPHWHUV ‡ XVH RI XQNQRZQ QDPHV WSH QDPHV IXQFWLRQ QDPHV
  • 108. LV GLVFRYHUHG ‡ VWDWLF DVVHUWLRQV DUH FKHFNHG $W instantiation time ± $OO FRGH GHSHQGLQJ RQ WHPSODWH SDUDPHWHUV LV GRXEOHFKHFNHG templatetypename T void foo(T t) { undeclared(); VW SKDVH HUURU LI undeclared() XQNQRZQ undeclared(t); QG SKDVH HUURU LI undeclared(T) XQNQRZQ static_assert(sizeof(int)4, small int); VW SKDVH HUURU LI VL]HRILQW
  • 109. ! static_assert(sizeof(T)4, small T); QG SKDVH HUURU LI VL]HRI7
  • 110. ! static_assert(false, oops); DOZDV IDLOV ZKHQ WHPSODWH LV FRPSLOHG HYHQ LI QRW FDOOHG
  • 111. } ‡ FRPSLOHWLPH HUURUV HYHQ LI foo() QHYHU FDOOHG ([FHSW ZLWK 9 ‹ E ,7FRPPXQLFDWLRQFRP 7HPSODWHV 7ZR3KDVH 7UDQVODWLRQ DQG 9LVXDO ‡ 9LVXDO E GHIDXOW
  • 112. GRHV QR ILUVWSKDVH ORRNXS DW DOO ‡ 9LVXDO 6WXLR VLQFH
  • 113. DOORZV ILUVWSKDVH ORRNXS ZLWK /permissive- ± KWWSVEORJVPVGQPLFURVRIWFRPYFEORJWZRSKDVHQDPHORRNXSVXSSRUWFRPHVWRPVYF ± 8QGHFODUHG IXQFWLRQV DQG static_assert() VWLOO DOZDV LJQRUHG void func(void*) { std::cout calls func(void*) (first-phase lookup)n; } templatetypename T void callfunc(T) { func(0); ILUVWSKDVH ORRNXS VKRXOG ILQG RQO func(void*) KHUH } void func(int) { std::cout calls func(int) (second-phase lookup)n; } int main() { callfunc(42); FDOOV IXQFYRLG
  • 114. ZLWK FRUUHFW WZRSKDVH ORRNXS } ‡ JFF FODQJ DQG 96 ZLWK /permissive- FDOOV func(void*) VW SKDVH ORRNXS
  • 115. ‡ 96 96 96 ZLWKRXW /permissive-
  • 118. ‹ E ,7FRPPXQLFDWLRQFRP RPSLOH7LPH LI DQG 9DULDGLF 7HPSODWHV template typename T, typename... Types void print (T firstArg, Types... args) { std::cout firstArg 'n'; if (sizeof...(args) 0) { print(args...); (UURU QHHGV SULQW
  • 119. LI sizeof...(args)==0 } } template typename T, typename... Types void print (T firstArg, Types... args) { std::cout firstArg 'n'; if constexpr(sizeof...(args) 0) { VLQFH print(args...); 2. QRW LQVWDQWLDWHG LI sizeof...(args)==0 } } ‹ E ,7FRPPXQLFDWLRQFRP )ROG ([SUHVVLRQV ‡ $SSO ELQDU RSHUDWRUV WR DOO HOHPHQWV RI D SDUDPHWHU SDFN template typename... T auto foldSum1 (T... s){ return (... + s); s1 s2 s3 } template typename... T auto foldSum2 (T... s){ return (0 + ... + s); 0 s1 s2 s3 } auto i = foldSum1(17, 4); auto j = foldSum1(i, 1000, i); foldSum1(hi, hi, hi); (5525 foldSum1(hi, hi, std::string(hi)); (5525 foldSum1(std::string(hi), hi, hi); 2. KLKLKL foldSum1(); (5525 auto i = foldSum2(17, 4); auto j = foldSum2(i, 1000, i); auto k = foldSum2(); foldSum2(std::string(hi), hi, hi); (5525 Nico Josuttis C++17 @CodeHard 32
  • 120. ‹ E ,7FRPPXQLFDWLRQFRP )ROG ([SUHVVLRQV ‡ $SSO ELQDU RSHUDWRUV WR DOO HOHPHQWV RI D SDUDPHWHU SDFN ‡ 6XSSRUWHG VQWD[ (... OP pack) (init OP ... OP pack) (pack OP ...) (pack OP ... OP init) ‡ )RU RSHUDWRUV || DQG , WKH SDFN PLJKW HYHQ EH HPSW ± ,Q WKDW FDVH LHOGV true false void() template typename... T auto foldSum (T... s){ return (... + s); s1 s2 s3 } template typename... T auto foldSum (T... s){ return (0 + ... + s); even works if sizeof...(s)==0 } (( pack1 OP pack2 ) OP pack3 ) ((( init OP pack1 ) OP pack2 ) OP pack3 ) VDPH IURP ULJKW WR OHIW ‹ E ,7FRPPXQLFDWLRQFRP 8VLQJ )ROG ([SUHVVLRQV template typename... Args void printAll (Args... args) { (std::cout ... args) ' '; } templatetypename T void print (T arg) { std::cout arg ' '; } templatetypename T, typename... Types void print (T firstArg, Types... args) { print(firstArg); print(args...); } std::string str = world; print(7.5, hi, str); KL ZRUOG = print(7.5); print(hi, str); = print(7.5); print(hi) print(str); RGH HIIHFWLYHO FRPSLOHG std::string str = world; std::cout hi ' '; std::cout 7.5 ' '; std::cout str ' '; std::string str = world; printAll(7.5, hi, str); KLZRUOG Nico Josuttis C++17 @CodeHard 33
  • 121. ‹ E ,7FRPPXQLFDWLRQFRP 8VLQJ )ROG ([SUHVVLRQV template typename... Args void printAll (Args... args) { (std::cout ... args) ' '; } std::string str = world; printAll(7.5, hi, str); KLZRUOG templatetypename T const T spaceBefore(T arg) { std::cout ' '; return arg; } template typename First, typename... Args void printSpaced(First arg0, Args... args) { std::cout arg0; (std::cout ... spaceBefore(args)) ' '; } std::string str = world; printSpaced(7.5, hi, str); KL ZRUOG ‹ E ,7FRPPXQLFDWLRQFRP )ROG ([SUHVVLRQV IRU )XQFWLRQ DOOV #include iostream struct A { void print() { std::cout An; } }; struct B { void print() { std::cout Bn; } }; struct C { void print() { std::cout Cn; } }; templatetypename... Bases struct MultiBase : private Bases... { void print() { (... , Bases::print()); } }; int main() { MultiBaseA,B,C mb; mb.print(); } H[SDQGV WR A::print(), B::print(), C::print(); Nico Josuttis C++17 @CodeHard 34
  • 122. ‹ E ,7FRPPXQLFDWLRQFRP )ROG ([SUHVVLRQV IRU 0HPEHU 3RLQWHUV GHILQH ELQDU WUHH VWUXFWXUH struct Node { int value; Node* left; Node* right; }; auto left = Node::left; auto right = Node::right; WUDYHUVH WUHH XVLQJ IROG H[SUHVVLRQ template typename T, typename... TP X* traverse (T np, TP... paths){ return (np -* ... -* paths); QS ! SDWKV ! SDWKV } LQLW DQG XVH ELQDU WUHH VWUXFWXUH X* root = new Node{0}; root-left = new Node{1}; root-left-right = new Node{2}; auto p = traverse(root, left, right); ‹ E ,7FRPPXQLFDWLRQFRP )ROG ([SUHVVLRQV IRU 7SHV ‡ )ROG H[SUHVVLRQV FDQ DOVR DSSO WR WSHV templatetypename T1, typename... TN struct IsHomogeneous { static constexpr bool value = (std::is_sameT1,TN::value ...); }; using Size = int; IsHomogeneousint, Size, decltype(42)::value templatetypename T1, typename... TN constexpr bool isHomogeneous(T1, TN...) { return (std::is_sameT1,TN::value ...); } isHomogeneous(43, -1, hello, nullptr) H[SDQGV WR std::is_sameint,Size::value std::is_sameint,decltype(42)::value H[SDQGV WR std::is_sameint,int::value std::is_sameint,const char*::value std::is_sameint,std::nullptr_t::value Nico Josuttis C++17 @CodeHard 35
  • 123. ‹ E ,7FRPPXQLFDWLRQFRP ODVV 7HPSODWH $UJXPHQW 'HGXFWLRQ ‡ ODVV WHPSODWH SDUDPHWHU WSHV FDQ QRZ EH GHGXFHG DFFRUGLQJ WR DUJXPHQWV SDVVHG WR WKH FRQVWUXFWRU templatetypename T class complex; std::cout std::complexint{5,3}; 2. DOO YHUVLRQV std::cout std::complex{5,3}; 2. VLQFH GHGXFHV VWGFRPSOH[LQW! std::cout std::complex(5,3); 2. VLQFH GHGXFHV VWGFRPSOH[LQW! std::cout std::complex(5,3.3); (5525 DUJV GR QRW KDYH WKH VDPH WSH 7 std::mutex mx; std::lock_guard lg(mx); 2. VLQFH GHGXFHV std::lock_guardstd::mutex ‹ E ,7FRPPXQLFDWLRQFRP 1R 3DUWLDO $UJXPHQW 'HGXFWLRQ IRU ODVV 7HPSODWHV ‡ 3DUWLDO FODVV WHPSODWH DUJXPHQW GHGXFWLRQ LV QRW SRVVLEOH ± 6SHFLI DOO RU GHGXFH DOO WHPSODWH SDUDPHWHUV ZLWKRXW GHIDXOWV
  • 124. template typename T1, typename T2, typename T3 = T2 class C { public: C (T1 x = T1{}, T2 y = T2{}, T3 z = T3{}); FRQVWUXFWRU IRU RU DUJXPHQWV }; Cstring,string,int c0; 2. 77 DUH VWULQJ 7 LV LQW Cstring,string,int c1(hi,guy,42); 2. 77 DUH VWULQJ 7 LV LQW Cint,string c2(52,my); 2. 7 LV LQW7 DQG 7 DUH VWULQJV Cstring,string c3(hi,my,guy); 2. 777 DUH VWULQJV Cstring,string c4(hi,my,42); (UURU LV QRW D VWULQJ C c5; (UURU 7 DQG 7 XQGHILQHG C c6(hi); (UURU 7 XQGHILQHG C c7(22,44.3); 2. VLQFH 7 LV LQW 7 DQG 7 DUH GRXEOH C c8(22,44.3,hi); 2. VLQFH 7 LV LQW 7 LV GRXEOH 7 LV FRQVW FKDU C c9(hi,guy); 2. VLQFH 7 7 DQG 7 DUH FRQVW FKDU Cstring c10(hi,my); (UURU RQO 7 H[SOLFLWO GHILQHG C c11(22,44.3); (UURU QHLWKHU 7 QRU 7 H[SOLFLWO GHILQHG C c12(22,44.3,42); (UURU QHLWKHU 7 QRU 7 H[SOLFLWO GHILQHG Nico Josuttis C++17 @CodeHard 36
  • 125. ‹ E ,7FRPPXQLFDWLRQFRP $SSOLQJ $UJXPHQW 'HGXFWLRQ IRU ODVV 7HPSODWHV std::cout std::complex(5,3); 2. VLQFH GHGXFHV D VWGFRPSOH[LQW! std::cout std::complex(5,3.3); (UURU DUJV GR QRW KDYH WKH VDPH WSH std::mutex mx; std::lock_guard lg(mx); 2. VLQFH GHGXFHV std::lock_guardstd::mutex std::tupleint t(42, 43); VWLOO HUURU JRRG
  • 126. FUHDWLQJ VHW ZLWK VSHFLILF VRUWLQJ FULWHULRQ std::setCust coll([](const Cust x, const Cust y) { VWLOO HUURU WRR EDG
  • 127. return x.name() y.name(); }); auto sortcrit = [](const Cust x, const Cust y) { return x.name() y.name(); }; std::setCust, decltype(sortcrit) coll(sortcrit); 2. 0RWLYDWLQJ H[DPSOH DJDLQVW DOORZLQJ SDUWLDO GHGXFWLRQ ‹ E ,7FRPPXQLFDWLRQFRP 'HGXFLQJ 7SH RI /DPEGDV LQ ODVV 7HPSODWHV #include utility IRU std::forward() templatetypename CB class CountCalls { private: CB callback; FDOOEDFN WR FDOO long calls = 0; FRXQWHU IRU FDOOV public: CountCalls(CB cb) : callback(cb) { } templatetypename... Args auto operator() (Args... args) { ++calls; return callback(std::forwardArgs(args)...); } long count() const { return calls; } }; CountCalls sc([](auto x, auto y) { return x y; }); std::sort(v.begin(), v.end(), std::ref(sc)); std::cout sorted with sc.count() callsn; HQDEOHV WR GHGXFH WKH WSH CB RI D SDVVHG ODPEGDIXQFWRU GHGXFHV CountCallsTypeOfLambda Nico Josuttis C++17 @CodeHard 37
  • 128. ‹ E ,7FRPPXQLFDWLRQFRP ODVV 7HPSODWH $UJXPHQW 'HGXFWLRQ RSLHV E 'HIDXOW ‡ ODVV $UJXPHQW 7HPSODWH 'HGXFWLRQ RSLHV E 'HIDXOW ± $IWHU CT x; C{x} GHGXFHV WR CT{x} LQVWHDG RI CCT{x} std::vector v{1, 2, 3}; YHFWRULQW! std::vector a{v}; YHFWRULQW! std::vector b(v); YHFWRULQW! std::vector c = {v}; YHFWRULQW! auto d = std::vector{v}; YHFWRULQW! std::vector v2{v, v}; YHFWRUYHFWRULQW!! LQVWHDG RI YHFWRUYHFWRULQW!! ‹ E ,7FRPPXQLFDWLRQFRP 'HGXFWLRQ *XLGHV ‡ 'HGXFWLRQ JXLGHV FDQ DGGIL[ GHGXFWLRQV ± 0XVW EH LQ WKH VDPH VFRSH HJ QDPHVSDFH VWG
  • 129. templatetypename T class complex; DV LQ FRPSOH[! std::cout std::complexint{5,3}; 2. DOO YHUVLRQV std::cout std::complex{5,3}; 2. VLQFH GHGXFHV D VWGFRPSOH[LQW! std::cout std::complex(5,3); 2. VLQFH GHGXFHV D VWGFRPSOH[LQW! std::cout std::complex(5,3.3); (UURU DUJV GR QRW KDYH WKH VDPH WSH 7 ,I ZH G KDYH namespace std { templatetypename T1, typename T2 complex(T1,T2) - complexcommon_type_tT1,T2; } WKHQ std::cout std::complex(5,3.3); ZRXOG EH 2. DQG GHGXFH WR VWGFRPSOH[GRXEOH! $ XVHUGHILQHG GHGXFWLRQ JXLGH IRU DQ VWDQGDUG OLEUDU FODVV WHPSODWH UHVXOW LQWR XQGHILQHG EHKDYLRU Nico Josuttis C++17 @CodeHard 38
  • 130. ‹ E ,7FRPPXQLFDWLRQFRP 8VLQJ 'HGXFWLRQ *XLGHV LQ 3UDFWLFH RQVWUXFWRUV ZLWK UHIHUHQFHV ‡ 8VH GHGXFWLRQ JXLGHV WR GHFD WHPSODWH SDUDPHWHU WSHV ± 6WULQJ OLWHUDOV GHGXFH WR SRLQWHU WSHV ‡ 3DUDPHWHUV DUH VWLOO SDVVHG E UHIHUHQFH templatetypename T class MyType { private: T value; public: MyType(const T v) : value{v} { } MyType(T v) : value{std::move(v)} { } }; GHGXFWLRQ JXLGH IRU WKH FRQVWUXFWRUV templatetypename T MyType(T) - MyTypeT; MyType x{hi} HTXLYDOHQW WR MyTypeconst char* x{hi} ‡ (UURU ZLWKRXW GHGXFWLRQ JXLGH ! const char value[3]; ‡ (UURU ZLWK std::decay_tT value; ! char* value; RQVWUXFWRUV VKRXOG PRYH LQLWLDOL]H PHPEHUV IURP EYDOXH SDUDPHWHUV MyType(T v) : value{v} { } ‹ E ,7FRPPXQLFDWLRQFRP 'HGXFWLRQ *XLGHV ‡ 'HGXFWLRQ JXLGHV ± PD QRW EH WHPSODWHV ± PD QRW FDOO D FRQVWUXFWRU HJ IRU DJJUHJDWHV
  • 131. templatetypename T struct S { T val; }; S(const char*) - Sstd::string; PDS 6! IRU VWULQJ OLWHUDOV WR 6VWGVWULQJ! S s1{hello}; 2. VDPH DV Sstd::string s1{hello}; S s2 = {hello}; 2. VDPH DV Sstd::string s2 = {hello}; S s3 = S{hello}; 2. S s4 = hello; (5525 QR DJJUHJDWH LQLWLDOL]DWLRQ
  • 132. void foo(Sstd::string); foo(S{hello}); 2. VDPH DV foo(Sstd::string{hello}); foo({hello}); 2. GRHV QRW QHHG D GHGXFWLRQ JXLGH foo(hello); (5525 QR DJJUHJDWH LQLWLDOL]DWLRQ
  • 134. ‹ E ,7FRPPXQLFDWLRQFRP ([SOLFLW 'HGXFWLRQ *XLGHV ‡ 'HGXFWLRQ *XLGHV FDQ EH H[SOLFLW ± $IIHFW RQO H[SOLFLW FRQYHUVLRQV ‡ 1R LPSOLFLW FRQYHUVLRQV templatetypename T struct S { T val; }; explicit S(const char*) - Sstd::string; PDS 6! IRU VWULQJ OLWHUDOV WR 6VWGVWULQJ! QRW IRU LPSOLFLW FRQVWUXFWLRQ
  • 135. S s1{hello}; 2. VDPH DV Sstd::string s1{hello}; S s2 = {hello}; (5525 LPSOLFLW FRQYHUVLRQ
  • 136. S s3 = S{hello}; 2. S s4 = {S{hello}}; 2. void foo(Sstd::string); foo(S{hello}); 2. VDPH DV foo(Sstd::string{hello}); foo({hello}); 2. GRHV QRW QHHG D GHGXFWLRQ JXLGH foo(hello); (5525 QR DJJUHJDWH LQLWLDOL]DWLRQ
  • 138. 1R YDOLG DJJUHJDWH LQLWLDOL]DWLRQ (UURU
  • 139. ,QYDOLG QHVWHG LPSOLFLW XVHUGHILQHG FRQYHUVLRQ $JJUHJDWHVODVVHV DQG $UJXPHQW 'HGXFWLRQ (UURU
  • 140. DQ W XVH DUUD DV LQLWLDOL]HU template typename T struct AR { T val; AR(const T s) : val(s) { } }; AR s1(hi); AR s2{hi}; AR s3 = hi; AR s4 = {hi}; ARstd::string s5 = {hi}; AR(const char*) - ARstd::string; AR s1(hi); AR s2{hi}; AR s3 = hi; AR s4 = {hi}; ARstd::string s5 = {hi}; 2. VWULQJ 2. VWULQJ (5525
  • 142. (5525
  • 143. (5525
  • 144. (5525
  • 145. template typename T struct AV { T val; AV(T s) : val(s) { } }; AV s1(hi); AV s2{hi}; AV s3 = hi; AV s4 = {hi}; AVstd::string s5 = {hi}; AV(const char*) - AVstd::string; AV s1(hi); AV s2{hi}; AV s3 = hi; AV s4 = {hi}; AVstd::string s5 = {hi}; 2. FRQVW FKDU 2. FRQVW FKDU 2. FRQVW FKDU 2. FRQVW FKDU 2. VWULQJ 2. VWULQJ (5525
  • 146. 2. VWULQJ template typename T struct A { T val; }; A i1{42}; Aint i2{42}; A s1(hi); A s2{hi}; A s3 = hi; A s4 = {hi}; Astd::string s5 = {hi}; A(const char*) - Astd::string; A s1(hi); A s2{hi}; A s3 = hi; A s4 = {hi}; Astd::string s5 = {hi}; (5525
  • 148. 2. VWULQJ (5525 2. (5525 (5525 (5525 (5525 struct S { S(std::string s); }; S x = hi; (UURU Nico Josuttis C++17 @CodeHard 40
  • 149. ‹ E ,7FRPPXQLFDWLRQFRP 'HGXFWLRQ *XLGHV LQ WKH /LEUDU ‡ 7R GHFD DQG VXSSRUW PHPEHU WHPSODWHV ± pair tuple optional ‡ 'LVDEOHG IRU SRLQWHUV GXH WR DUUD WSH FODVK
  • 150. ± unique_ptr shared_ptr ‡ FRQYHUVLRQV IURP weak_ptrunique_ptr WR shared_ptr ‡ ,QLWLDOL]H IURP UDQJH ± FRQWDLQHUV H[FHSW array
  • 151. VWULQJV UHJH[ ‡ 2WKHU ± std::array a {42,45,77} ! std::arrayint,3 ± RQWDLQHU DGDSWHUV GHGXFH SDVVHG FRQWDLQHU WSHV ± RSLQJ IRU DOO ORFN JXDUG FODVVHV ‹ E ,7FRPPXQLFDWLRQFRP 'HGXFWLRQ *XLGHV LQ WKH /LEUDU ‡ 'HGXFWLRQ JXLGHV FDQ DGGIL[ GHGXFWLRQV ‡ 6RPH DUH SUHGHILQHG ‡ )RU H[DPSOH OHW VWGYHFWRU! GHGXFH HOHPHQW WSH IURP LQLWLDOL]LQJ LWHUDWRUV namespace std { templatetypename Iterator vector(Iterator, Iterator) - vectortypename iterator_traitsIterator::value_type; } std::setfloat s; std::vector(s.begin(), s.end()); 2. GHGXFHV std::vectorfloat Nico Josuttis C++17 @CodeHard 41
  • 152. ‹ E ,7FRPPXQLFDWLRQFRP 'HGXFWLRQ *XLGHV LQ WKH /LEUDU ‡ 'HGXFWLRQ JXLGHV FDQ DGGIL[ GHGXFWLRQV ‡ 6RPH DUH SUHGHILQHG ‡ )RU H[DPSOH OHW VWGDUUD! GHGXFH WKHLU QXPEHU RI HOHPHQWV PXVW KDYH VDPH WSH
  • 153. namespace std { templatetypename T, typename... U array(T, U...) - arrayenable_if_t(is_same_vT,U ...), T, (1 + sizeof...(U)); } std::array a{42,45,77}; 2. GHGXFHV std::arrayint,3 std::array a{42,45,77.7}; (UURU WSHV GLIIHU )ROG ([SUHVVLRQ ‹ E ,7FRPPXQLFDWLRQFRP 'HGXFWLRQ *XLGHV IRU 6PDUW 3RLQWHUV ‡ make_shared() DQG make_unique() DUH VWLOO XVHIXO ± FODVV WHPSODWH DUJXPHQW GHGXFWLRQ LV QRW HQDEOHG WKHUH ,) :( :28/' +$9( GHGXFWLRQ JXLGH IRU VKDUHG SRLQWHU LQLWLDOL]DWLRQ namespace std{ templatetypename Y shared_ptr(Y*) - shared_ptrY; } std::shared_ptrint sp{new int(7)}; 2. std::shared_ptr sp{new int(7)}; 2. GHGXFHV shared_ptrint std::shared_ptr sp{new int[10]}; 2236 GHGXFHV shared_ptrint namespace std { templatetypename T class shared_ptr { public: constexpr shared_ptr() noexcept; templatetypename Y explicit shared_ptr(Y* p); }; } Nico Josuttis C++17 @CodeHard 42
  • 154. ‹ E ,7FRPPXQLFDWLRQFRP 'HGXFWLRQ *XLGHV 2YHUORDGLQJ ‡ 'HGXFWLRQ JXLGH GHILQH WHPSODWH SDUDPHWHUV ‡ RX FDQ RYHUORDG GHGXFWLRQ JXLGHV templatetypename T struct C { C(T) { } }; templatetypename T C(const T) - Cdouble; templatetypename T C(T) - Clong; templatetypename T C(T) - Cint; C c1(42); GHGXFHV LQW! int x = 42; C c2(x); GHGXFHV ORQJ! C c3(std::move(x)); GHGXFHV LQW! const int c = 42; C c4(c); GHGXFHV GRXEOH! C c5(oops); (5525 FDQ W FRQYHUW FRQVW FKDU@ WR GRXEOH ‹ E ,7FRPPXQLFDWLRQFRP 8VLQJ 'HFODUDWLRQV DUH /LVWV QRZ ‡ 8VLQJ GHFODUDWLRQV FDQ EH OLVWV QRZ ± 6LGH HIIHFW RI SDFN H[SDQVLRQV LQ XVLQJ GHFODUDWLRQV class Base { public: void a(); void b(); void c(); }; class Derived : private Base { public: using Base::a, Base::b, Base::c; }; Derived d; d.a(); d.b(); d.c(); Nico Josuttis C++17 @CodeHard 43
  • 155. ‹ E ,7FRPPXQLFDWLRQFRP 3DFN ([SDQVLRQ LQ using 'HFODUDWLRQV #include string #include unordered_set class Customer { std::string name; public: Customer(const std::string n) : name(n) { } std::string getName() const { return name; } }; struct CustomerEq { bool operator() (const Customer c1, const Customer c2) const { return c1.getName() == c2.getName(); } }; struct CustomerHash { std::size_t operator() (const Customer c) const { return std::hashstd::string()(c.getName()); } }; template typename... Bases struct Overloader : Bases... { using Bases::operator()...; 2. VLQFH }; using CustomerOP = OverloaderCustomerHash,CustomerEq; FRPELQH KDVKHU DQG LQ RQH WSH std::unordered_setCustomer,CustomerHash,CustomerEq coll1; std::unordered_setCustomer,CustomerOP,CustomerOP coll2; ‹ E ,7FRPPXQLFDWLRQFRP ODULILHG ,QKHULWLQJ RQVWUXFWRUV ‡ 6HYHUDO FODULILFDWLRQV RQ LQKHULWLQJ FRQVWUXFWRUV ± using Base::Base ‡ DGRSWV DOO FRQVWUXFWRUV IURP WKH EDVH FODVVHV ‡ RQVWUXFWRUV IRU 7 FDOO ± Base::Base(T) IRU PDWFKLQJ WSH ± Base::Base() IRU RWKHU WSHV ZUDS DQ FODVV E DGRSWLQJ DOO RI LWV FRQVWUXFWRUV ZKLOH ZULWLQJ D PHVVDJH WR WKH VWDQGDUG ORJ ZKHQHYHU DQ REMHFW LV GHVWURHG templatetypename T struct Log : public T { using T::T; LQKHULW DOO FRQVWUXFWRUV IURP FODVV 7 ~Log() { std::clog Destroying wrapper 'n'; } }; Nico Josuttis C++17 @CodeHard 44
  • 156. ‹ E ,7FRPPXQLFDWLRQFRP 9DULDGLF using 'HFODUDWLRQV DQG ,QKHULWHG RQVWUXFWRUV templatetypename T class Base { T value{}; public: Base() { } Base(const T v) : value{v} { } Base operator= (const T v) { value = v; return *this; } }; templatetypename... Types class Multi : private BaseTypes... { public: GHULYH DOO FRQVWUXFWRUV using BaseTypes::Base...; GHULYH DOO DVVLJQPHQW RSHUDWRUV using BaseTypes::operator=...; }; using MultiISP = Multiint,std::string,void*; std::cout std::is_base_of_vBaseint, MultiISP; WUXH MultiISP m1 = 42; MultiISP m2{hello}; 2. HUURU ZLWK MultiISB v2=hello GXH WR WZR XVHUGHILQHG FRQYHUVLRQV
  • 157. MultiISP m3 = nullptr; m3 = 42; 2. ZRXOG DOVR ZRUN ZLWKRXW using operator=...
  • 158. m2 = world; 2. GXH WR using operator=... DOOV ‡ Base::Base(T) IRU PDWFKLQJ WSH ‡ Base::Base() IRU RWKHU WSHV 0XOWL,6% 0XOWLLQWVWGVWULQJERRO!
  • 159. %DVHLQW! %DVHVWGVWULQJ! %DVHERRO! ‹ E ,7FRPPXQLFDWLRQFRP 6WULQJV DV 7HPSODWH $UJXPHQWV ‡ 6LQFH QRQWSH WHPSODWH SDUDPHWHUV FDQ EH LQVWDQWLDWHG ZLWK VWULQJV ZLWK QR OLQNDJH template const char* str class Message { }; extern const char hello[] = Hello World!; H[WHUQDO OLQNDJH const char hello11[] = Hello World!; LQWHUQDO OLQNDJH void foo() { Messagehello msg; 2. DOO YHUVLRQV Messagehello11 msg11; 2. VLQFH static const char hello17[] = Hello World!; QR OLQNDJH Messagehello17 msg17; 2. VLQFH } Nico Josuttis C++17 @CodeHard 45
  • 160. ‹ E ,7FRPPXQLFDWLRQFRP 1RQ7SH 7HPSODWH 3DUDPHWHUV ZLWK auto ‡ 6LQFH RX FDQ GHFODUH QRQWSH WHPSODWH SDUDPHWHUV ZLWK placeholder types auto DQG decltype(auto) template auto N class S { }; S42 s1; 2. WSH RI 1 LQ 6 LV LQW S'a' s2; 2. WSH RI 1 LQ 6 LV FKDU S2.5 s3; (UURU WHPSODWH SDUDPHWHU WSH VWLOO FDQQRW EH GRXEOH SDUWLDO VSHFLDOL]DWLRQ template int N class SN { }; WHPSODWH ZKHUH 3 PXVW EH D SRLQWHU WR FRQVW VRPHWKLQJ template const auto* P struct S; /LVW RI KHWHURJHQHRXV FRQVWDQW WHPSODWH DUJXPHQWV template auto... VS struct value_list { }; /LVW RI KRPRJHQHRXV FRQVWDQW WHPSODWH DUJXPHQWV template auto V1, decltype(V1)... VS struct typed_value_list { }; ‹ E ,7FRPPXQLFDWLRQFRP auto DQG 6WULQJV IRU 1RQ7SH 7HPSODWH 3DUDPHWHUV template auto Msg class Message { public: void print() { std::cout Msg 'n'; } }; int main() { Message'x' m1; m1.print(); RXWSXWV [ Message42 m2; m2.print(); RXWSXWV static const char s[] = hello; Messages m3; 2. VLQFH m3.print(); RXWSXWV KHOOR } Nico Josuttis C++17 @CodeHard 46
  • 161. ‹ E ,7FRPPXQLFDWLRQFRP 8VLQJ )ROG ([SUHVVLRQV ZLWK auto 7HPSODWH 3DUDPHWHUV templateauto sep = ' ', typename First, typename... Args void print(const First arg0, const Args... args) { std::cout arg0; auto coutSepAndArg = [](const auto arg) { std::cout sep arg; }; (... , coutSepAndArg(args)); std::cout 'n'; } std::string str = world; print(7.5, hi, str); KL ZRUOG print'-'(7.5, hi, str); KLZRUOG static const char sep[] = , ; printsep(7.5, hi, str); KL ZRUOG ‹ E ,7FRPPXQLFDWLRQFRP 9DULDEOH 7HPSODWHV ZLWK auto #include variable.hpp #include iostream void print() { std::cout arrdouble,100u 'n'; std::cout arrint,10 'n'; for (unsigned i=0; iarrint,10.size(); ++i) { std::cout arrint,10[i] 'n'; } } #include variable.hpp void print(); int main() { arrdouble,100u[0] = 17; arrint,10[0] = 42; print(); std::cout val'c' 'n'; } #include array templatetypename T, auto N std::arrayT,N arr; 2. VLQFH templateauto N constexpr decltype(N) val = N; 2. VLQFH WZR GLIIHUHQW JOREDO REMHFWV arr XVHG LQ ERWK WUDQVODWLRQ XQLWV WZR GLIIHUHQW JOREDO REMHFWV arr XVHG LQ ERWK WUDQVODWLRQ XQLWV Nico Josuttis C++17 @CodeHard 47
  • 162. ‹ E ,7FRPPXQLFDWLRQFRP 1RQ7SH 7HPSODWH 3DUDPHWHUV ZLWK decltype(auto) #include iostream #include type_traits templatedecltype(auto) N struct S { S() { if (std::is_same_vdecltype(N),int) std::cout ref ; std::cout N has value N 'n'; } void print() { std::cout value: N 'n'; } }; constexpr int x = 42; int y = 0; OYDOXH int main() { Sx s0; 1 LV LQW ! SULQWV N has value 42 S(y) s1; 1 LV LQW ! SULQWV ref N has value 0 y = 77; S(y) s2; 1 LV LQW ! SULQWV ref N has value 77 y = 88; s1.print(); SULQWV value: 88 s2.print(); SULQWV value: 88 } 5HPHPEHU decltype(auto) XVHV WKH UXOHV RI decltype WSH RI HQWLW H YDOXH FDWHJRU RI H[SUHVVLRQ H IRU SUYDOXHV type IRU OYDOXHV type IRU [YDOXHV type ‹ E ,7FRPPXQLFDWLRQFRP RUH )L[HV DQG ,PSURYHPHQWV Nico Josuttis C++17 @CodeHard 48
  • 163. ‹ E ,7FRPPXQLFDWLRQFRP JXDUDQWHHG VLQFH 'HILQHG ([SUHVVLRQ (YDOXDWLRQ 2UGHU ‡ 0RVW RSHUDWRUV KDYH QR GHILQHG HYDOXDWLRQ RUGHU VLQFH std::string s = I heard it even works if you don't believe; s.replace(0,8,).replace(s.find(even),4,sometimes) .replace(s.find(you don't),9,I); it sometimes works if I believe it sometimes workIdon't believe SRVVLEOH EHIRUH it even worsometiIdon't believe SRVVLEOH EHIRUH it even worsometimesf youIlieve SRVVLEOH EHIRUH DOVR XQGHILQHG EHKDYLRU LI I
  • 164. J
  • 166. GHSHQG RQ HDFK RWKHU std::cout f() g() h(); FDOOV cout.operator(f()) FDOOV cout.operator(g()).operator(h()); ‡ GHILQHV HYDOXDWLRQ RUGHU IRU . - .* -* = += -= [] expr(a,b,c) ± expr EHIRUH a DQG b DQG c EXW abc VWLOO LQ DQ RUGHU ‹ E ,7FRPPXQLFDWLRQFRP 'HILQHG ([SUHVVLRQ (YDOXDWLRQ 2UGHU ‡ GHILQHV HYDOXDWLRQ RUGHU RI . - .* -* = += -= [] f(a,b,c) ± )RU f(a,b,c): f EHIRUH a/b/c EXW abc VWLOO LQ DQ RUGHU DQ DQDQVW QG UG s.replace(0,4,).replace(s.find(even),4,only).replace(s.find( don't),6,);s.replace(0,4,).replace(s.find(even),4,only).replace(s.find( don't),6,);s.replace(0,4,).replace(s.find(even),4,only).replace(s.find( don't),6,);s.replace(0,4,).replace(s.find(even),4,only).replace(s.find( don't),6,);s.replace(0,4,).replace(s.find(even),4,only).replace(s.find( don't),6,);s.replace(0,4,).replace(s.find(even),4,only).replace(s.find( don't),6,); std::string s = but I have heard it works even if you don’t believe; s.replace(0,4,).replace(s.find(even),4,only) .replace(s.find( don't),6,); LV QRZ HYDOXDWHG DV IROORZV Nico Josuttis C++17 @CodeHard 49
  • 167. ‹ E ,7FRPPXQLFDWLRQFRP 'HILQHG ([SUHVVLRQ (YDOXDWLRQ 2UGHU RQVHTXHQFHV void printElem(const std::vectorint v, int idx, const std::string pre = ) { std::cout pre v.at(idx) 'n'; PLJKW WKURZ VWGRXWBRIBUDQJH } try { std::vectorint coll{7, 14, 21, 28}; for (int i=0; i=coll.size(); ++i) { printElem(coll, i, elem: ); } } catch (const std::exception e) { std::cerr EXCEPTION: e.what() 'n'; } catch (...) { std::cerr EXCEPTION of unknown typen; } ‡ 6LQFH H[SUHVVLRQV IRU RSHUDWRU DUH JXDUDQWHHG WR HYDOXDWH IURP OHIW WR ULJKW 0LJKW RXWSXW EHIRUH elem: 7 elem: 14 elem: 21 elem: 28 EXCEPTION: :LOO RXWSXW VLQFH elem: 7 elem: 14 elem: 21 elem: 28 elem: EXCEPTION: ‹ E ,7FRPPXQLFDWLRQFRP noexcept 3DUW RI WKH )XQFWLRQ 7SH ‡ WSH VVWHP GLIIHUHQWLDWHV EHWZHHQ ± QRH[FHSW IXQFWLRQV ± IXQFWLRQV WKDW GRQ W JXDUDQWHH QRW WR WKURZ ‡ $ IXQFWLRQ WKDW PLJKW WKURZ FDQ W EH XVHG DV QRH[FHSW IXQFWLRQ ± 7KH RSSRVLWH LV ILQH void f1(); void f2() noexcept; GLIIHUHQW WSH WKDQ f1 void f3() noexcept(sizeof(int)4); VDPH WSH DV HLWKHU f1 RU f2 void f4() noexcept(sizeof(int)=4); GLIIHUHQW WSH WKDQ f3 Nico Josuttis C++17 @CodeHard 50
  • 168. ‹ E ,7FRPPXQLFDWLRQFRP noexcept 3DUW RI WKH )XQFWLRQ 7SH ‡ WSH VVWHP GLIIHUHQWLDWHV EHWZHHQ ± QRH[FHSW IXQFWLRQV ± IXQFWLRQV WKDW GRQ W JXDUDQWHH QRW WR WKURZ ‡ $ IXQFWLRQ WKDW PLJKW WKURZ FDQ W EH XVHG DV QRH[FHSW IXQFWLRQ WKH RSSRVLWH LV ILQH
  • 169. ‡ 7SH RI IXQFWLRQV ZLWK FRQGLWLRQDO QRH[FHSW VSHFLILFDWLRQV GHSHQGV RQ ZKDW WKH FRQGLWLRQ LHOGV ‡ 'QDPLF H[FHSWLRQ VSHFLILFDWLRQV ZHUH UHPRYHG void f1(); void f2() noexcept; GLIIHUHQW WSH WKDQ f1 void f3() noexcept(sizeof(int)4); VDPH WSH DV HLWKHU f1 RU f2 void f4() noexcept(sizeof(int)=4); GLIIHUHQW WSH WKDQ f3 VDPH WSH DV f2 LI f3 KDV VDPH WSH DV f1 void fnothrow() throw(); 2. EXW PD QRW XQZLQG VWDFN LI YLRODWHG VDPH WSH DV f2 void fthrow() throw(std::bad_alloc); (UURU LQYDOLG VLQFH ‹ E ,7FRPPXQLFDWLRQFRP noexcept 3DUW RI WKH )XQFWLRQ 7SH void f1(); void f2() noexcept; GLIIHUHQW WSH WKDQ I void (*fp)() noexcept; UHTXLUHV QRH[FHSW IXQFWLRQ fp = f2; 2. fp = f1; (UURU VLQFH void (*fp2)(); GRHVQ W UHTXLUH QRH[FHSW IXQFWLRQ fp2 = f2; 2. fp2 = f1; 2. FDQ DOVR XVH QRH[FHSW IXQFWLRQ
  • 170. templatetypename T void call(T op1, T op2); call(f1, f2); (UURU VLQFH I DQG I QRZ KDYH GLIIHUHQW WSHV
  • 171. templatetypename T1, typename T2 void call2(T1 op1, T2 op2); call2(f1, f2); 2. Nico Josuttis C++17 @CodeHard 51
  • 172. ‹ E ,7FRPPXQLFDWLRQFRP noexcept 3DUW RI WKH )XQFWLRQ 7SH SULPDU WHPSODWH LQ JHQHUDO WSH 7 LV QR IXQFWLRQ
  • 173. templatetypename T struct is_function : std::false_type { }; SDUWLDO VSHFLDOL]DWLRQV IRU DOO IXQFWLRQ WSHV templatetypename Ret, typename... Params struct is_functionRet (Params...) : std::true_type { }; templatetypename Ret, typename... Params struct is_functionRet (Params...) const : std::true_type { }; templatetypename Ret, typename... Params struct is_functionRet (Params...) : std::true_type { }; templatetypename Ret, typename... Params struct is_functionRet (Params...) const : std::true_type { }; SDUWLDO VSHFLDOL]DWLRQV IRU DOO IXQFWLRQ WSHV ZLWK QRH[FHSW templatetypename Ret, typename... Params struct is_functionRet (Params...) noexcept : std::true_type { }; templatetypename Ret, typename... Params struct is_functionRet (Params...) const noexcept : std::true_type { }; templatetypename Ret, typename... Params struct is_functionRet (Params...) noexcept : std::true_type { }; templatetypename Ret, typename... Params struct is_functionRet (Params...) const noexcept : std::true_type { }; QRZ LQVWHDG RI SDUWLDO VSHFLDOL]DWLRQV ‹ E ,7FRPPXQLFDWLRQFRP 5HOD[HG (QXPHUDWLRQ ,QLWLDOL]DWLRQ ‡ )RU HQXPHUDWLRQV ZLWK D IL[HG XQGHUOLQJ WSH RX FDQ XVH DQ LQWHJUDO YDOXH RI WKDW WSH IRU GLUHFW OLVW LQLWLDOL]DWLRQV ± DSSOLHV WR ERWK enum DQG enum class enum class Salutation { mr, mrs }; Salutation s4 = 0; (UURU DOO YHUVLRQV
  • 174. Salutation s5(0); (UURU DOO YHUVLRQV
  • 175. Salutation s6{0}; 2. VLQFH HUURU EHIRUH
  • 176. enum class Salut : char { mr, mrs }; Salut s7 = 0; (UURU DOO YHUVLRQV
  • 177. Salut s8(0); (UURU DOO YHUVLRQV
  • 178. Salut s9{0}; 2. VLQFH HUURU EHIRUH
  • 179. enum Flag { bit1=1, bit2=2, bit3=4 }; Flag f3{0}; VWLOO (UURU DOO YHUVLRQV
  • 180. enum Byte : unsigned char { }; Byte b1 = 42; (UURU DOO YHUVLRQV
  • 181. Byte b2(42); (UURU DOO YHUVLRQV
  • 182. Byte b3{42}; 2. VLQFH HUURU EHIRUH
  • 183. Byte b4 = {42}; (UURU DOO YHUVLRQV
  • 184. 7KLV LV ZK LW ZDV LQWURGXFHG ‡ ,QLWLDOL]DWLRQ RI QHZ LQWHJUDO WSHV DV HQXP ‡ 6HH std::byte Nico Josuttis C++17 @CodeHard 52
  • 185. ‹ E ,7FRPPXQLFDWLRQFRP ,QLWLDOL]DWLRQV ZLWK auto DQG {} ‡ auto a1(42); GLUHFW LQLWLDOL]DWLRQ LQLWLDOL]HV DQ LQW auto a2{42}; GLUHFWOLVWLQLWLDOL]DWLRQ LQLWLDOL]HV VWGLQLWLDOL]HUBOLVWLQW! auto a3{1,2}; GLUHFWOLVWLQLWLDOL]DWLRQ LQLWLDOL]HV VWGLQLWLDOL]HUBOLVWLQW! auto a4 = 42; FRS LQLWLDOL]DWLRQ LQLWLDOL]HV DQ LQW auto a5 = {42}; FRSOLVWLQLWLDOL]DWLRQ LQLWLDOL]HV DQ LQLWLDOL]HUBOLVWLQW! auto a6 = {1,2}; FRSOLVWLQLWLDOL]DWLRQ LQLWLDOL]HV DQ LQLWLDOL]HUBOLVWLQW! ‡ 6LQFH EXW VRPH FRPSLOHUV VXSSRUW LW EHIRUH
  • 186. auto x1(42); GLUHFW LQLWLDOL]DWLRQ LQLWLDOL]HV DQ LQW auto x2{42}; GLUHFWOLVWLQLWLDOL]DWLRQ LQLWLDOL]HV DQ LQW auto x3{1,2}; (UURU auto x4 = 42; FRS LQLWLDOL]DWLRQ LQLWLDOL]HV DQ LQW auto x5 = {42}; FRSOLVWLQLWLDOL]DWLRQ VWLOO LQLWLDOL]HV VWGLQLWLDOL]HUBOLVWLQW! auto x6 = {1,2}; FRSOLVWLQLWLDOL]DWLRQ VWLOO LQLWLDOL]HV VWGLQLWLDOL]HUBOLVWLQW! ‹ E ,7FRPPXQLFDWLRQFRP 1HZ /LEUDU RPSRQHQWV Nico Josuttis C++17 @CodeHard 53
  • 187. ‹ E ,7FRPPXQLFDWLRQFRP 1HZ %DVLF 'DWD 6WUXFWXUHV ‡ $IWHU SDLU! WXSOH! DGGV VRPH VPDUW GDWD WSHV WR KROG D YDOXH ± VWGRSWLRQDO! ‡ RSWLRQDOO KROGV D YDOXH ‡ HLWKHU HPSW RU KDV D YDOXH RI D VSHFLILF WSH ‡ DGDSWHG IURP ERRVWRSWLRQDO! ± VWGYDULDQW! ‡ KROGV D YDOXH WKDW PLJKW KDYH RQH RI PXOWLSOH SUHGHILQHG WSHV ‡ XVXDOO QHYHU HPSW RQO GXH WR VRPH H[FHSWLRQV
  • 188. ‡ GLIIHUV IURP ERRVWYDULDQW! ± VWGDQ! ‡ KROGV D YDOXH WKDW PLJKW KDYH DQ SRVVLEOH WSH ‡ PD EH HPSW ‡ DGDSWHG IURP ERRVWDQ! ‹ E ,7FRPPXQLFDWLRQFRP std::optional ‡ 6WUXFWXUH WR RSWLRQDOO KROG D YDOXH RI D FHUWDLQ WSH ± HLWKHU HPSW RU KDV D YDOXH ± QR QHHG WR GHDO ZLWK VSHFLDO YDOXHV VXFK DV 18// RU ‡ $GDSWHG IURP ERRVWRSWLRQDO ± std::nullopt LQVWHDG RI boost::none std::optionalstd::string noString; std::optionalstd::string optStr(hello); optStr = new value; *optStr = new value; if (optStr) { HTXLYDOHQW WR if (optStr.has_value()) std::string s = *optStr; XQGHILQHG EHKDYLRU LI QR YDOXH } try { std::string s = optStr.value(); H[FHSWLRQ LI QR YDOXH } catch (const std::bad_optional_access e) { optStr.reset(); PDNHV LW HPSW } Nico Josuttis C++17 @CodeHard 54
  • 189. ‹ E ,7FRPPXQLFDWLRQFRP ([DPSOH IRU std::optional #include optional #include string #include iostream std::optionalint asInt(const std::string s) UHWXUQV LQW RU QR LQW { try { return std::stoi(s); } catch (...) { return std::nullopt; } } int main() { for (auto s : {42, 077, hello, 0x33} ) { std::optionalint oi = asInt(s); if (oi) { std::cout convert ' s ' to int: *oi n; LQW } else { std::cout can't convert ' s ' to intn; QR LQW } } } 2XWSXW convert '42' to int: 42 convert ' 077' to int: 77 can't convert 'hello' to int convert '0x33' to int: 0 ‹ E ,7FRPPXQLFDWLRQFRP std::optional 2SHUDWLRQV PRYH VHPDQWLFV LV VXSSRUWHG std::optionalstd::string os; std::string s = hello; os = std::move(s); std::string s2 = *os; std::string s3 = std::move(*os); RPSDULVRQ ZRUN RQ WKH YDOXHV QR YDOXH DQ RWKHU YDOXH std::optionalbool ob0; if (ob false) WUXH std::optionalunsigned uo; if (uo 0) WUXH GLIIHUHQW WKDQ XVLQJ DV ERRO std::optionalbool ob{false}; if (!ob) IDOVH if (ob==false) WUXH std::optionalint* op{nullptr}; if (!op) IDOVH if (op==nullptr) WUXH Nico Josuttis C++17 @CodeHard 55
  • 190. ‹ E ,7FRPPXQLFDWLRQFRP std::optional RQVLGHUHG +DUPIXO ‡ %HZDUH RI DFFHVVLQJ WKH FRQWDLQHG REMHFW IRU WHPSRUDULHV ± /LIHWLPH LVVXHV ZLWK GLUHFW DFFHVV ± 'RQ W UHSODFH REMHFWV E RSWLRQDO REMHFWV EOLQGO std::optionalstd::string getString(); auto a = getString().value(); 2. FRS RI FRQWDLQHG REMHFW auto b = *getString(); (5525 XQGHILQHG EHKDYLRU LI std::nullopt const auto r1 = getString().value(); (5525 UHIHUHQFH WR GHOHWHG FRQWDLQHG REMHFW auto r2 = getString().value(); (5525 UHIHUHQFH WR GHOHWHG FRQWDLQHG REMHFW std::vectorint getVector(); for (int i : getVector()) { 2. std::cout i 'n'; } std::optionalstd::vectorint getOptVector(); for (int i : getOptVector().value()) { (5525 LWHUDWH RYHU GHOHWHG YHFWRU std::cout i 'n'; } ‹ E ,7FRPPXQLFDWLRQFRP 'HFODUDWLRQ RI VWGRSWLRQDO! template typename T class optional { public: using value_type = T; constexpr optional() noexcept; // observers: constexpr const T operator*() const; constexpr T operator*() ; constexpr T operator*() ; constexpr const T operator*() const; constexpr const T value() const; constexpr T value() ; constexpr T value() ; constexpr const T value() const; }; 6HH KWWSZJOLQNS IRU RXU SURSRVDO WR GHFODUH WKDW WKH UHWXUQ YDOXH GHSHQGV RQ WKH OLIHWLPH RI WKLV Nico Josuttis C++17 @CodeHard 56
  • 191. ‹ E ,7FRPPXQLFDWLRQFRP std::variant ‡ ORVH GLVFULPLQDWHG XQLRQ ± 6WUXFWXUH WR KROG D YDOXH RI RQH RI WKH VSHFLILHG alternatives ± 8QOLNH union ‡ 7KH WSH RI WKH FXUUHQW YDOXH LV DOZDV NQRZQ ‡ DQ KDYH DQ PHPEHU RI DQ WSH ‡ DQ EH EDVH FODVV ± 0XOWLSOH RFFXUUHQFHV RI VDPH WSH DUH VXSSRUWHG ‡ 6HPDQWLF XQLRQ HJ GLIIHUHQW VWULQJV IRU GLIIHUHQW GDWDEDVH FROXPQV
  • 192. ‡ ,QWHUIDFH ZLWK LQGH[ OLNH WXSOH ± 1R HPSW VWDWH ‡ DQ XVH std::monostate WR VLPXODWH LW ± 'HIDXOWRQVWUXFWLEOH LI ILUVW DOWHUQDWLYH LV GHIDXOW FRQVWUXFWLEOH ‡ DQ XVH std::monostate IRU LW ± 'LIIHUV IURP ERRVWYDULDQW ‡ 1R KHDS DOORFDWLRQ ‹ E ,7FRPPXQLFDWLRQFRP ([DPSOH IRU std::variant #include variant std::variantint, int, std::string var; VHWV ILUVW LQW WR LQGH[
  • 193. var = hello; VHWV VWULQJ LQGH[
  • 194. var.emplace1(42); VHWV VHFRQG LQW LQGH[
  • 195. try { auto s = std::getstd::string(var); WKURZV H[FHSWLRQ VHFRQG LQW FXUUHQWO VHW
  • 196. auto a = std::getdouble(var); FRPSLOHWLPH HUURU QR GRXEOH auto b = std::get3(var); FRPSLOHWLPH HUURU QR WK DOWHUQDWLYH auto c = std::getint(var); FRPSLOHWLPH HUURU LQW WZLFH auto i = std::get1(var); 2. L auto j = std::get0(var); WKURZV H[FHSWLRQ RWKHU LQW FXUUHQWO VHW
  • 197. std::get1(var) = 77; 2. EHFDXVH VHFRQG LQW DOUHDG VHW std::get0(var) = 99; WKURZV H[FHSWLRQ RWKHU LQW FXUUHQWO VHW
  • 198. } catch (const std::bad_variant_access e) { LI UXQWLPH HUURU std::cout Exception: e.what() 'n'; } Nico Josuttis C++17 @CodeHard 57
  • 199. ‹ E ,7FRPPXQLFDWLRQFRP std::variant 2SHUDWLRQV ‹ E ,7FRPPXQLFDWLRQFRP 7ULFN 8VDJH IRU std::variant #include variant H[SOLFLWO FKRRVH WKH DOWHUQDWLYH std::variantint, long var{std::in_place_index1, 11}; LQLWV ORQJ DOWKRXJK LQW SDVVHG LQGH[
  • 200. var = 22; VHWV LQW LQGH[
  • 201. var.emplace1(32); VHWV ORQJ DOWKRXJK LQW SDVVHG LQGH[
  • 202. LQLWLDOL]H YDULDQW ZLWK D VHW ZLWK ODPEGD DV VRUWLQJ FULWHULRQ auto sc = [] (int x, int y) { return std::abs(x) std::abs(y); }; std::variantstd::vectorint, std::setint,decltype(sc) v8{std::in_place_index1, {4, 8, -7, -2, 0, 5}, sc}; if (auto ip = std::get_if1(var); ip) { QRWH SDVV WKH DGGUHVV std::cout *ip: *ip 'n'; } QHZ if ZLWK LQLWLDOL]DWLRQ Nico Josuttis C++17 @CodeHard 58
  • 203. ‹ E ,7FRPPXQLFDWLRQFRP VWGYDULDQW! DQG VWGPRQRVWDWH struct NoDefConstr { NoDefConstr(int i) { } }; std::variantNoDefConstr, int v1; (5525 FDQ W GHIDXOW FRQVWUXFW ILUVW WSH std::variantstd::monostate, NoDefConstr v2; 2. YDOXH LV PRQRVWDWH^` std::cout index: v2.index() 'n'; SULQW FKHFN IRU PRQRVWDWH if (v2.index() == 0) { } if (!v2.index()) { } PRQRVWDWH PXVW EH ILUVW DOWHUQDWLYH if (std::holds_alternativestd::monostate(v2)) { } if (std::get_if0(v2)) { } if (std::get_ifstd::monostate(v2)) { } v2 = 42; v2 = std::monostate{}; PRQRVWDWH DJDLQ D ZD WR VLJQDO HPSWLQHVV D ZD WR VLJQDO HPSWLQHVV ‹ E ,7FRPPXQLFDWLRQFRP std::variant %HFRPLQJ (PSW ‡ variant PLJKW EHFRPH HPSW RQO E XQKDQGOHG H[FHSWLRQ ± 2QO LI XVLQJ WKH YDULDQW DIWHU H[FHSWLRQ ZLWKRXW UHLQLWLDOL]DWLRQ ‡ 7KHQ v.valueless_by_exception() == true v.index() == std::variant_npos struct S { operator int() { throw EXCEPTION; } DQ FRQYHUVLRQ WR LQW WKURZV }; std::variantfloat,int var{12.2}; try { var.emplace1(S()); RRSV WKURZV ZKLOH EHLQJ VHW } catch (...) { RRSV UHDOO GRQ W VHW YDU WR D QHZ GHILQHG VWDWH } var.valueless_by_exception() == true var.index() == std::variant_npos Nico Josuttis C++17 @CodeHard 59
  • 204. ‹ E ,7FRPPXQLFDWLRQFRP 'HULYLQJ IURP VWGYDULDQW! class Derived : public std::variantint, std::string { }; Derived d = {{hello}}; DJJUHJDWH LQLWLDOL]DWLRQ std::cout d.index() 'n'; SULQWV std::cout std::get1(d) 'n'; SULQWV KHOOR d.emplace0(77); std::cout std::get0(d) 'n'; SULQWV ‹ E ,7FRPPXQLFDWLRQFRP std::variant 9LVLWRUV std::variantint, std::string var(42); struct MyVisitor { void operator()(double d) const { std::cout d 'n'; } void operator()(int i) const { std::cout i 'n'; } void operator()(const std::string s) const { std::cout s 'n'; } }; std::visit(MyVisitor(), var); FRPSLOHWLPH HUURU LI QRW DOO SRVVLEOH WSHV VXSSRUWHG RU ZLWK DPELJXLWLHV std::visit([](const auto val) { FDOO ODPEGD IRU WKH DSSURSULDWH WSH std::cout val 'n'; }, var); ‡ 8VLQJ YLVLWRUV Nico Josuttis C++17 @CodeHard 60
  • 205. ‹ E ,7FRPPXQLFDWLRQFRP std::variant 9LVLWRUV struct MyVisitor { template typename T YLVLWRU IRU VLQJOH YDOXH RI DQ WSH void operator() (T var) { std::cout var; } void operator() (int i, double d, char c) { IRU VSHFLILF YDOXHV std::cout i ' ' d ' ' c; } void operator() (...) { IRU DOO RWKHU FDVHV std::cout no match; } }; std::variantint, std::string var1{12}; std::variantstd::string, double var2{13}; std::variantstd::string, char var3{'x'}; std::visit(MyVisitor(), var1, var2, var3); SULQWV [ var2 = hello; std::visit(MyVisitor(), var1, var2, var3); SULQWV QR PDWFK std::visit(MyVisitor(), var2); SULQWV KHOOR ‡ 0XOWL9LVLWRUV ‹ E ,7FRPPXQLFDWLRQFRP 5XQWLPH 3ROPRUSKLVP ([DPSOH ZLWK +HDS 0HPRU class GeoObj { public: virtual void move(Coord) = 0; virtual void draw() const = 0; virtual ~GeoObj() = default; }; class Circle : public GeoObj { private: Coord center; int rad; public: Circle (Coord c, int r); virtual void move(Coord c) override; virtual void draw() const override; }; class Line : public GeoObj { private: Coord from; Coord to; public: Line (Coord f, Coord t); virtual void move(Coord c) override; virtual void draw() const override; }; std::vectorGeoObj* createFig() { std::vectorGeoObj* f; Line* lp = new Line(Coord(1,2), Coord(3,4)); Circle* cp = new Circle(Coord(5,5), 2); f.push_back(lp); f.push_back(cp); return f; } void drawElems (const std::vectorGeoObj* v) { for (const auto geoobjptr : v) { geoobjptr-draw(); } } std::vectorGeoObj* fig = createFig(); drawElems(fig); for (const auto geoobjptr : fig) { geoobjptr-move(Coord(2,2)); } drawElems(fig); UHPRYH DOO HOHPHQWV LQ WKH YHFWRU for (auto geoobjptr : fig) { delete geoobjptr; geoobjptr = nullptr; NULL EHIRUH } fig.clear(); /LQH *HR2EM LUFOH Nico Josuttis C++17 @CodeHard 61
  • 206. ‹ E ,7FRPPXQLFDWLRQFRP 3ROPRUSKLVP ([DPSOH ZLWK std::variant class GeoObj { public: virtual void move(Coord) = 0; virtual void draw() const = 0; virtual ~GeoObj() = default; }; class Circle : public GeoObj { private: Coord center; int rad; public: Circle (Coord c, int r); virtual void move(Coord c) override; virtual void draw() const override; }; class Line : public GeoObj { private: Coord from; Coord to; public: Line (Coord f, Coord t); virtual void move(Coord c) override; virtual void draw() const override; }; using GeoObjVar = std::variantCircle, Line; std::vectorGeoObjVar createFig() { std::vectorGeoObjVar f; f.push_back(Line(Coord(1,2),Coord(3,4))); f.push_back(Circle(Coord(5,5),2)); return f; } void drawElems (const std::vectorGeoObjVar v) { for (const auto geoobj : v) { std::visit([] (const auto obj) { obj.draw(); }, geoobj); } } std::vectorGeoObjVar fig = createFig(); drawElems(fig); for (auto geoobj : fig) { std::visit([] (auto obj) { obj.move(Coord(2,2)); }, geoobj); } drawElems(fig); fig.clear(); UHPRYH DOO HOHPHQWV LQ WKH YHFWRU /LQH *HR2EM LUFOH ‡ QR SRLQWHUV ‡ QR QHZGHOHWH LQ DSSO FRGH ‡ REMHFWV ORFDWHG WRJHWKHU YLVLWRU XVHV D ORFDO YWDEOH ‹ E ,7FRPPXQLFDWLRQFRP 3ROPRUSKLVP ([DPSOH ZLWK std::variant class Circle { private: Coord center; int rad; public: Circle (Coord c, int r); void move(Coord c); void draw() const; }; class Line { private: Coord from; Coord to; public: Line (Coord f, Coord t); void move(Coord c); void draw() const; }; using GeoObjVar = std::variantCircle, Line; std::vectorGeoObjVar createFig() { std::vectorGeoObjVar f; f.push_back(Line(Coord(1,2),Coord(3,4))); f.push_back(Circle(Coord(5,5),2)); return f; } void drawElems (const std::vectorGeoObjVar v) { for (const auto geoobj : v) { std::visit([] (const auto obj) { obj.draw(); }, geoobj); } } std::vectorGeoObjVar fig = createFig(); drawElems(fig); for (auto geoobj : fig) { std::visit([] (auto obj) { obj.move(Coord(2,2)); }, geoobj); } drawElems(fig); fig.clear(); UHPRYH DOO HOHPHQWV LQ WKH YHFWRU ‡ QR FRPPRQ EDVH FODVV ‡ QR YLUWXDO IXQFWLRQV /LQH *HR2EM LUFOH YLVLWRU XVHV D ORFDO YWDEOH ‡ QR SRLQWHUV ‡ QR QHZGHOHWH LQ DSSO FRGH ‡ REMHFWV ORFDWHG WRJHWKHU Nico Josuttis C++17 @CodeHard 62
  • 207. ‹ E ,7FRPPXQLFDWLRQFRP std:any ‡ 7SH WR KROG DQ SRVVLEOH YDOXH RI DQ WSH ± PD EH HPSW ‡ $GDSWHG IURP ERRVWDQ std::any empty; std::any anyVal(42); anyVal = std::string(hello); anyVal = oops; %HZDUH WSH LV FRQVW FKDU VR VWRUHV WKH DGGUHVV if (anyVal.has_value()) { if (anyVal) QRW VXSSRUWHG if (anyVal.type() == typeid(std::string)) { type()==typeid(void) LI HPSW std::string s = std::any_caststd::string(anyVal); } } try { int i = std::any_castint(anyVal); WSH PXVW PDWFK H[DFWO RQO FRQVWUHIV LJQRUHG
  • 208. } catch (std::bad_any_cast) { anyVal.reset(); PDNHV LW HPSW } ‹ E ,7FRPPXQLFDWLRQFRP std::any 2SHUDWLRQV Nico Josuttis C++17 @CodeHard 63
  • 209. ‹ E ,7FRPPXQLFDWLRQFRP 0RYH 6HPDQWLFV ZLWK std:any ‡ 7SHV LQ VWGDQ PXVW EH FRSDEOH ± 0RYHRQO WSHV DUH QRW VXSSRUWHG ‡ %XW RX FDQ XVH PRYH VHPDQWLFV std::string s(a pretty long string value (disabling SSO)); std::cout s: s 'n'; RXWSXWV WKH LQLWLDOL]HG VWULQJ std::any a; a = std::move(s); PRYH V LQWR D std::cout s: s 'n'; SUREDEO RXWSXWV DQ HPSW VWULQJ s = std::any_caststd::string(std::move(a)); PRYH VWULQJ LQ D LQWR V std::cout s: s 'n'; RXWSXWV WKH RULJLQDO VWULQJ ‹ E ,7FRPPXQLFDWLRQFRP std::byte ‡ 7SH UHSUHVHQWLQJ D EWH ± 1RW DQ LQWHJHU QRW D FKDUDFWHU ± 2SHUDWRUV = = = | |= = ^ ^= ~ == != = = sizeof ‡ 3OXV to_integerintegraltype(byte) std::byte b1{0xFF}; 2. DV IRU DOO HQXPV ZLWK IL[HG XQGHUOLQJ WSH VLQFH
  • 210. std::byte b2{0b1111'0000}; std::byte[4] b4{0xFF, 0, 0, 0}; if (b1 == b4[0]) { b1 = 4; } std::byte b0; XQGHILQHG YDOXH std::byte bx(42); (UURU std::byte by = 42; (UURU if (b1) (UURU if (b1 != std::byte{0}) 2. if (to_integerbool(b2)) (UURU $'/ GRHVQ W ZRUN KHUH
  • 211. if (std::to_integerbool(b2)) 2. std::cout sizeof(b0); DOZDV Nico Josuttis C++17 @CodeHard 64
  • 212. ‹ E ,7FRPPXQLFDWLRQFRP VWGEWH 'HILQLWLRQ LQ WKH 6WDQGDUG namespace std { enum class byte : unsigned char {}; EWH WSH RSHUDWLRQV template typename IntType constexpr byte operator (byte b, IntType shift) noexcept; template typename IntType constexpr byte operator= (byte b, IntType shift) noexcept; template typename IntType constexpr byte operator (byte b, IntType shift) noexcept; template typename IntType constexpr byte operator= (byte b, IntType shift) noexcept; constexpr byte operator|= (byte l, byte r) noexcept; constexpr byte operator| (byte l, byte r) noexcept; constexpr byte operator= (byte l, byte r) noexcept; constexpr byte operator (byte l, byte r) noexcept; constexpr byte operator^= (byte l, byte r) noexcept; constexpr byte operator^ (byte l, byte r) noexcept; constexpr byte operator~ (byte b) noexcept; template typename IntType constexpr IntType to_integer (byte b) noexcept; } ‹ E ,7FRPPXQLFDWLRQFRP std::string_view ‡ +DQGOH IRU UHDGRQO FKDUDFWHU VHTXHQFH ± /LIHWLPH RI WKH GDWD QRW FRQWUROOHG EH WKH REMHFW ± 1R DOORFDWRU VXSSRUW ± 3DVVLQJ E YDOXH LV FKHDS ‡ 'LIIHUV IURP VWULQJV DV IROORZV ± 1RW JXDUDQWHHG WR EH QXOO WHUPLQDWHG QR 17%6
  • 213. ‡ RX FDQ SODFH D ? DV ODVW FKDUDFWHU WKRXJK ± 9DOXH LV nullptr DIWHU GHIDXOW FRQVWUXFWLRQ ‡ 7KHQ data()==nullptr size()==0 VWULQJ G D D ?W VWULQJBYLHZ G D DWV R HP H P RL PQ U OHQ GDWD OHQ GDWD ‡ $OZDV XVH size() EHIRUH XVLQJ WKH GDWD operator[]data()
  • 215. ‹ E ,7FRPPXQLFDWLRQFRP std::string_view ‡ +HDGHU string_view ‡ +DV VRPH WSLFDO VWULQJ VXSSRUW ± $OVR u16string_view u32string_view wstring_view ± RUUHVSRQGLQJ OLWHUDO RSHUDWRU LV GHILQHG ‡ 6XIIL[ sv ± std::quoted() LV VXSSRUWHG ± +DVK YDOXHV PDWFK ZLWK KDVK YDOXHV RI std::string ‡ 6WLOO RSHQ LQWHJUDWLRQV ± 1R UHJH[ VXSSRUW #include chrono using namespace std::literals; auto s = R(somevalue)sv; std::cout quoted(s); RXWSXW somevalue s Y D XOV R H ??P H ? OHQ GDWD ‹ E ,7FRPPXQLFDWLRQFRP std::string_view 2SHUDWLRQV XQOLNH VWGVWULQJ Nico Josuttis C++17 @CodeHard 66
  • 216. ‹ E ,7FRPPXQLFDWLRQFRP std::string_view ‡ RQYHUVLRQ VWULQJ ! VWULQJBYLHZ LV FKHDS ! ,PSOLFLW FRQYHUVLRQ ‡ RQYHUVLRQ VWULQJBYLHZ ! VWULQJ LV H[SHQVLYH ! ([SOLFLW FRQYHUVLRQ void foo_s (const string s); void foo_v (string_view sv); foo_s(some value); FRPSXWHV OHQJWK DOORFDWHV PHPRU FRSLHV FKDUDFWHUV foo_v(some value); FRPSXWHV OHQJWK RQO VWULQJ VWULQJBYLHZ Y D XOV R HP H ? OHQ GDWD OHQ GDWD Y D XOV R HP H ? ‹ E ,7FRPPXQLFDWLRQFRP RQYHUWLQJ $3, V IURP string WR string_view #include string templatetypename Coll void printElems(const Coll coll, const std::string prefix) { SULQW HDFK HOHPHQW ZLWK D OHDGLQJ SUHIL[ for (const auto elem : coll) { std::cout prefix elem 'n'; } } #include string_view templatetypename Coll void printElems(const Coll coll, std::string_view prefix) { SULQW HDFK HOHPHQW ZLWK D OHDGLQJ SUHIL[ for (const auto elem : coll) { std::cout prefix elem 'n'; } } VDYHV QHZPDOORF IRU printElems(myVector, - Coll Element: ); VWLOO ZRUNV DV EHIRUH IRU std::string getPrefix(); ... printElems(myVector, getPrefix()); %HZDUH 2QO 2. EHFDXVH ‡ QR QXOO WHUPLQDWRU UHTXLUHG ‡ data() QRW XVHG nullptr
  • 217. ‡ OLIHWLPH 2. Nico Josuttis C++17 @CodeHard 67
  • 218. ‹ E ,7FRPPXQLFDWLRQFRP RQYHUWLQJ $3, V IURP string WR string_view #include string templatetypename Coll void printElems(const Coll coll, const std::string prefix) { SULQW HDFK HOHPHQW ZLWK D OHDGLQJ SUHIL[ for (const auto elem : coll) { std::cout prefix elem 'n'; } } #include string_view templatetypename Coll void printElems(const Coll coll, std::string_view prefix) { SULQW HDFK HOHPHQW ZLWK D OHDGLQJ SUHIL[ for (const auto elem : coll) { std::cout prefix elem 'n'; } } ZLWK ERWK SURYLGHG printElems(myVector, - Coll Element: ); (UURU DPELJXRXV ‹ E ,7FRPPXQLFDWLRQFRP RQYHUWLQJ $3, V IURP string WR string_view #include string class Customer { std::string name; public: Customer (const std::string n) : name(n) { } }; #include string #include string_view class Customer { std::string name; public: Customer (std::string_view n) : name(n) { } }; VDYHV QHZPDOORF IRU Customer c1(Enterprise Applications); EXW DGGV QHZPDOORF IRU std::string getName(); ... Customer c2(getName()); 'RQ W XVH std::string_view LQ FDOO VHTXHQFHV IRU std::string Nico Josuttis C++17 @CodeHard 68
  • 219. ‹ E ,7FRPPXQLFDWLRQFRP RQVWUXFWRUV VKRXOG PRYH LQLWLDOL]H PHPEHUV IURP EYDOXH SDUDPHWHUV ,QLWLDOL]LQJ 'DWD 0HPEHUV VLQFH #include string class Customer { std::string name; public: Customer (const std::string n) : name(n) { } }; #include string #include string_view class Customer { std::string name; public: Customer (std::string n) : name(std::move(n)) { } }; 9 VDYHV QHZPDOORF IRU Customer c1(Enterprise Applications); DQG VDYHV DQ QHZPDOORF IRU std::string getName(); ... Customer c2(getName()); ‹ E ,7FRPPXQLFDWLRQFRP VWULQJBYLHZ RQVLGHUHG +DUPIXO ‡ 1(9(5 XVH VWGVWULQJBYLHZ DV UHWXUQ WSH ± 6WULQJ YLHZV DUH DV EDG DV SRLQWHUV ZRUVH WKDQ UHIHUHQFHV
  • 220. std::string_view concat (std::string_view sv1, std::string_view sv2) { return std::string(sv1) + std::string(sv2); )DWDO 5XQWLPH (5525 } UHWXUQ YDOXH UHIHUV WR PHPRU RI GHVWUXFWHG VWULQJ std::string str = hello; std::cout concat(str, world) 'n'; IDWDO EXW FRPSLOHV std::string s1 = concat(str, world); IDWDO EXW FRPSLOHV auto s2 = concat(str, world); IDWDO EXW FRPSLOHV auto s3 = concat(str, world); IDWDO EXW FRPSLOHV std::string_view sv = concat(str, world); IDWDO EXW FRPSLOHV ‡ 1RW HYHQ FRPSLOHU ZDUQLQJV HW
  • 221. ‡ 7KHUH PLJKW FRPH VRPHWKLQJ ZLWK PDUN UHVXOW RI FRQYHUVLRQ IRUP string WR string_view DV OLIHWLPHGHSHQGHQW VHH KWWSZJOLQNS Nico Josuttis C++17 @CodeHard 69
  • 222. ‹ E ,7FRPPXQLFDWLRQFRP VWULQJBYLHZ RQVLGHUHG +DUPIXO ‡ 3UHIHU auto DV UHWXUQ WSH LQ WHPSODWHV ‡ $YRLG auto IRU LQLWLDOL]DWLRQV IURP UHWXUQ YDOXHV std::string operator+ (std::string_view sv1, std::string_view sv2) { return std::string(sv1) + std::string(sv2); } templatetypename T T concat (const T x, const T y) { return x + y; } std::string_view hi = hi; auto xy = concat(hi, hi); 2236 [ LV VWGVWULQJBYLHZ std::cout xy 'n'; 5XQWLPH (5525 UHWXUQHG VWULQJ DOUHDG GHVWUXFWHG
  • 223. EHWWHU GHFODUH WKH UHWXUQ WSH RI WHPSODWH DV auto EHWWHU QRW GHFODUH REMHFW LQLWLDOL]HG ZLWK UHWXUQ YDOXH DV auto ‹ E ,7FRPPXQLFDWLRQFRP )LOHVVWHP /LEUDU Nico Josuttis C++17 @CodeHard 70
  • 224. ‹ E ,7FRPPXQLFDWLRQFRP )LOHVVWHP /LEUDU ‡ $3, WR GHDO ZLWK ILOHV GLUHFWRULHV SDWKV ± $GDSWHG IURP ERRVW ± 0DNH ILOHVVWHP RSHUDWLRQV DV SRUWDEOH DV SRVVLEOH ‡ (QFRXUDJHV EHKDYLRU DV GHILQHG E 326,; ‡ ,PSOHPHQWDWLRQV KDYH WR GRFXPHQW GLIIHUHQFHV DQG UHSRUW DQ HUURU LI WKHUH LV QRW UHDVRQDEOH EHKDYLRU ‡ 0RGLILFDWLRQV DJDLQVW %RRVW )LOHVVWHP 76 ± 5RRW HOHPHQWV DUH QRW ORQJHU ILOHQDPHV ± $ SDWK HQGLQJ ZLWK / QR ORQJHU LHOGV . DV ODVW HOHPHQW ‡ ([WHQVLRQV ± 5HODWLYH SDWK IXQFWLRQV ‡ OH[LFDOO DFFRUGLQJ WR VQWD[
  • 225. RU RSHUDWLRQDO DFFRUGLQJ WR ILOH VVWHP
  • 226. ‡ ZLWK DQG ZLWKRXW DEVROXWH SDWK DV IDOOEDFN ‹ E ,7FRPPXQLFDWLRQFRP )LOHVVWHP 6LPSOH ([DPSOH #include iostream #include filesystem int main (int argc, char* argv[]) { if (argc 2) { std::cout Usage: argv[0] path n; return EXIT_FAILURE; } std::filesystem::path p(argv[1]); S UHSUHVHQWV D ILOHVVWHP SDWK PLJKW QRW H[LVW
  • 227. if (exists(p)) { GRHV SDWK S DFWXDOO H[LVW if (is_regular_file(p)) { LV SDWK S D UHJXODU ILOH std::cout size of p is file_size(p) 'n'; } else if (is_directory(p)) { LV SDWK S D GLUHFWRU std::cout p is a directory containing:n; for (auto e : std::filesystem::directory_iterator(p)) { std::cout e.path() 'n'; } } else { std::cout p exists, but is neither regular file nor directoryn; } } else { std::cout p doesn't existn; } } 1R FKDQJH IURP %RRVW)676 $3, H[FHSW KHDGHU ILOH DQG QDPHVSDFH 0LJKW 2XWSXW / is a directory containing: /proc /dev Nico Josuttis C++17 @CodeHard 71
  • 228. ‹ E ,7FRPPXQLFDWLRQFRP )LOHVVWHP 6LPSOH ([DPSOH #include iostream #include filesystem int main (int argc, char* argv[]) { if (argc 2) { } namespace fs = std::filesystem; fs::path p(argv[1]); S UHSUHVHQWV D ILOHVVWHP SDWK PLJKW QRW H[LVW
  • 229. if (exists(p)) { GRHV SDWK S DFWXDOO H[LVW if (is_regular_file(p)) { LV SDWK S D UHJXODU ILOH std::cout size of p is file_size(p) 'n'; } else if (is_directory(p)) { LV SDWK S D GLUHFWRU std::cout p is a directory containing:n; for (auto e : fs::directory_iterator(p)) { std::cout e.path() 'n'; } } else { std::cout p exists, but is neither regular file nor directoryn; } } else { std::cout p doesn't existn; } } RPPRQ FRQYHQWLRQ IRU ILOHVVWHP QDPHVSDFH 0LJKW 2XWSXW / is a directory containing: /proc /dev ‹ E ,7FRPPXQLFDWLRQFRP )LOHVVWHP 0RGLILQJ ([DPSOH #include iostream #include fstream #include filesystem int main () { try { std::filesystem::path tmpDir(/tmp); std::filesystem::path testPath = tmpDir / test; if (!create_directory(testPath)) { std::cout test directory already exists 'n'; } testPath /= data.txt; std::ofstream dataFile(testPath.string()); if (dataFile) { dataFile the answer is 42n; } create_symlink(testPath, std::filesystem::path(slinkToTestDir)); } catch (std::filesystem::filesystem_error e) { std::cout error creating e.path1() : e.what() 'n'; } } 1R FKDQJH IURP %RRVW)676 $3, H[FHSW KHDGHU ILOH DQG QDPHVSDFH Nico Josuttis C++17 @CodeHard 72
  • 230. ‹ E ,7FRPPXQLFDWLRQFRP 6ZLWFKLQJ RYHU 7SHV RI DQ ,QLWLDOL]HG )LOHVVWHP 3DWK void checkFilename(const std::string name) { namespace fs = std::filesystem; switch (fs::path p(name); status(p).type()) { case fs::file_type::not_found: std::cout p not foundn; break; case fs::file_type::directory: std::cout p :n; for (const auto entry : fs::directory_iterator(p)) { std::cout - entry.path() 'n'; } break; default: std::cout p existsn; break; } } QHZ switch ZLWK LQLWLDOL]DWLRQ ‹ E ,7FRPPXQLFDWLRQFRP +RZ WR XVH WKH )LOHVVWHP /LEUDU ‡ 8VH ERRVW ± %RRVW )LOHVVWHP VXSSRUW FORVH WR )LOHVVWHP 76
  • 231. #include boost/filesystem.hpp namespace std { namespace filesystem = boost::filesystem; } ‡ 8VH JFFJ ± )LOHVVWHP VXSSRUW ± VLQFH J ZLWK -lstdc++fs #include filesystem ‡ 8VH 9LVXDO ± ([SHULPHQWDO )LOHVVWHP 76 VXSSRUW ± VLQFH 96 #include experimental/filesystem namespace std { namespace filesystem = std::experimental::filesystem; } Nico Josuttis C++17 @CodeHard 73
  • 232. ‹ E ,7FRPPXQLFDWLRQFRP )LOHVVWHP 3ULQFLSOHV ‡ RPPRQ QDPHVSDFH FRQYHQWLRQ ± namespace fs = std::namespace; ‡ 0HPEHU IXQFWLRQV YHUVXV IUHHVWDQGLQJ IXQFWLRQV ± 0HPEHU IXQFWLRQV DUH FKHDS ‡ 3XUH OH[LFDO RSHUDWLRQV HJ p.is_absolute()
  • 233. ± )UHHVWDQGLQJ IXQFWLRQV DUH H[SHQVLYH ‡ 7DNH DFWXDO ILOHVVWHP LQWR DFFRXQW HJ equivalent(p1, p2)
  • 234. ‡ )OH[LEOH HUURU KDQGOLQJ ± )XQFWLRQV PLJKW ‡ UHWXUQ VRPHWKLQJ VSHFLDO RQ VSHFLILF HUURUV DQG RWKHUZLVH WKURZ std::filesystem::filesystem_error ‡ UHWXUQ HUURU FRGH LQ SDVVHG std::error_code DUJXPHQW ‹ E ,7FRPPXQLFDWLRQFRP )LOHVVWHP (UURU +DQGOLQJ ‡ )XQFWLRQV PLJKW ± UHWXUQ VRPHWKLQJ VSHFLDO RQ VSHFLILF HUURUV DQG RWKHUZLVH WKURZ std::filesystem::filesystem_error ± UHWXUQ HUURU FRGH LQ SDVVHG std::error_code DUJXPHQW try { if (!create_directory(p)) { H[FHSWLRQ RQ HUURU XQOHVV SDWK H[LVWV
  • 235. std::cout p already existsn; SDWK H[LVWV } } catch (const std::filesystem::filesystem_error e) { GHULYHG IURP VWGH[FHSWLRQ std::cout EXCEPTION: e.what() 'n'; std::cout path: e.path1() 'n'; } std::error_code ec; if (!create_directory(p, ec)) { VHW HUURU FRGH RQ HUURU std::cout can't create directory p n; DQ HUURU RFFXUUHG } if (ec) { LI HUURU FRGH VHW GXH WR RWKHU HUURU
  • 236. std::cout ERROR: ec.message() n; } if (ec == std::errc::read_only_file_system) { LI VSHFLILF HUURU FRGH VHW std::cout ERROR: p is read-onlyn; } Nico Josuttis C++17 @CodeHard 74
  • 237. ‹ E ,7FRPPXQLFDWLRQFRP 6VWHP (UURU RQGLWLRQV (UURU RQGLWLRQ RUUHVSRQGLQJ (UUQR 9DOXH DGGUHVVBIDPLOBQRWBVXSSRUWHG ($)126833257 DGGUHVVBLQBXVH ($''5,186( DGGUHVVBQRWBDYDLODEOH ($''5127$9$,/ DOUHDGBFRQQHFWHG (,6211 DUJXPHQWBOLVWBWRRBORQJ (%,* DUJXPHQWBRXWBRIBGRPDLQ ('20 EDGBDGGUHVV ()$8/7 EDGBILOHBGHVFULSWRU (%$') EDGBPHVVDJH (%$'06* EURNHQBSLSH (3,3( FRQQHFWLRQBDERUWHG (211$%257(' FRQQHFWLRQBDOUHDGBLQBSURJUHVV ($/5($' FRQQHFWLRQBUHIXVHG (2115()86(' FRQQHFWLRQBUHVHW (2115(6(7 FURVVBGHYLFHBOLQN (;'(9 GHVWLQDWLRQBDGGUHVVBUHTXLUHG ('(67$''55(4 GHYLFHBRUBUHVRXUFHBEXV (%86 GLUHFWRUBQRWBHPSW (127(037 H[HFXWDEOHBIRUPDWBHUURU (12(;( ILOHBH[LVWV ((;,67 ILOHBWRRBODUJH ()%,* ILOHQDPHBWRRBORQJ (1$0(722/21* IXQFWLRQBQRWBVXSSRUWHG (1266 KRVWBXQUHDFKDEOH (+267815($+ LGHQWLILHUBUHPRYHG (,'50 LOOHJDOBEWHBVHTXHQFH (,/6(4 LQDSSURSULDWHBLRBFRQWUROBRSHUDWLRQ (1277 LQWHUUXSWHG (,175 LQYDOLGBDUJXPHQW (,19$/ LQYDOLGBVHHN (63,3( LRBHUURU (,2 LVBDBGLUHFWRU (,6',5 PHVVDJHBVL]H (06*6,=( QHWZRUNBGRZQ (1(7'2:1 QHWZRUNBUHVHW (1(75(6(7 QHWZRUNBXQUHDFKDEOH (1(7815($+ QRBEXIIHUBVSDFH (12%8)6 QRBFKLOGBSURFHVV (+,/' QRBOLQN (12/,1. (UURU RQGLWLRQ RUUHVSRQGLQJ (UUQR 9DOXH QRBORFNBDYDLODEOH (12/. QRBPHVVDJHBDYDLODEOH (12'$7$ QRBPHVVDJH (1206* QRBSURWRFROBRSWLRQ (1235272237 QRBVSDFHBRQBGHYLFH (1263 QRBVWUHDPBUHVRXUFHV (1265 QRBVXFKBGHYLFHBRUBDGGUHVV (1;,2 QRBVXFKBGHYLFH (12'(9 QRBVXFKBILOHBRUBGLUHFWRU (12(17 QRBVXFKBSURFHVV (65+ QRWBDBGLUHFWRU (127',5 QRWBDBVRFNHW (12762. QRWBDBVWUHDP (12675 QRWBFRQQHFWHG (127211 QRWBHQRXJKBPHPRU (120(0 QRWBVXSSRUWHG (127683 RSHUDWLRQBFDQFHOHG ($1(/(' RSHUDWLRQBLQBSURJUHVV (,1352*5(66 RSHUDWLRQBQRWBSHUPLWWHG (3(50 RSHUDWLRQBQRWBVXSSRUWHG (231276833 RSHUDWLRQBZRXOGBEORFN (:28/'%/2. RZQHUBGHDG (2:1(5'($' SHUPLVVLRQBGHQLHG ($(6 SURWRFROBHUURU (35272 SURWRFROBQRWBVXSSRUWHG (35272126833257 UHDGBRQOBILOHBVVWHP (52)6 UHVRXUFHBGHDGORFNBZRXOGBRFFXU ('($'/. UHVRXUFHBXQDYDLODEOHBWUBDJDLQ ($*$,1 UHVXOWBRXWBRIBUDQJH (5$1*( VWDWHBQRWBUHFRYHUDEOH (1275(29(5$%/( VWUHDPBWLPHRXW (7,0( WH[WBILOHBEXV (7;7%6 WLPHGBRXW (7,0('287 WRRBPDQBILOHVBRSHQBLQBVVWHP (1),/( WRRBPDQBILOHVBRSHQ (0),/( WRRBPDQBOLQNV (0/,1. WRRBPDQBVPEROLFBOLQNBOHYHOV (/223 YDOXHBWRRBODUJH (29(5)/2: ZURQJBSURWRFROBWSH (3527273( might EH HUURU FRGH value() SRUWDEOH ‹ E ,7FRPPXQLFDWLRQFRP )LOHVVWHP 87) 6XSSRUW ‡ )LOHVVWHP SDWKV VXSSRUWV 87) VWULQJV namespace fs = std::filesystem; FUHDWH GLUHFWRU IURP UHWXUQHG 87) VWULQJ fs::create_directory(fs::u8path(u8Ku00F6ln)); .|OQ RORJQH QDWLYH
  • 238. std::string utf8String = readUTF8String(); fs::create_directory(fs::u8path(utf8String)); VWRUH SDWKV DV 87) VWULQJ std::vectorstd::string utf8paths; for (const auto entry : fs::directory_iterator(p)) { utf8paths.push_back(entry.path().u8string()); } FRQYHUVLRQ EHWZHHQ QDWLYH DQG 87) FKDUDFWHU VHW PXVW EH YDOLG SDWK
  • 239. utf8str = std::filesystem::path(str).u8string(); FRQYHUW QDWLYH WR 87) VWULQJ str = std::filesystem::u8path(utf8str).string(); FRQYHUW 87) WR QDWLYH VWULQJ 1RQLQWHQGHG XVDJH KLQW E 7RP +RQHUPDQQ
  • 240. vectoru8string ZLWK LQWURGXFLQJ char8_t IRU 87) FKDUV
  • 242. ‹ E ,7FRPPXQLFDWLRQFRP ILOHQDPH VWHP H[W ILOHQDPH VWHP H[W ILOHQDPH VWHP H[W ILOHQDPH VWHP H[W ILOHQDPH VWHP H[W ILOHQDPH VWHP H[WHQVLRQ 7HUPLQRORJ (OHPHQWV RI D 3DWK ‡ 7HUPV ± 5RRW1DPH KRVW RU RU ± 5RRW'LUHFWRU VDPH DV GLUHFWRU VHSDUDWRU ± 'LUHFWRU6HSDUDWRU RU ? RU RU ?? ‡ PXOWLSOH VHSDUDWRUV DUH LQWHUSUHWHG DV RQH GLU VHSDU URRW QDPH URRW GLU GLU VHSDU ? IRR ? EDU ? ILOH W[W KRVW IRR EDU ILOH W[W GLU VHSDU URRW QDPH URRW GLU GLUHFWRU VHSDUDWRU H[WHQVLRQ ‡ IURP ODVW WLO HQG ‡ XQOHVV VWHP ZRXOG EH HPSW QHZ
  • 243. ‹ E ,7FRPPXQLFDWLRQFRP )LOHVVWHP 0RGLILQJ ([DPSOH #include iostream #include filesystem using namespace std; using namespace std::filesystem; int main () { path p0 = path(foo) / bar; cout p0 'n'; path p(/foo/bar/data.txt); cout p 'n'; p.make_preferred(); cout p 'n'; cout decomposition:n; cout p.root_name() 'n'; cout p.root_directory() 'n'; cout p.root_path() 'n'; cout p.relative_path() 'n'; cout p.parent_path() 'n'; cout p.filename() 'n'; cout p.stem() 'n'; cout p.extension() 'n'; cout p.is_absolute() 'n'; } foo/bar foobar / / foo/bar/data.txt /foo/bar data.txt data .txt 1 WUXH
  • 246. ‹ E ,7FRPPXQLFDWLRQFRP )LOHQDPH KDQJHV IRU ‡ )LOHQDPHV VWDUWLQJ ZLWK . DUH QR H[WHQVLRQV ‡ )LOHQDPH LV ZKDW LV EHWZHHQ URRW RU GLUHFWRU VHSDUDWRUV ± 5RRW HOHPHQWV DUH QR ILOHQDPHV • has_filename() LV QR ORQJHU WUXH IRU //host RU XQGHU :LQGRZV C: ± 3DWKV ZLWK WUDLOLQJ / KDYH QR ILOHQDPHV • has_filename() LV QR ORQJHU WUXH IRU foo/ ± $OZDV filename() == stem() extension() ‡ :KHQ LWHUDWLQJ RYHU D SDWK WKH HPSW VWULQJ UHSUHVHQWV D WUDLOLQJ QRQURRW GLUHFWRU VHSDUDWRU ± :H FDQ QRZ GLVWLQJXLVK EHWZHHQ URRWGLU WUDLOLQJ DQG LQ SDWKV ‡ /RRSV RI UHPRYHBILOHQDPH
  • 247. QR ORQJHU XQZLQG D SDWK ± 8VH LWHUDWRUV DQGRU ORRSV RYHU parent_path() ‹ E ,7FRPPXQLFDWLRQFRP ODULI ILOHQDPH
  • 250. IRREDUW[W EDUW[W EDU IRREDU EDU EDU IRREDUJLW JLW IRREDU IRREDU KRVW KRVW KRVW KRVW RU RU RU IRR RU RU RU 8QL[ YV :LQGRZV ‡ 5HPHPEHU ,Q 8QL[ LV QRWKLQJ VSHFLDO Nico Josuttis C++17 @CodeHard 77
  • 251. ‹ E ,7FRPPXQLFDWLRQFRP ODULI ILOHQDPH
  • 256. VWHP
  • 258. WUXH WUXH IRREDUW[W EDUW[W EDU EDUW[W WUXH EDU W[W IRREDU EDU EDU EDU WUXH EDU IRREDUJLW JLW JLW WUXH JLW IRREDU WUXH IRREDU IDOVH IDOVH KRVW KRVW KRVW IDOVH KRVW IDOVH RU RU WUXH RU IDOVH RU RU RU IDOVH IRR IDOVH RU RU RU WUXH RU RU IDOVH ‹ E ,7FRPPXQLFDWLRQFRP )LOHVVWHP 6HPDQWLF KDQJHV ZLWK #include experimental/filesystem ROG OLE IURP )LOHVVWHP 76
  • 259. #include filesystem QHZ OLE VLQFH
  • 260. #include iostream int main (int argc, char* argv[]) { if (argc 2) { std::cout Usage: argv[0] path n; return EXIT_FAILURE; } namespace fs = std::experimental::filesystem; ROG OLE IURP )LOHVVWHP 76
  • 261. namespace fs = std::filesystem; QHZ OLE IURP
  • 262. fs::path p(argv[1]); S UHSUHVHQWV D ILOHVVWHP SDWK PLJKW RU PLJKW QRW H[LVW
  • 263. std::cout fn(): p.filename() 'n'; std::cout stem(): p.stem() 'n'; FKDQJHG ZLWK std::cout ext(): p.extension() 'n'; FKDQJHG ZLWK while (p.has_filename()) { FKDQJHG ZLWK p.remove_filename(); FKDQJHG ZLWK std::cout p: p 'n'; std::cout fn: p.filename() 'n'; } } ([SHULPHQWDO 2XWSXW $ prog /usr/home/nico/.git fn(): .git stem(): ext(): .git p: usrhomenico fn: nico p: usrhome fn: home p: usr fn: usr p: fn: p: fn: p: fn: $OWHUQDWLYHV Nico Josuttis C++17 @CodeHard 78
  • 264. ‹ E ,7FRPPXQLFDWLRQFRP )LOHVVWHP 6HPDQWLF KDQJHV ZLWK #include experimental/filesystem ROG OLE IURP )LOHVVWHP 76
  • 265. #include filesystem QHZ OLE VLQFH
  • 266. #include iostream int main (int argc, char* argv[]) { if (argc 2) { std::cout Usage: argv[0] path n; return EXIT_FAILURE; } namespace fs = std::experimental::filesystem; ROG OLE IURP )LOHVVWHP 76
  • 267. namespace fs = std::filesystem; QHZ OLE IURP
  • 268. fs::path p(argv[1]); S UHSUHVHQWV D ILOHVVWHP SDWK PLJKW RU PLJKW QRW H[LVW
  • 269. std::cout fn(): p.filename() 'n'; std::cout stem(): p.stem() 'n'; FKDQJHG ZLWK std::cout ext(): p.extension() 'n'; FKDQJHG ZLWK while (p.has_filename()) { FKDQJHG ZLWK p.remove_filename(); FKDQJHG ZLWK std::cout p: p 'n'; std::cout fn: p.filename() 'n'; } } 2XWSXW VLQFH $ prog /usr/home/nico/.git fn(): .git stem(): .git ext(): p: /usr/home/nico/ fn: ([SHULPHQWDO 2XWSXW $ prog /usr/home/nico/.git fn(): .git stem(): ext(): .git p: usrhomenico fn: nico p: usrhome fn: home p: usr fn: usr p: fn: p: fn: p: fn: $OWHUQDWLYHV ‹ E ,7FRPPXQLFDWLRQFRP ([DPSOHV ZLWK 6PEROLF /LQNV RPPDQGOLQH VKHOOV DUH FKHDWLQJ ‡ $IWHU cd a/d/e ‡ , DP LQ a/b ‡ %XW VKHOOV pwd FODLP WR EH LQ a/d/e ‡ ls ../e LV QRW DQ HUURU ‡ cd ../e LV QRW DQ HUURU ‡ 7U cd –P pwd –P Nico Josuttis C++17 @CodeHard 79
  • 270. ‹ E ,7FRPPXQLFDWLRQFRP ([DPSOHV ZLWK 6PEROLF /LQNV 1RWH VRPH FRPPDQGOLQH VKHOOV OLH ‡ $IWHU cd a/d/e ‡ , DP LQ a/b ‡ %XW VKHOOV FODLP , DP LQ a/d/e ‡ ls ../e LV QRW DQ HUURU ‡ cd ../e LV QRW DQ HUURU ‡ 7U pwd –P DQG cd –P ‹ E ,7FRPPXQLFDWLRQFRP namespace fs = std::filesystem; fs::path from(/a/b/c); fs::path to(/a/b/d); fs::path rel = fs::lexically_relative(to, from); FKHDS rel = fs::relative(to, from); H[SHQVLYH std::cout rel 'n'; RXWSXWV ../d auto abs = fs::absolute(from/rel); std::cout abs 'n'; RXWSXWV DEFG std::cout to 'n'; RXWSXWV DEG std::cout equal: (abs == to) 'n'; RXWSXWV equal: 0 IDOVH
  • 271. std::cout equivalent: ; if (fs::exists(abs) fs::exists(to)) { std::cout fs::equivalent(abs, to) 'n'; HUURU LI RQH GRHVQ W H[LVW } else { std::cout (abs.lexically_normal() == to.lexically_normal()) 'n'; } )LOHVVWHP 5HODWLYH 3DWK )XQFWLRQ E D F G Nico Josuttis C++17 @CodeHard 80
  • 272. ‹ E ,7FRPPXQLFDWLRQFRP )LOHVVWHP 3DWK ([DPSOH std::filesystem::path px(/tmp/a/x); std::filesystem::path py(/tmp/a/y); std::filesystem::current_path(/tmp); FKDQJH FXUUHQW SDWK std::cout std::filesystem::current_path(); WPS std::cout px.relative_path(); SDWK IURP WRS ZLWKRXW URRW WPSD[ std::cout px.lexically_relative(py); WR S[ IURP S [ std::cout relative(px,py); WR S[ IURP S [ std::cout relative(px); WR S[ IURP FXUUHQW SDWK D[ std::filesystem::path s{/tmp/a/s}; std::cout px.lexically_relative(s); WR S[ IURP V [ std::cout relative(px, s); WR S[ IURP V [ D WPS [ V FXUUHQW SDWK H[SHQVLYH FKHDS ‹ E ,7FRPPXQLFDWLRQFRP std::filesystem::path px(/tmp/a/x); std::filesystem::path py(/tmp/a/y); std::filesystem::current_path(/tmp); FKDQJH FXUUHQW SDWK std::cout std::filesystem::current_path(); WPS std::cout px.relative_path(); SDWK IURP WRS ZLWKRXW URRW WPSD[ std::cout px.lexically_relative(py); WR S[ IURP S [ std::cout relative(px,py); WR S[ IURP S [ std::cout relative(px); WR S[ IURP FXUUHQW SDWK D[ std::filesystem::path s{/tmp/a/s}; std::cout px.lexically_relative(s); WR S[ IURP V [ std::cout relative(px, s); WR S[ IURP V [ create_directories(px); create_directories(py); std::filesystem::create_symlink(/tmp, s); std::cout px.lexically_relative(s); WR S[ IURP V [ std::cout relative(px, s); WR S[ IURP V D[ VOLQN UHVROYHG
  • 273. V )LOHVVWHP 3DWK ([DPSOH D WPS V[ FXUUHQW GLU H[SHQVLYH FKHDS Nico Josuttis C++17 @CodeHard 81
  • 274. ‹ E ,7FRPPXQLFDWLRQFRP /LEUDU ([WHQVLRQV DQG 0RGLILFDWLRQV ‹ E ,7FRPPXQLFDWLRQFRP 3DUDOOHO ([HFXWLRQ RI 67/ $OJRULWKPV ‡ ([HFXWLRQ RI 67/ DOJRULWKPV LQ SDUDOOHO ‡ 'LIIHUHQW H[HFXWLRQ SROLFLHV ± VHTXHQWLDO ± SDUDOOHO ± SDUDOOHO VHTXHQFHG YHFWRUL]HG
  • 275. ‡ 1RWH ± $OO DOJRULWKPV UHTXLUH DW OHDVW IRUZDUG LWHUDWRUV 35
  • 276. ± 6XSSOHPHQWDU DOJRULWKPV IRU SDUDOOHOL]DWLRQ ‡ %HWD LPSOHPHQWDWLRQV ± 0LFURVRIW KWWSSDUDOOHOVWOFRGHSOH[FRP ± +3; KWWSVWHOODUJURXSJLWKXELRKS[GRFVKWPOKS[PDQXDOSDUDOOHOKWPO ± RGHSOD KWWSJLWKXEFRP.KURQRV*URXS6FO3DUDOOHO67/ ± +6$ KWWSZZZKVDIRXQGDWLRQFRPKVDIRUPDWKVFLHQFH ± 7KLEDXW /XW] KWWSJLWKXEFRPWOXW]3DUDOOHO67/ ± 19,',$ KWWSJLWKXEFRPQQ Nico Josuttis C++17 @CodeHard 82
  • 277. ‹ E ,7FRPPXQLFDWLRQFRP 8VLQJ 3DUDOOHO $OJRULWKPV #include vector #include iostream #include algorithm #include execution IRU WKH H[HFXWLRQ SROLF template typename C, typename P void count(const C coll, P execpolicy) { FRXQW HOHPHQWV ZLWK HYHQ YDOXH auto num = std::count_if(execpolicy, H[HFXWLRQ SROLF coll.cbegin(), coll.cend(), UDQJH [](int elem){ FULWHULRQ return elem % 2==0; }); std::cout number of elements with even value: num 'n'; } int main() { std::vectorint coll; count(coll, std::execution::seq); count(coll, std::execution::par); count(coll, std::execution::par_unseq); } ‹ E ,7FRPPXQLFDWLRQFRP 3DUDOOHO ([HFXWLRQ 3ROLFLHV 3DUDOOHO VHTXHQFHG H[HFXWLRQ F D E F D E F D E F D E F D E F D E F D E F D E F D E 3DUDOOHO XQVHTXHQFHG H[HFXWLRQ 6HTXHQWLDO H[HFXWLRQ ‡ 0XOWLSOH WKUHDGV PLJKW H[HFXWH WDVNV ‡ 7KUHDGV PLJKW H[HFXWH SDUWV RI RWKHU WDVNV EHIRUH HQGLQJ WKH ILUVW WDVN Ÿ 'RQ W ORFN RQ WKH VDPH PXWH[ Ÿ 1R PHPRU GH
  • 278. DOORFDWLRQ ‡ 0XOWLSOH WKUHDGV PLJKW H[HFXWH WDVNV ‡ 7DVNV DUH SURFHVVHG VHTXHQFHG IURP EHJLQ WR HQG Ÿ $OO VWHSV PXVW EH DEOH WR EH GRQH FRQFXUUHQWO ‡ 2QH WKUHDG H[HFXWHV DOO WDVNV RQH DIWHU WKH RWKHU ‡ 6HTXHQFHG IURP EHJLQ WR HQG Nico Josuttis C++17 @CodeHard 83
  • 279. ‹ E ,7FRPPXQLFDWLRQFRP :KHQ WR XVH ZKLFK 3DUDOOHO ([HFXWLRQ 3ROLF transform (std::execution::par_unseq, coll1.begin(),coll1.end(), VRXUFH UDQJH coll2.begin(), GHVWLQDWLRQ UDQJH [] (auto x) { RSHUDWLRQ auto y = x * x; 2. IRU HDFK HOHPHQW WKH RQO UHTXLUHPHQW LV return y; 2. WR NHHS WKH RUGHU RI VWDWHPHQWV }); transform (std::execution::par, coll1.begin(),coll1.end(), VRXUFH UDQJH coll2.begin(), GHVWLQDWLRQ UDQJH [] (auto x) { RSHUDWLRQ std::lock_guard lg(m); 2. IRU par EXW QRW IRU par_unseq return x*x; }); transform (std::execution::seq, coll1.begin(),coll1.end(), VRXUFH UDQJH coll2.begin(), GHVWLQDWLRQ UDQJH [] (auto x) { RSHUDWLRQ logFile x; FRQFXUUHQW DFFHVV WR ILOHV LV D UDFH return x*x; }); ‹ E ,7FRPPXQLFDWLRQFRP 3DUDOOHO $OJRULWKPV 6XSSRUW ZLWK 9LVXDO 6WXGLR KWWSEORJVPVGQPLFURVRIWFRPYFEORJFSURJUHVVLQYVDQG ‡ We’re gradually implementing experimental support for the parallel algorithms. ‡ Here are the parallel algorithms that we’ve implemented: ± LQWHQWLRQDOO QRW SDUDOOHOL]HG copy() copy_n() fill() fill_n() move() reverse() reverse_copy() rotate() rotate_copy() swap_ranges() ‡ The signatures for these parallel algorithms are added but not parallelized at this time; profiling showed no benefit in parallelizing algorithms that only move or permute elements ± all_of() any_of() for_each() for_each_n() none_of() reduce() replace() replace_if() sort() ± 3UHYLHZ adjacent_find() count() count_if() equal() find() find_end() find_first_of() find_if() find_if_not() ± DIWHU 3UHYLHZ mismatch() remove() remove_if() search() search_n() transform() ± [ partition() stable_sort() Nico Josuttis C++17 @CodeHard 84
  • 280. ‹ E ,7FRPPXQLFDWLRQFRP 1HZ 67/ $OJRULWKPV ‡ 6XSSOHPHQWDU DOJRULWKPV VXSSRUW SDUDOOHO SURFHVVLQJ ± IRUBHDFKBQbeg count op
  • 282. ‡ $SSOLHV op WR counW HOHPHQWV RI UDQJH VWDUWLQJ IURP beg XVLQJ H[HFXWLRQ SROLF pol
  • 286. ‡ /LNH accumulate() EXW DSSOLHV op LQ DQ XQVSHFLILHG RUGHU ‡ LHOGV D QRQGHWHUPLQLVWLF UHVXOW IRU QRQDVVRFLDWLYH RU QRQFRPPXWDWLYH op VXFK DV IORDWLQJSRLQW DGGLWLRQ ± WUDQVIRUPBUHGXFH
  • 287. ‡ $FFXPXODWH WUDQVIRUPHG SDVVHG HOHPHQW HJ VXPSURGXFW RI op(elem)
  • 292. ‹ E ,7FRPPXQLFDWLRQFRP 8VLQJ transform_reduce() #include numeric IRU WUDQVIRUPBUHGXFH
  • 293. #include execution IRU WKH H[HFXWLRQ SROLF void printDirSize(const std::string dir) { LQLW paths ZLWK DOO SDWKV IURP GLUHFWRU dir std::vectorstd::filesystem::path paths; std::filesystem::recursive_directory_iterator dirpos(dir); std::copy(begin(dirpos), end(dirpos), std::back_inserter(paths)); VXP VL]H RI UHJXODU ILOHV auto sz = std::transform_reduce( std::execution::par, SDUDOOHO H[HFXWLRQ SROLF RSW
  • 294. paths.cbegin(), paths.cend(), UDQJH std::uintmax_t{0}, LQLWLDO YDOXH DQG UHWXUQ WSH
  • 295. std::plus(), DGG [](const std::filesystem::path p) { ILOH VL]H LI UHJXODU ILOH return is_regular_file(p) ? file_size(p) : std::uintmax_t{0}; }); std::cout sum of size of regular files: sz 'n'; } DQ W SDVV GLUHFWRU LWHUDWRU WR SDUDOOHO DOJRULWKPV EHFDXVH WKH UHTXLUH IRUZDUG LWHUDWRUV DOO ODPEGD IRU HDFK HOHPHQW DQG DFFXPXODWH UHVXOWV Nico Josuttis C++17 @CodeHard 85
  • 300. ± LHOG YDOXH FRQVWUDLQW WR EH EHWZHHQ min DQG max XVLQJ RS WR FRPSDUH YDOXHV
  • 301. ± )LUVW IRUP LHOGV VWGPLQVWGPD[valmin
  • 302. max
  • 303. ‡ VDPSOHbegend out maxCount gen
  • 304. ± H[WUDFW VDPSOH IURP begend
  • 305. WR out DFFRUGLQJ WR UDQGRP QXPEHU JHQHUDWRU gen ‡ VHOHFWLRQ VDPSOLQJ DQG UHVHUYRLU VDPSOLQJ ‹ E ,7FRPPXQLFDWLRQFRP %RHU 0RRUH 6XEVWULQJ 6HDUFKHUV ‡ GHIDXOWBVHDUFKbegend
  • 313. ± )XQFWLRQ REMHFWV IRU IDVWHU VXEVWULQJ VHDUFK LPSOHPHQWLQJ WKH %RHU0RRUH+RUVSRRO
  • 314. DOJRULWKPV QHHGOH LQ KDVWDFN
  • 315. ‡ VHH KWWSVHQZLNLSHGLDRUJZLNL%RHU0RRUHBVWULQJBVHDUFKBDOJRULWKP ‡ VHH KWWSZZZERRVWRUJGRFOLEVBBOLEVDOJRULWKPGRFKWPODOJRULWKP6HDUFKLQJKWPO ‡ VWGVHDUFKbegend searcher
  • 316. ± WR VZLWFK EHWZHHQ WUDGLWLRQDO DQG %RZHU0RRUH VHDUFK Nico Josuttis C++17 @CodeHard 86
  • 317. ‹ E ,7FRPPXQLFDWLRQFRP %RHU 0RRUH +RUVSRRO
  • 318. 6HDUFKHUV #include iostream #include string #include functional IRU VHDUFKHUV int main() { std::string in = R(Remember, an easy question can have an easy answer. But a hard question must have a hard answer. And for the hardest questions of all, there may be no answer - except faith.); std::string sub = question; std::default_searcher searcher{sub.begin(), sub.end()}; FODVVLF std::boyer_moore_searcher searcher{sub.begin(), sub.end()}; IDVWHVW std::boyer_moore_horspool_searcher searcher{sub.begin(), sub.end()}; OHVV VSDFH for (auto pos=in.begin(); pos!=in.end(); ) { auto [beg, end] = searcher(pos, in.end()); std::cout found ' sub ' at offsets beg - in.begin() - end - in.begin() n; pos = end; } } $OWHUQDWLYHV 2XWSXW found 'question' at offsets 18-26 found 'question' at offsets 85-93 found 'question' at offsets 161-169 found 'question' at offsets 236-236 ‹ E ,7FRPPXQLFDWLRQFRP 6XSSRUW IRU ,QFRPSOHWH 7SHV ‡ 9HFWRUV DQG IRUZDUG
  • 319. OLVWV QRZ VXSSRUW LQFRPSOHWH WSHV class Node { private: std::string value; std::vectorNode next; 2. VLQFH Node LV DQ LQFRPSOHWH WSH KHUH
  • 320. public: Node(const std::string s) : value{s}, next{} { } void add(const Node n) { next.push_back(n); } Node operator[](std::size_t idx) { return next.at(idx); } }; Node root{root}; root.add(Node{add1}); root.add(Node{add2}); root[0].add(Node{add3}); Nico Josuttis C++17 @CodeHard 87
  • 321. ‹ E ,7FRPPXQLFDWLRQFRP RQWDLQHU ,PSURYHPHQWV ‡ WUBHPSODFH
  • 322. ± IRU PDS XQRUGHUHGBPDS ‡ HPSODFHBEDFN
  • 324. ± QRZ UHWXUQ D UHIHUHQFH WR WKH LQVHUWHG HOHPHQW ± IRU YHFWRU GHTXH OLVW IRUZDUGBOLVW VWDFN TXHXH ‡ QRQFRQVW GDWD
  • 325. IRU VWULQJV ‡ ,QWHUIDFH WR DVVRFLDWLYHXQRUGHUHG FRQWDLQHUV WR VSOLFH HOHPHQWV RU PRGLI NHV ZLWKRXW UHDOORFDWLRQ ‹ E ,7FRPPXQLFDWLRQFRP 6SOLFLQJ 8QRUGHUHG
  • 326. 6HW DQG 0DS (OHPHQWV ‡ ,QWHUIDFH DQG WSH WR VSOLFH HOHPHQWV QRGHV
  • 328. VHWV DQG PDSV ± )RU ‡ KHDS PRGLILFDWLRQ RI NHV ‡ ,QWHUIDFH WR VXSSRUW PRYHRQO HOHPHQW WSHV ± %HWWHU SHUIRUPDQFH WKDQ remove() DQG insert() ± 5HIHUHQFHVSRLQWHUV WR HOHPHQWV UHPDLQ YDOLG ± 2QO HOHPHQW WSHV DQG DOORFDWRU
  • 329. KDYH WR PDWFK ‡ RPSDULVRQ FULWHULRQ KDVK IXQFWLRQ PLJKW GLIIHU ‡ DQ PRYH IURP PXOWL WR QRQPXOWL FRQWDLQHU ‡ 7SH IRU QRGH KDQGOH container::node_type ± 0HPEHU value() IRU DOO VHW WSHV ± 0HPEHUV key()DQG mapped() IRU DOO PDS WSHV ± 8VHV PRYH VHPDQWLFV Nico Josuttis C++17 @CodeHard 88
  • 330. ‹ E ,7FRPPXQLFDWLRQFRP KHDS 0RGLILFDWLRQ RI 8QRUGHUHG
  • 331. 6HW0DS .HV 0RGLILQJ WKH NH RI D VHWPDS HOHPHQW std::mapint, std::string m{{1,mango}, {2,papaya}, {3,guava}}; auto nh = m.extract(2); nh KDV WSH decltype(m)::node_type nh.key() = 4; m.insert(std::move(nh)); (UURU ZLWKRXW move() SDSDD PDQJR JXDYD JXDYD PDQJR SDSDD SDSDD PDQJR JXDYD nh ‡ 5HIHUHQFHVSRLQWHUV WR HOHPHQWV UHPDLQ YDOLG ‡ %XW XQGHILQHG EHKDYLRU LI XVHG ZKLOH QRGH KDQGOH %HWZHHQ ‡ set DQG multiset ‡ map DQG multimap ‡ unordered_set DQG unordered_multiset ‡ unordered_map DQG unordered_multimap ‹ E ,7FRPPXQLFDWLRQFRP ([DPSOH IRU 6SOLFLQJ 6HW DQG 0DS (OHPHQWV 0RYLQJ HOHPHQWV IURP RQH KDVK WDEOH WR DQRWKHU std::unordered_multimapdouble, std::string src{{1.1,one}, {2.2,two}, {3.3,three}}; std::unordered_mapdouble, std::string dst{{3.3,new}}; dst.insert(src.extract(src.find(1.1))); VSOLFH XVLQJ DQ LWHUDWRU dst.insert(src.extract(2.2)); VSOLFH XVLQJ WKH NH auto [pos,done,node] = dst.insert(src.extract(3.3)); H[WUDFWV EXW if (!done) { GRHVQ W LQVHUW std::cout insert() of key ' node.key() ' with value ' node.mapped() ' failed due to existing elem with value ' pos-second 'n; } insert(node_type) UHWXUQV LQVHUWBUHWXUQBWSH ZLWK PHPEHUV LWHUDWRU SRVLWLRQ ERRO LQVHUWHG QRGHBWSH QRGH Nico Josuttis C++17 @CodeHard 89
  • 332. ‹ E ,7FRPPXQLFDWLRQFRP 1HZ OLWWOH KHOSHUV ‡ VWGDVBFRQVWobj
  • 333. ± LHOGV FRQVWDQW YLHZ WR obj QRW IRU WHPSRUDULHV UYDOXHV
  • 335. ± DYRLGV XVH RI FRQVWBFDVW DQGRU DGGBFRQVW! ± LQ XWLOLW! ‡ VWGVL]Hobj
  • 338. ± 8QLIRUP $3, WR FKHFN UDZ DUUDV FRQWDLQHUV LQLWLDOL]HUBOLVW V ± LQ LWHUDWRU! template typename T void check (const T t) { std::cout size: std::size(t) 'n'; std::cout empty: std::empty(t) 'n'; std::cout data: std::data(t) 'n'; SULQWV DGGUHVV } int arr[10] = { 42, 43, -1 }; check(arr); HPSW
  • 339. LV DOZDV IDOVH IRU DUUDV check(std::as_const(arr)); LHOGV VDPH DGGUHVV ZLWK GDWD
  • 341. std::initializer_listint il = { 42, 43, -1 }; check(il); GDWD
  • 343. ‹ E ,7FRPPXQLFDWLRQFRP 0XWH[ DQG *XDUG ODVVHV ‡ 0XWH[ FODVVHV E ± 6LPSOH PXWH[ std::mutex ± 1HVWHG PXWH[HV std::recursive_mutex ± 6LPSOH PXWH[ ZLWK WLPHRXW std::timed_mutex ± 1HVWHG PXWH[ ZLWK WLPHRXW std::recursive_timed_mutex ± 5HDG:ULWH PXWH[ std::shared_mutex VLQFH
  • 344. ± 5HDG:ULWH PXWH[ ZLWK WLPHRXW std::shared_timed_mutex VLQFH
  • 345. ‡ /RFN JXDUGV ± 6LPSOH JXDUG IRU PXWH[ std::lock_guard ± 6LPSOH VKDUHG UHDG IRU PXWH[ std::shared_lock VLQFH
  • 346. ± 6LPSOH JXDUG IRU PXOWLSOH PXWH[HV std::scoped_lock VLQFH
  • 347. ± 6RSKLVWLFDWHG JXDUG IRU PXWH[ std::unique_lock ORFN
  • 350. XQORFN
  • 352. ‹ E ,7FRPPXQLFDWLRQFRP 6KDUHG /RFNV ‡ 7R VXSSRUW 5HDG:ULWH /RFNV 5: ORFNV
  • 353. ± LQWURGXFHV ‡ ODVV std::shared_timed_mutex ‡ ODVV std::shared_lock ± LQWURGXFHV ‡ ODVV std::shared_mutex ‡ $OORZV WR VKDUH D ORFN IRU PXOWLSOH FRQFXUUHQW UHDGV ± 1R UHDGHU RU ZULWHU SUHIHUHQFH GHILQHG TXDOLW RI LPSOHPHQWDWLRQ
  • 354. ‡ *HQHULF DSSURDFK ± 8VH H[LVWLQJ ORFN LQWHUIDFHV IRU H[FOXVLYH ORFNV ± 8VH DGGLWLRQDO LQWHUIDFHV IRU VKDUHG ORFNV ‡ VSHFLDO VWDWH DYDLODEOH RQO LQ VKDUHG PXWH[HV std::shared_mutex sm; D PXWH[ WR ORFN
  • 359. FDOOHG KHUH ‹ E ,7FRPPXQLFDWLRQFRP VWGVFRSHGBORFN! ‡ VWGVFRSHGBORFN! ± 9DULDGLF YHUVLRQ RI std::lock_guard ± 7KXV LQ ZH KDYH lock_guard unique_lock scoped_lock void swap(const MyType l, const MyType r) { std::lock(l.mtx, r.mtx); 1RWH GHDGORFN DYRLGDQFH DOJRULWKP XVHG std::lock_guardstd::mutex lg1(l.mtx, std::adopt_lock); std::lock_guardstd::mutex lg2(r.mtx, std::adopt_lock); } void swap(const MyType l, const MyType r) { std::scoped_lock lg(l.mtx, r.mtx); } XVHV FODVV WHPSODWH DUJXPHQW GHGXFWLRQ Nico Josuttis C++17 @CodeHard 91
  • 360. ‹ E ,7FRPPXQLFDWLRQFRP 8VLQJ /RFN *XDUGV void threadUpdate() { std::unique_lock lg(doneMutex); while (true) { lg.unlock(); static double val = 1; { XSGDWH YHFWRU std::scoped_lock sl(vMutex); v.push_back(val); } val *= 2.3; std::this_thread::sleep_for(1s); lg.lock(); } } ILQDOO UHOHDVH GRQH ORFN void threadRead() { std::unique_lockmutex lg(doneMutex); while (true) { lg.unlock(); double val = 0; UHDG IURP YHFWRU if (std::shared_lock sl(vMutex); v.size()0) { val = v.back(); } XVH YDO lg.lock(); } } ILQDOO UHOHDVH GRQH ORFN #include shared_mutex #include mutex std::vectordouble v; VKDUHG UHVRXUFH std::shared_mutex vMutex; FRQWURO DFFHVV WR Y bool done = false; VLJQDO HQG std::mutex doneMutex; ‹ E ,7FRPPXQLFDWLRQFRP 8VLQJ /RFN *XDUGV void threadUpdate() { std::unique_lock lg(doneMutex); while (!done) { lg.unlock(); static double val = 1; { XSGDWH YHFWRU std::scoped_lock sl(vMutex); v.push_back(val); } val *= 2.3; std::this_thread::sleep_for(1s); lg.lock(); } } ILQDOO UHOHDVH GRQH ORFN void threadRead() { std::unique_lockmutex lg(doneMutex); while (!done) { lg.unlock(); double val = 0; UHDG IURP YHFWRU if (std::shared_lock sl(vMutex); v.size()0) { val = v.back(); } XVH YDO lg.lock(); } } ILQDOO UHOHDVH GRQH ORFN #include shared_mutex #include mutex std::vectordouble v; VKDUHG UHVRXUFH std::shared_mutex vMutex; FRQWURO DFFHVV WR Y bool done = false; VLJQDO HQG std::mutex doneMutex; void threadSignalEnd() { std::lock_guard lg(doneMutex); done = true; } UHOHDVH GRQH ORFN D ORW RI VKDUHG UHDGV RI done EORFN HDFK RWKHU Nico Josuttis C++17 @CodeHard 92
  • 361. ‹ E ,7FRPPXQLFDWLRQFRP 8VLQJ /RFN *XDUGV void threadUpdate() { while (true) { if (std::shared_lock dl(doneMutex); done) { break; } static double val = 1; { XSGDWH YHFWRU std::scoped_lock sl(vMutex); v.push_back(val); } val *= 2.3; std::this_thread::sleep_for(1s); } } void threadRead() { while (true) { if (std::shared_lock dl(doneMutex); done) { break; } double val = 0; UHDG IURP YHFWRU if (std::shared_lock sl(vMutex); v.size()0) { val = v.back(); } XVH YDO } } #include shared_mutex #include mutex std::vectordouble v; VKDUHG UHVRXUFH std::shared_mutex vMutex; FRQWURO DFFHVV WR Y bool done = false; VLJQDO HQG std::shared_mutex doneMutex; void threadSignalEnd() { std::lock_guard lg(doneMutex); done = true; } UHOHDVH GRQH ORFN EHWWHU WR XVH D FRQGLWLRQ YDULDEOH KHUH RI FRXUVH ‹ E ,7FRPPXQLFDWLRQFRP DWRPLF! 2SHUDWLRQV ‡ 7R FKHFN ZKHWKHU D WSH LV QDWLYHO DWRPLF ± 3UHSURFHVVRU FRQVWDQWV WDNHQ IURP
  • 362. #define ATOMIC_BOOL_LOCK_FREE unspecified #define ATOMIC_CHAR_LOCK_FREE unspecified #define ATOMIC_INT_LOCK_FREE unspecified #define ATOMIC_LONG_LOCK_FREE unspecified #define ATOMIC_LLONG_LOCK_FREE unspecified #define ATOMIC_POINTER_LOCK_FREE unspecified ... ‡ PLJKW LHOG 0 IRU QHYHU 1 IRU VRPHWLPHV 2 IRU DOZDV ORFNIUHH ± 0HPEHU IXQFWLRQ is_lock_free() ‡ LHOGV WUXH LI WKH REMHFW KDV QDWLYH DWRPLF VXSSRUW VR WKDW LW GRHVQ W XVH ORFNV ± 1 7KH SURSRVDO SURYLGHV ORFNIUHH TXHU IXQFWLRQV RQ LQGLYLGXDO REMHFWV UDWKHU WKDQ ZKROH WSHV WR SHUPLW XQDYRLGDEO PLVDOLJQHG DWRPLF YDULDEOHV ZLWKRXW SHQDOL]LQJ WKH SHUIRUPDQFH RI DOLJQHG DWRPLF YDULDEOHV ‡ 1RWH WKDW atomicint GLIIHUV IURP int HYHQ LI LW LV ORFN IUHH EHFDXVH LW LQWURGXFHV PHPRU EDUULHUV ZLOO DGG constexpr bool atomicT::is_always_lock_free Nico Josuttis C++17 @CodeHard 93
  • 363. ‹ E ,7FRPPXQLFDWLRQFRP 1HZ RQFXUUHQF ,QIRUPDWLRQV ‡ +HOSHU WR FKHFN ZKHWKHU DWRPLF WSHV XVH ORFNV ‡ 3RUWDEOH ZD WR DFFHVV WKH / GDWD FDFKH OLQH VL]H namespace std { template typename T struct atomic { static constexpr bool is_always_lock_free = implementation-defined; }; } namespace std { PLQLPXP UHFRPPHQGHG RIIVHW EHWZHHQ WZR FRQFXUUHQWODFFHVVHG REMHFWV inline constexpr size_t hardware_destructive_interference_size = implementation-defined; PD[LPXP UHFRPPHQGHG VL]H RI FRQWLJXRXV PHPRU RFFXSLHG E WZR REMHFWV inline constexpr size_t hardware_constructive_interference_size = implementation-defined; } ‹ E ,7FRPPXQLFDWLRQFRP 1HZ 0DWKHPDWLFDO )HDWXUHV ‡ 6SHFLDO QXPHULFDO IXQFWLRQV ± (OOLSWLF LQWHJUDOV 3ROQRPLDOV %HVVHO IXQFWLRQV ± ,6 ± 2QO LQ FPDWK! ZLWKLQ QDPHVSDFH VWG QRW LQ PDWKK!
  • 364. ‡ DGG gcd() DQG lcm() ± 7HPSODWHV IRU DOO LQWHJUDO WSHV DOVR FKDU
  • 365. H[FHSW bool ‡ DUJXPHQW hypot() ± )RU DOO IORDWLQJSRLQW WSHV ± 2QO LQ FPDWK! ZLWKLQ QDPHVSDFH VWG QRW LQ PDWKK!
  • 367. ‹ E ,7FRPPXQLFDWLRQFRP (OHPHQWDU 6WULQJ RQYHUVLRQV #include charconv const char* str = 12 monkeys; int value; std::from_chars_result res = std::from_chars(str, str+10, value); if (auto[ptr, ec] = std::from_chars(str, str+10, value); ec != std::errc{}) { HUURU KDQGOLQJ } int value = 42; char str[10]; std::to_chars_result res = std::to_chars(str, str+10, value); if (auto[ptr, ec] = std::to_chars(str, str+10, value); ec != std::errc{}) { HUURU KDQGOLQJ } ‡ /RZOHYHO $3, IRU SULQWI
  • 368. OLNH IRUPDWWLQJ ± VLPSOH IDVW ORFDOHLQGHSHQGHQW ‡ ,QFOXGLQJ URXQGWULS VXSSRUW ‹ E ,7FRPPXQLFDWLRQFRP (OHPHQWDU 6WULQJ RQYHUVLRQV to_chars(beg,end, 44) GHFLPDO to_chars(beg,end, 44, 16) KH[DGHFLPDO to_chars(beg,end, 44, 13) WR WKH EDVH RI EDVH EHWZHHQ @
  • 369. to_chars(beg,end, 44.1234567) GHFLPDO URXQGWULSDEOH I RU H DFF WR PLQLPDO FKDUV to_chars(beg,end, 44.1234567, chars_format::general) GHFLPDO J URXQGWULSDEOH to_chars(beg,end, 44.1234567, chars_format::fixed) GHFLPDO I URXQGWULSDEOH to_chars(beg,end, 44.1234567, chars_format::scientific) GHFLPDO H URXQGWULSDEOH to_chars(beg,end, 44.1234567, chars_format::hex) KH[ D URXQGWULSDEOH to_chars(beg,end, 44.1234567, chars_format::general, 4) GHFLPDO J SUHFLVLRQ to_chars(beg,end, 44.1234567, chars_format::fixed, 4) GHFLPDO I SUHFLVLRQ to_chars(beg,end, 44.1234567, chars_format::scientific, 4) GHFLPDO H SUHFLVLRQ to_chars(beg,end, 44.1234567, chars_format::hex, 4) KH[ D SUHFLVLRQ ‡ /RZOHYHO $3, IRU SULQWI
  • 370. OLNH IRUPDWWLQJ ± VLPSOH IDVW ORFDOHLQGHSHQGHQW ‡ ,QFOXGLQJ URXQGWULS VXSSRUW Nico Josuttis C++17 @CodeHard 95
  • 371. ‹ E ,7FRPPXQLFDWLRQFRP 6KDUHG 3RLQWHUV DQG 'HOHWHUV ‡ % GHIDXOW delete IRU VLQJOH REMHFWV
  • 372. LV FDOOHG ‡ RX FDQ DQG PLJKW KDYH WR
  • 373. SDVV RWKHU GHOHWHUV DV VHFRQG DUJXPHQW WR WKH FRQVWUXFWRU std::shared_ptrFILE pp(popen(), SS UHSUHVHQWV RSHQ SLSH [] (FILE* fp) { std::cout close pipe 'n'; pclose(fp); }); std::shared_ptrstd::string p(new std::string[10]); (5525 EXW FRPSLOHV std::shared_ptrstd::string p(new std::string[10], 2. RZQ GHOHWHU IRU DUUDV [](std::string* p) { delete[] p; }); std::shared_ptrstd::string p(new std::string[10], 2. GHIDXOW GHOHWHU IRU DUUDV std::default_deletestd::string[]()); std::shared_ptrstd::string[] p(new std::string[10]); 2. VLQFH ‹ E ,7FRPPXQLFDWLRQFRP %XJ
  • 374. )L[HV ‡ *XDUDQWHH WKDW VKDUHGBIURPBWKLV
  • 375. WKURZV bad_weak_ptr LI QR VKDUHG SRLQWHU ZDV FUHDWHG IRU DQ REMHFW HW ‡ $GGLQJ constexpr LQ D ORW RI SODFHV ± )RU H[DPSOH ‡ FKDUBWUDLWV ‡ FKURQR LV FRPSOHWH FRQVWH[SU H[FHSW now() to_time_t() DQG from_time_t() ‡ 3ROLVKLQJ FKURQR! ± $GG IORRU
  • 376. FHLO
  • 377. DEV
  • 378. URXQG
  • 379. ZKHUH PLVVLQJ Nico Josuttis C++17 @CodeHard 96
  • 380. ‹ E ,7FRPPXQLFDWLRQFRP ([SHUW 8WLOLWLHV ‹ E ,7FRPPXQLFDWLRQFRP 1HZ 7SH 7UDLWV VLQFH ‡ LVBDJJUHJDWH ± WR ILQG RXW ZKHWKHU DQ REMHFW LV DQ DJJUHJDWH WSH ‡ KDVBXQLTXHBREMHFWBUHSUHVHQWDWLRQV ± WR ILQG RXW ZKHWKHU HTXDO REMHFWV KDYH HTXDO KDVK YDOXHV ‡ LVBVZDSSDEOH LVBVZDSSDEOHBZLWK LVBQRWKURZBVZDSSDEOH LVBQRWKURZBVZDSSDEOHBZLWK ‡ LVBLQYRFDEOH LVBLQYRFDEOHBU LVBQRWKURZBLQYRFDEOH LVBQRWKURZBLQYRFDEOHBU LQYRNHBUHVXOW ± IRU REMHFWV WKDW FDQ EH XVHG DV IXQFWLRQV ± 7HPSRUDULO ZH KDG LVBFDOODEOH ‡ FRQMXQFWLRQ GLVMXQFWLRQ QHJDWLRQ ± RPELQH WSH WUDLWV IRU YDULDGLF WHPSODWHV 'HSUHFDWHG LVBOLWHUDOBWSH UHVXOWBRI Nico Josuttis C++17 @CodeHard 97
  • 381. ‹ E ,7FRPPXQLFDWLRQFRP 7SH 7UDLW VWGLVBDJJUHJDWH! ‡ 7R HQDEOH VSHFLDO KDQGOLQJ LI QRW
  • 382. DJJUHJDWH #include type_traits template typename Coll, typename... T void insert(Coll coll, T... val) { if constexpr(!std::is_aggregate_vtypename Coll::value_type) { coll.emplace_back(std::forwardT(val)...); LQYDOLG IRU DJJUHJDWHV } else { coll.emplace_back(typename Coll::value_type{std::forwardT(val)...}); } } class C { int i; double d; public: C(int x, double y) : i(x), d(y) { } }; std::vectorC vc; vc.emplace_back(42, 7.5); 2. insert(vc, 42, 7.5); 2. struct A { int i; double d; }; std::vectorA va; va.emplace_back(42, 7.5); (UURU insert(va, 42, 7.5); 2. ‹ E ,7FRPPXQLFDWLRQFRP RPELQLQJ 7SH 7UDLWV VLQFH std::conjunction std::disjunction std::negation ‡ DOORZ WR FRPELQH WSH WUDLW GHILQLWLRQV VLPLODU WR || ! ‡ conjunction DQG disjunction VKRUW FLUFXLW ± HQG HYDOXDWLRQ DV VRRQ DV RXWFRPH LV FOHDU templatetypename T struct IsNoPtrT : std::negationstd::disjunctionstd::is_null_pointerT, std::is_member_pointerT, std::is_pointerT { }; std::cout isNoPtrTvoid*::value 'n'; IDOVH std::cout isNoPtrTstd::string::value 'n'; WUXH auto np = nullptr; std::cout isNoPtrTdecltype(np)::value 'n'; IDOVH Nico Josuttis C++17 @CodeHard 98
  • 383. ‹ E ,7FRPPXQLFDWLRQFRP RPELQLQJ 7SH 7UDLWV VLQFH ‡ std::conjunction DQG std::disjunction ± VKRUW FLUFXLW struct X { X(int); }; struct Y; LQFRPSOHWH WSH XQGHILQHG EHKDYLRU EHFDXVH LV LQFRPSOHWH LVBFRQVWUXFWLEOH! PLJKW QRW FRPSLOH static_assert(std::is_constructibleX,int{} || std::is_constructibleY,int{}, can't init X or Y from int); 2. ZLOO FRPSLOH DQG KDV GHILQHG EHKDYLRU static_assert(std::disjunctionstd::is_constructibleX, int, std::is_constructibleY, int{}, can't init X or Y from int); 7KDQNV WR +RZDUG +LQQDQW IRU SRLQWLQJ WKDW RXW ‹ E ,7FRPPXQLFDWLRQFRP VWGLQYRNH!
  • 384. ‡ 8WLOLW IRU JHQHULF FRGH WR FDOO FDOODEOHV ± IXQFWLRQV IXQFWLRQ SRLQWHUV ± IXQFWLRQ REMHFWV ODPEGDV ± PHPEHU IXQFWLRQ IRU REMHFWV SDVVHG DV DGGLWLRQDO DUJXPHQW template typename Iter, typename Callable, typename... Args void foreach (Iter act, Iter end, Callable op, Args... args) { for ( ; act != end; ++act) { DV ORQJ DV QRW UHDFKHG WKH HQG FDOO std::invoke(std::forwardCallable(op), FDOODEOH std::forwardArgs(args)..., DGGLWLRQDO DUJV *act); FXUUHQW HOHPHQW } } std::vectorint primes = { 2, 3, 5, 7, 11, 13, 17, 19 }; foreach(primes.begin(), primes.end(), HOHPHQWV XVHG DV QG DUJ [] (std::string const prefix, int i) { ODPEGD WR FDOO std::cout prefix i 'n'; }, - value: ); VW DUJ IRU ODPEGD Nico Josuttis C++17 @CodeHard 99
  • 386. IRU 0HPEHU )XQFWLRQV #include functional #include iostream #include vector template typename Iter, typename Callable, typename... Args void foreach (Iter act, Iter end, Callable op, Args... args) { for ( ; act != end; ++act) { DV ORQJ DV QRW UHDFKHG WKH HQG FDOO std::invoke(std::forwardCallable(op), SDVVHG FDOODEOH IRU std::forwardArgs(args)..., DQ DGGLWLRQDO DUJXPHQWV *act); DQG WKH FXUUHQW HOHPHQW } } class MyClass { public: void memfunc(int i) const { std::cout MyClass::memfunc() called for: i 'n'; } }; int main() { std::vectorint primes = { 2, 3, 5, 7, 11, 13, 17, 19 }; MyClass obj; foreach(primes.begin(), primes.end(), HOHPHQWV XVHG DV DUJV MyClass::memfunc, PHPEHU IXQFWLRQ WR FDOO obj); REMHFW WR FDOO memfunc() IRU } ‹ E ,7FRPPXQLFDWLRQFRP VWGLQYRNH!
  • 387. ZLWK 3HUIHFW )RUZDUGLQJ 5HWXUQ 9DOXHV #include utility IRU VWGLQYRNH
  • 388. #include functional IRU VWGIRUZDUG
  • 389. #include type_traits IRU VWGLVBVDPH! DQG VWGLQYRNHBUHVXOW! templatetypename Callable, typename... Args decltype(auto) call(Callable op, Args... args) { if constexpr(std::is_same_vstd::invoke_result_tCallable, Args..., void) { UHWXUQ WSH LV YRLG std::invoke(std::forwardCallable(op), std::forwardArgs(args)...); return; } else { UHWXUQ WSH LV QRW YRLG decltype(auto) ret{std::invoke(std::forwardCallable(op), std::forwardArgs(args)...)}; return ret; } } LQYDOLG IRU void EHFDXVH LW LV DQ LQFRPSOHWH WSH
  • 391. ‹ E ,7FRPPXQLFDWLRQFRP LVBLQYRFDEOH! DQG LQYRNHBUHVXOW! 7SH 7UDLWV ‡ ILQG RXW ZKHWKHU D FDOODEOH FDQ EH FDOOHG IRU DQ REMHFW DQG ZKLFK WSH LW UHWXUQV ± LVBLQYRFDEOHT, Args ± LVBLQYRFDEOHBURET_T, T, Args ‡ LHOGV ZKHWKHU RX FDQ XVH T DV FDOODEOH IRU Args... UHWXUQLQJ D YDOXH FRQYHUWLEOH WR WSH RET_T
  • 392. ± LVBQRWKURZBLQYRFDEOHT, Args ± LVBQRWKURZBLQYRFDEOHBURET_T, T, Args ‡ VDPH ZLWK WKH JXDUDQWHH WKDW QR H[FHSWLRQ LV WKURZQ ± LQYRNHBUHVXOWT, Args ‡ LHOGV WKH UHWXUQ WSH ZKHQ XVLQJ T DV FDOODEOH IRU Args... ‡ WSH LV QRW GHILQHG LI QR FDOO LV SRVVLEOH ‡ 5HSODFH UHVXOWBRI! VLQFH
  • 393. DQG LVBFDOODEOH! ILUVW SURSRVHG IRU
  • 394. ± %HWWHU QDPHV PRGHUQ GHFODUDWLRQ WKH GHFD QRZ EHIRUH DQ FKHFN DUJXPHQW WSHV FDQ EH DEVWUDFW FODVV DQG IXQFWLRQ RU DUUD WSHV FDQ EH XVHG DV UHWXUQ WSH ‹ E ,7FRPPXQLFDWLRQFRP 8VLQJ LQYRNHBUHVXOW! DQG LVBLQYRFDEOH! struct C { bool operator() (int) const { return true; } }; struct Abstract { virtual ~Abstract() = 0; void operator() () const { } }; typename std::result_ofC(int)::type LHOGV ERRO typename std::invoke_resultC,int::type LHOGV ERRO typename std::result_ofAbstract()::type (5525 $EVWUDFW
  • 395. LV LOOIRUPHG typename std::invoke_resultAbstract::type 2. LHOGV YRLG std::is_invocableC,int::value WUXH std::is_invocableAbstract::value WUXH std::is_invocableint*::value IDOVH std::is_invocableint(*)()::value WUXH std::is_invocable_rbool,C,int::value WUXH std::is_invocable_rint,C,long::value WUXH std::is_invocable_rvoid,C,int::value WUXH std::is_invocable_rchar*,C,int::value IDOVH Nico Josuttis C++17 @CodeHard 101
  • 396. ‹ E ,7FRPPXQLFDWLRQFRP 2WKHU ,PSURYHPHQWV IRU 7HPSODWHV ‡ 'HILQLQJ VWGYRLGBW ± PDS DQ JLYHQ VHTXHQFH RI WSHV WR D VLQJOH WSH void ± 6LPSO templatetypename... using void_t = void; #include utility IRU GHFOYDO! #include type_traits IRU WUXHBWSH IDOVHBWSH DQG YRLGBW SULPDU WHPSODWH templatetypename, typename = std::void_t struct HasVariousT : std::false_type { }; SDUWLDO VSHFLDOL]DWLRQ PD EH 6),1$(¶G DZD
  • 397. templatetypename T struct HasVariousTT, std::void_tdecltype(std::declvalT().begin()), typename T::difference_type, typename T::iterator : std::true_type { }; ‹ E ,7FRPPXQLFDWLRQFRP 2WKHU ,PSURYHPHQWV IRU 7HPSODWHV ‡ 6SHFLDO VWGERROBFRQVWDQW! WSH IRU WSHBWUDLWV WKDW LHOG true RU false ± GRHV EHWWHU VXSSRUW LPSOLFLW FRQYHUVLRQV namespace std { templatebool B using bool_constant = integral_constantbool, B; using true_type = bool_constanttrue; using false_type = bool_constantfalse; } templatetypename T struct IsLargerThanInt : std::bool_constant(sizeof(T)sizeof(int)) { } if constexpr(IsLargerThanIntT::value) { } Nico Josuttis C++17 @CodeHard 102
  • 398. ‹ E ,7FRPPXQLFDWLRQFRP std::uncaught_exceptions() int std::uncaught_exceptions() ‡ RUUHFW LQWHUIDFH WR GHWHFW UHOHYDQW VWDFN XQZLQGLQJ ‡ 5HSODFHV bool std::uncaught_exception() ± 'LG QRW ZRUN LI REMHFW ZDV WHPSRUDULO FUHDWHG GXULQJ VWDFN XQZLQGLQJ class C { private: int initialUncaught = std::uncaught_exceptions(); public: ~C() { if (initialUncaught == std::uncaught_exceptions()) { commit(); GHVWUXFWLRQ QRW FDXVHG E VWDFN XQZLQGLQJ } else { rollback(); GHVWUXFWLRQ FDXVHG E VWDFN XQZLQGLQJ } } }; ‹ E ,7FRPPXQLFDWLRQFRP 8VLQJ std::uncaught_exceptions() C x(x); D d(d); throw oops; C::C() for x: initialUncaught: 0 D::D() for d --------------------- throw D::~D() for d C::C() for y: initialUncaught: 1 C::C() for z: initialUncaught: 1 --------------------- throw C::~C() for z: 1 = 2 uncaught = rollback() C::~C() for y: 1 = 1 uncaught = commit() C::~C() for x: 0 = 1 uncaught = rollback() class C { private: int initialUncaught = std::uncaught_exceptions(); public: ~C() { if (initialUncaught == std::uncaught_exceptions()) { commit(); GHVWUXFWLRQ QRW FDXVHG E VWDFN XQZLQGLQJ } else { rollback(); GHVWUXFWLRQ FDXVHG E VWDFN XQZLQGLQJ } } }; class D { public: ~D() { cleanup(); } }; void cleanup() { C y(y); try { C z(z); throw oops; } catch (...) { } } Nico Josuttis C++17 @CodeHard 103
  • 399. ‹ E ,7FRPPXQLFDWLRQFRP )L[ QRH[FHSW 'HFODUDWLRQV RI VRPH RQWDLQHUV ‡ ,Q 5DSSHUVZLO ZH GLVFXVVHG WKLV WRSLF EDVHG RQ SDSHU 1 LQ /(:* DQG FDPH WR WKH IROORZLQJ FRQFOXGLQJ YRWH ± )RU YHFWRUV ZH ZDQW WR KDYH ‡ QRH[FHSW GHIDXOW FRQVWUXFWRU ‡ QRH[FHSW PRYH FRQVWUXFWRU ‡ FRQGLWLRQDO QRH[FHSW PRYH DVVLJQPHQW ‡ FRQGLWLRQDO QRH[FHSW VZDS ± )RU VWULQJV ZH ZDQW WR KDYH ‡ QRH[FHSW GHIDXOW FRQVWUXFWRU ‡ QRH[FHSW PRYH FRQVWUXFWRU ‡ FRQGLWLRQDO QRH[FHSW PRYH DVVLJQPHQW ‡ FRQGLWLRQDO QRH[FHSW VZDS ± )RU DOO RWKHU FRQWDLQHUV ZH ZDQW WR KDYH ‡ FRQGLWLRQDO QRH[FHSW PRYH DVVLJQPHQW ‡ FRQGLWLRQDO QRH[FHSW VZDS ‡ QR UHTXLUHG QRH[FHSW IRU PRYH FRQVWUXFWRU %HVW SHUIRUPDQFH JXDUDQWHHG LQ DOO PRGHV IRU RXU DOPRVW IXQGDPHQWDO GDWD WSHV ‡ YHFWRU ‡ VWULQJ ‹ E ,7FRPPXQLFDWLRQFRP )LQDO KDQJHV LQ /LEUDU :RUNLQJ *URXS ,Q 8UEDQD ZH DJUHHG LQ /:* RQ 1 H[WUDFW RI SDJHV
  • 400. ‡ ,Q † EDVLFVWULQJ@ LQ FODVV VWGEDVLFBVWULQJ 0RGLI DGG
  • 401. basic_string() noexcept : basic_string(Allocator()) { } explicit basic_string(const Allocator a) noexcept; 8QOLNH OLEUDU LVVXH SURSRVHG NHHS basic_string(basic_string str) noexcept; 0RGLI DGG
  • 402. basic_string operator=(basic_string str) noexcept(allocator_traitsAllocator ::propagate_on_container_move_assignment::value || allocator_traitsAllocator::is_always_equal::value); VLPLODU FKDQJHV IRU VZDS Nico Josuttis C++17 @CodeHard 104
  • 405. LV %URNHQ 0RGHUQ ‹ E ,7FRPPXQLFDWLRQFRP 7KH 3UREOHP 2EMHFW OLIHWLPH EDVLFOLIH@ ,I DIWHU WKH OLIHWLPH RI DQ REMHFW KDV HQGHG DQG EHIRUH WKH VWRUDJH ZKLFK WKH REMHFW RFFXSLHG LV UHXVHG RU UHOHDVHG D QHZ REMHFW LV FUHDWHG DW WKH VWRUDJH ORFDWLRQ ZKLFK WKH RULJLQDO REMHFW RFFXSLHG D SRLQWHU WKDW SRLQWHG WR WKH RULJLQDO REMHFW D UHIHUHQFH WKDW UHIHUUHG WR WKH RULJLQDO REMHFW RU WKH QDPH RI WKH RULJLQDO REMHFW ZLOO DXWRPDWLFDOO UHIHU WR WKH QHZ REMHFW DQG RQFH WKH OLIHWLPH RI WKH QHZ REMHFW KDV VWDUWHG FDQ EH XVHG WR PDQLSXODWH WKH QHZ REMHFW LI
  • 406. ² WKH VWRUDJH IRU WKH QHZ REMHFW H[DFWO RYHUODV WKH VWRUDJH ORFDWLRQ ZKLFK WKH RULJLQDO REMHFW RFFXSLHG DQG
  • 407. ² WKH QHZ REMHFW LV RI WKH VDPH WSH DV WKH RULJLQDO REMHFW LJQRULQJ WKH WRSOHYHO FYTXDOLILHUV
  • 408. DQG
  • 409. ² WKH WSH RI WKH RULJLQDO REMHFW LV QRW FRQVWTXDOLILHG DQG LI D FODVV WSH GRHV QRW FRQWDLQ DQ QRQVWDWLF GDWD PHPEHU ZKRVH WSH LV FRQVW TXDOLILHG RU D UHIHUHQFH WSH DQG
  • 410. ² WKH RULJLQDO REMHFW ZDV D PRVW GHULYHG REMHFW
  • 411. RI WSH 7 DQG WKH QHZ REMHFW LV D PRVW GHULYHG REMHFW RI WSH 7 WKDW LV WKH DUH QRW EDVH FODVV VXEREMHFWV
  • 413. ‹ E ,7FRPPXQLFDWLRQFRP 7KH 3UREOHP 2EMHFW OLIHWLPH EDVLFOLIH@ ,I DIWHU WKH OLIHWLPH RI DQ REMHFW KDV HQGHG DQG EHIRUH WKH VWRUDJH ZKLFK WKH REMHFW RFFXSLHG LV UHXVHG RU UHOHDVHG D QHZ REMHFW LV FUHDWHG DW WKH VWRUDJH ORFDWLRQ ZKLFK WKH RULJLQDO REMHFW RFFXSLHG D SRLQWHU WKDW SRLQWHG WR WKH RULJLQDO REMHFW D UHIHUHQFH WKDW UHIHUUHG WR WKH RULJLQDO REMHFW RU WKH QDPH RI WKH RULJLQDO REMHFW ZLOO DXWRPDWLFDOO UHIHU WR WKH QHZ REMHFW DQG RQFH WKH OLIHWLPH RI WKH QHZ REMHFW KDV VWDUWHG FDQ EH XVHG WR PDQLSXODWH WKH QHZ REMHFW LI
  • 414. ² WKH VWRUDJH IRU WKH QHZ REMHFW H[DFWO RYHUODV WKH VWRUDJH ORFDWLRQ ZKLFK WKH RULJLQDO REMHFW RFFXSLHG DQG
  • 415. ² WKH QHZ REMHFW LV RI WKH VDPH WSH DV WKH RULJLQDO REMHFW LJQRULQJ WKH WRSOHYHO FYTXDOLILHUV
  • 416. DQG
  • 417. ² WKH WSH RI WKH RULJLQDO REMHFW LV QRW FRQVWTXDOLILHG DQG LI D FODVV WSH GRHV QRW FRQWDLQ DQ QRQVWDWLF GDWD PHPEHU ZKRVH WSH LV FRQVW TXDOLILHG RU D UHIHUHQFH WSH DQG
  • 418. ² WKH RULJLQDO REMHFW ZDV D PRVW GHULYHG REMHFW
  • 419. RI WSH 7 DQG WKH QHZ REMHFW LV D PRVW GHULYHG REMHFW RI WSH 7 WKDW LV WKH DUH QRW EDVH FODVV VXEREMHFWV
  • 420. ,Q RWKHU ZRUGV 7KH QDPH RI DQ REMHFW WKDW GLHV DQG JHWV UHSODFHG E D QHZ REMHFW FDQ EH UHXVHG IRU WKH QHZ REMHFW XQOHVV WKH REMHFW LV FRQVW RU GRHV FRQWDLQ DQ QRQVWDWLF FRQVWUHI PHPEHUV ‹ E ,7FRPPXQLFDWLRQFRP 7KH RQVHTXHQFH #include new struct C { int i; const int c; }; C* p = new C{0,0}; int a = p-i; 2. D LV new(p) C{42,42}; UHTXHVW WR SODFH QHZ LQLWLDOL]HG E WR S FRPSLOHUV PD DVVXPH WKDW YDOXH GLG QRW FKDQJH Nico Josuttis C++17 @CodeHard 106
  • 421. ‹ E ,7FRPPXQLFDWLRQFRP 7KH RQVHTXHQFH #include new struct C { int i; const int c; }; C* p = new C{0,0}; int a = p-i; 2. D LV new(p) C{42,42}; UHTXHVW WR SODFH QHZ LQLWLDOL]HG E WR S FRPSLOHUV PD DVVXPH WKDW YDOXH GLG QRW FKDQJH int b = p-c; XQGHILQHG EHKDYLRU PLJKW ZRUN
  • 422. int c = p-i; XQGHILQHG EHKDYLRU PLJKW ZRUN
  • 423. ‹ E ,7FRPPXQLFDWLRQFRP 7KH RQVHTXHQFH #include new struct C { int i; const int c; }; C* p = new C{0,0}; int a = p-i; 2. D LV new(p) C{42,42}; UHTXHVW WR SODFH QHZ LQLWLDOL]HG E WR S FRPSLOHUV PD DVVXPH WKDW YDOXH GLG QRW FKDQJH int b = p-c; XQGHILQHG EHKDYLRU PLJKW ZRUN
  • 424. int c = p-i; XQGHILQHG EHKDYLRU PLJKW ZRUN
  • 425. :RXOG QRW EH D SUREOHP ZLWK p = new(p) C{42,42}; Nico Josuttis C++17 @CodeHard 107
  • 427. #include new struct C { int i; const int c; }; C* p = new C{0,0}; int a = p-i; 2. D LV new(p) C{42,42}; UHTXHVW WR SODFH QHZ LQLWLDOL]HG E WR S FRPSLOHUV PD DVVXPH WKDW YDOXH GLG QRW FKDQJH int b = p-c; XQGHILQHG EHKDYLRU PLJKW ZRUN
  • 428. int c = p-i; XQGHILQHG EHKDYLRU PLJKW ZRUN
  • 429. int d = std::launder(p)-c; 2. G LV ODXQGHUS
  • 431. int e = std::launder(p)-i; 2. H LV ODXQGHUS
  • 433. int f = p-c; VWLOO XQGHILQHG EHKDYLRU int g = p-i; VWLOO XQGHILQHG EHKDYLRU auto q = std::launder(p); int h = q-c; 2. K LV :RXOG QRW EH D SUREOHP ZLWK p = new(p) C{42,42}; ‹ E ,7FRPPXQLFDWLRQFRP SXVKBEDFN
  • 434. ZLWK (OHPHQWV ZLWK RQVWDQW 0HPEHUV class C { private: int i; const int c; FRQVWDQW PHPEHU public: C(int x, int y) : i(x), c(y) { } friend std::ostream operator (std::ostream os, const C c) { return os c.i c.c; } }; std::vectorC v; v.push_back(C{0,0}); LQVHUW ILUVW HOHPHQW v.clear(); v.push_back(C{42,0}); LQVHUW D QHZ ILUVW HOHPHQW std::cout v[0]; VKRXOG RXWSXW Nico Josuttis C++17 @CodeHard 108
  • 435. ‹ E ,7FRPPXQLFDWLRQFRP template typename T, typename A = std::allocatorT class vector { public: using ATR = typedef typename std::allocator_traitsA; using pointer = typename ATR::pointer; private: A _alloc; FXUUHQW DOORFDWRU pointer _elems; DUUD RI HOHPHQWV size_t _size; QXPEHU RI HOHPHQWV size_t _capa; FDSDFLW public: void push_back(const T t) { if (_capa == _size) { LI QHFHVVDU UHVHUYH PRUH PHPRU reserve((_capa+1)*2); } ATR::construct(_alloc, _elems+_size, t); FRQVWUXFW WKH QHZ HOHPHQW ++_size; } T operator[] (size_t i) { return _elems[i]; } }; ,PSOHPHQWLQJ D RQWDLQHU 8VLQJ DQ $OORFDWRU 0LVVLQJ ‡ PRYH VHPDQWLFV ‡ H[FHSWLRQ KDQGOLQJ ‹ E ,7FRPPXQLFDWLRQFRP :KDW GHIDXOW
  • 436. $OORFDWRU7UDLWV GR namespace std { template class Alloc struct allocator_traits { static pointer allocate(Alloc a, size_type n); static pointer allocate(Alloc a, size_type n, const_void_pointer hint); static void deallocate(Alloc a, pointer p, size_type n); template class T, class... Args static void construct(Alloc a, T* p, Args... args) { GLUHFWO RU YLD DFRQVWUXFW
  • 437. FDOOV ::new(static_castvoid*(p)) T(std::forwardArgs(args)...); } template class T static void destroy(Alloc a, T* p); }; Nico Josuttis C++17 @CodeHard 109
  • 438. ‹ E ,7FRPPXQLFDWLRQFRP template typename T, typename A = std::allocatorT class vector { public: using ATR = typedef typename std::allocator_traitsA; using pointer = typename ATR::pointer; private: A _alloc; FXUUHQW DOORFDWRU pointer _elems; DUUD RI HOHPHQWV size_t _size; QXPEHU RI HOHPHQWV size_t _capa; FDSDFLW public: void push_back(const T t) { if (_capa == _size) { reserve((_capa+1)*2); } ATR::construct(_alloc, _elems+_size, t); ++_size; } T operator[] (size_t i) { return _elems[i]; 8% IRU UHSODFHG HOHPHQWV ZLWK FRQVWDQW PHPEHUV } }; ,PSOHPHQWLQJ D RQWDLQHU 8VLQJ DQ $OORFDWRU ‹ E ,7FRPPXQLFDWLRQFRP template typename T, typename A = std::allocatorT class vector { public: using ATR = typedef typename std::allocator_traitsA; using pointer = typename ATR::pointer; private: A _alloc; FXUUHQW DOORFDWRU pointer _elems; DUUD RI HOHPHQWV size_t _size; QXPEHU RI HOHPHQWV size_t _capa; FDSDFLW public: void push_back(const T t) { if (_capa == _size) { reserve((_capa+1)*2); } ATR::construct(_alloc, _elems+_size, t); ++_size; } T operator[] (size_t i) { return std::launder(_elems)[i]; VWLOO 8% IRU UHSODFHG HOHPV ZLWK FRQVW PHPEHUV } }; VWGODXQGHU
  • 439. GRHV QRW KHOS KHUH VWGODXQGHUS
  • 440. UHTXLUHV S WR EH D SRLQWHU $75SRLQWHU PLJKW QRW EH D UDZ SRLQWHU Nico Josuttis C++17 @CodeHard 110
  • 441. ‹ E ,7FRPPXQLFDWLRQFRP template typename T, typename A = std::allocatorT class vector { public: typedef typename std::allocator_traitsA ATR; typedef typename ATR::pointer pointer; private: A _alloc; FXUUHQW DOORFDWRU pointer _elems; DUUD RI HOHPHQWV size_t _size; QXPEHU RI HOHPHQWV size_t _capa; FDSDFLW public: void push_back(const T t) { if (_capa == _size) { reserve((_capa+1)*2); } ATR::construct(_alloc, _elems+_size, t); ++_size; } T operator[] (size_t i) { return std::launder(this)-_elems[i]; VWLOO 8% IRU UHSO HOHPV ZLWK FRQVW PHP } }; VWGODXQGHU
  • 442. GRHV QRW KHOS KHUH VWGODXQGHUS
  • 443. LV D QRRS XQOHVV S SRLQWV WR DQ REMHFW ZKRVH OLIHWLPH KDV HQGHG DQG ZKHUH D QHZ REMHFW KDV EHHQ FUHDWHG LQ WKH VDPH VWRUDJH ‹ E ,7FRPPXQLFDWLRQFRP SXVKBEDFN
  • 444. UHVXOWV LQWR 8QGHILQHG %HKDYLRU class C { private: int i; const int c; FRQVWDQW PHPEHU public: C(int x, int y) : i(x), c(y) { } friend std::ostream operator (std::ostream os, const C c) { return os c.i c.c; } }; std::vectorC v; v.push_back(C{0,0}); LQVHUW ILUVW HOHPHQW v.clear(); v.push_back(C{42,0}); XQGHILQHG EHKDYLRU GXH WR FRQVW PHPEHU
  • 445. std::cout v[0]; PLJKW RXWSXW RU Nico Josuttis C++17 @CodeHard 111
  • 446. ‹ E ,7FRPPXQLFDWLRQFRP $OVR D 3UREOHP IRU VWGRSWLRQDO! DQG VWGYDULDQW! template typename T class coreoptional { private: T payload; public: coreoptional(const T t) : payload(t) { } templatetypename... Args void emplace(Args... args) { payload.~T(); ::new(payload) T(std::forwardArgs(args)...); } const T operator*() const { return payload; } }; ‹ E ,7FRPPXQLFDWLRQFRP VWGODXQGHU
  • 447. 6XPPDU ‡ IRU VWGYHFWRU! DQG VWGGHTXH! ± SXVKBEDFN
  • 449. LQVHUW
  • 450. LV EURNHQ LI HOHPHQWV KDYH FRQVW PHPEHUV ± 1RWH 3UREOHP VLQFH ‡ 1HHGV PRYH VHPDQWLFV WR PRYH WKHP LQ ‡ VWGRSWLRQDO! DQG VWGYDULDQW! ± QHHG DGGLWLRQDO SRLQWHU PHPEHUV WR UHIHU WR WKHLU RZQ PHPEHU WR ZRUN ZLWK YDOXHV KDYLQJ FRQVW PHPEHUV EUHDNV ELQDU FRPSDWLELOLW Nico Josuttis C++17 @CodeHard 112
  • 451. ‹ E ,7FRPPXQLFDWLRQFRP 2WKHU $VSHFWV RI ‹ E ,7FRPPXQLFDWLRQFRP %DVHG RQ ‡ UHIHUV WR LQVWHDG RI ± 'UDIW ‡ ZZZRSHQVWGRUJMWFVFZJZZZGRFVQSGI ± KDQJHV ‡ KWWSVHQZLNLSHGLDRUJZLNLBBVWDQGDUGBUHYLVLRQ
  • 452. ± IXQFWLRQV IRU VDIHU PRUH VHFXUH SURJUDPPLQJ´ ZLWK VXIIL[ _s DQG DGGLWLRQDO VL]H DUJXPHQW HJ strcpy_s() sprintf_s()
  • 453. ‡ may EH DYDLODEOH LQ WKH KHDGHUV ‡ EXW QRW GHILQHG LQ QDPHVSDFH std Nico Josuttis C++17 @CodeHard 113
  • 454. ‹ E ,7FRPPXQLFDWLRQFRP 'HSUHFDWHG 5HPRYHG LQ RUH ‡ 5HPRYHG ± 7ULJUDSKV ± 2SHUDWRU ++ IRU bool ± NHZRUG register EXW NHHS UHVHUYHG IRU IXWXUH XVH
  • 455. ± 'QDPLF H[FHSWLRQ VSHFLILFDWLRQV ZLWK 7SHV void foo() throw(bad_alloc); LQYDOLG VLQFH void foo() throw(); VWLOO YDOLG EXW PLJKW QRW XQZLQG VWDFN ± auto_ptr unary_function binary_function ptr_fun mem_fun mem_fun_ref bind1st bind2nd random_shuffle() ± std::function QR ORQJHU KDV DOORFDWRU VXSSRUW ‡ 'HSUHFDWHG LQ /LEUDU ± codecvt wstring_convert wbuffer_convert ZDV QHZ LQ
  • 456. ± result_of WUDLW XVH invoke_result LQVWHDG
  • 457. ‡ 7HPSRUDULO GLVFRXUDJHG ± memory_order_consume ‹ E ,7FRPPXQLFDWLRQFRP RQFOXVLRQ 0RGHUQ Nico Josuttis C++17 @CodeHard 114
  • 458. ‹ E ,7FRPPXQLFDWLRQFRP +LJKOLJKWV ‡ 6WUXFWXUHG %LQGLQJV ‡ )ROG H[SUHVVLRQV ‡ ,QOLQH 9DULDEOHV ‡ RPSLOH7LPH LI ‡ ODVV 7HPSODWH $UJXPHQW 'HGXFWLRQ ‡ VWGRSWLRQDO ‡ VWGYDULDQW ‡ VWGDQ ‡ VWGEWH ‡ VWGVWULQJBYLHZ EXW FRQVLGHUHG KDUPIXO
  • 459. ‡ )LOHVVWHP /LEUDU ‡ 3DUDOOHO 67/ $OJRULWKPV ‡ 6HYHUDO 6PDOO +HOSHUV ‡ PRUH DQG PRUH FRQVWH[SU DOO RYHU WKH SODFH ‹ E ,7FRPPXQLFDWLRQFRP 8QLIRUP ,QLWLDOL]DWLRQ QRZ $OPRVW 'RQH int i2 = 0; FRS LQLWLDOL]DWLRQ IURP
  • 460. int i3(0); GLUHFW LQLWLDOL]DWLRQ VLQFH
  • 461. int i4{0}; GLUHFW LQLWLDOL]DWLRQ IURP 0RGHUQ VLQFH
  • 462. int i5 = {0}; FRS LQLWLDOL]DWLRQ IURP 0RGHUQ unsigned long l1{-17}; (5525 JRRG
  • 463. QDUURZLQJ GHWHFWHG unsigned long l2{4.8}; (5525 JRRG
  • 464. QDUURZLQJ GHWHFWHG auto x{42}; [ LV LQW QRZ ZDV VWGLQLWLDOL]HUBOLVWLQW! EHIRUH
  • 465. auto y{0,8,15}; (5525 QRZ JRRG ZDV VWGLQLWLDOL]HUBOLVWLQW! EHIRUH
  • 466. auto z = {0,8,15}; VWLOO VWGLQLWLDOL]HUBOLVWLQW! enum class MyIntegralEnum; MyIntegralEnum e{17}; 2. VLQFH DOO RWKHU LQLWLDOL]DWLRQV DUH VWLOO LOOIRUPHG
  • 467. struct CData { int amount; double value; }; struct DData : CData { std::string name; void print() const; }; DData a{{42, 6.7}, book}; LQLWLDOL]H DOO HOHPHQWV AnyType t{}; YDOXH LQLWLDOL]DWLRQ GHIDXOW YDOXH RU IDOVHQXOOSWU IRU )'7 V
  • 468. int i6{}; LQLWLDOL]HG ZLWK VLQFH
  • 469. DData b{}; VDPH DV {0,0.0},} MyIntegralEnum f{}; VWLOO 2. ± 8VH XQLIRUP GLUHFW LQLWLDOL]DWLRQ ‡ XQLIRUP ZLWK {«} ‡ GLUHFW ZLWKRXW = ± 6WLOO std::atomic QHHGV D IL[ ‡ VHH 35 ± 6WLOO VRPH IODZV ZLWK DJJUHJDWHV ‡ AggrT x{}; LV SRVVLEOH ZLWK GHOHWHG FRQVWUXFWRU Nico Josuttis C++17 @CodeHard 115
  • 470. ‹ E ,7FRPPXQLFDWLRQFRP :KDW ZDV not YRWHG LQWR ‡ 0RGXOHV ‡ RQFHSWV ‡ 5DQJHV ‡ 5HIOHFWLRQ ‡ R5RXWLQHV ‡ 2YHUORDGLQJ operator.() ‡ 'HIDXOW FRPSDULVRQ RSHUDWRUV ‡ 8QLIRUP DOO 6QWD[ ‡ 1HWZRUNLQJ OLEUDU ± %RRVW$VLR ZLOO EH WKH QH[W UHYROXWLRQ ‹ E ,7FRPPXQLFDWLRQFRP 2YHUYLHZV ([WUDFW
  • 471. ‡ KDQJHV EHWZHHQ DQG ',6 ± KWWSVLVRFSSRUJILOHVSDSHUVSUKWPO ± /LVW RI DOO SDSHUV ZLWK DOO IHDWXUHV ± E 7KRPDV .|SSH ‡ 'HVFULSWLRQV RI IHDWXUHV ± SUHVHQWHG PRVWO LQ 7RQ 7DEOHV ± KWWSVJLWKXEFRPWYDQHHUGFSSBLQB77V ± E 7RQ 9DQ (HUG ‡ 2YHUYLHZ 6OLGHV ± KWWSZZZFRGHSODFRPSXEOLFXSORDGHGSXEOLFFEGDIBFSRVWRXOXSGI ± E 0LFKDHO :RQJ ‡ 'UDIW $YDLODEOH ± 7KH RPSOHWH *XLGH ± VHH KWWSFSSVWGFRP ± E 1LFRODL 0 -RVXWWLV Nico Josuttis C++17 @CodeHard 116
  • 472. ‹ E ,7FRPPXQLFDWLRQFRP 6XPPDU ‡ LV D VLJQLILFDQW LPSURYHPHQW ± %LJ VWHS RXW RI PDQ VPDOO VWHSV ‡ RPSLOHU VXSSRUW ± JFFJ ± ODQJ ± 96[ ‡ 6RPH ERRNV DOUHDG FRYHU ± C++17 – The Complete Guide ‡ VHH KWWSFSSVWGFRP ± C++ Templates, 2nd ed. ‡ VHH KWWSWPSOERRNFRP ‡ :H DUH VWLOO ORRNLQJ IRUZDUG WR QLFR#MRVXWWLVGH Nico Josuttis C++17 @CodeHard 117