The devil is in the detail. This also applies to C++17. We get new cool features, but we also get new things to care for and remember. This talk discusses some of the cool features when they may lead to surprises.
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
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
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
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
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
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
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()