- the worst feature of modern c++: default behavior di… · the worst feature of modern c++:...

Post on 01-Oct-2020

2 Views

Category:

Documents

0 Downloads

Preview:

Click to see full reader

TRANSCRIPT

The worst feature of modern C++: default behavior

Marcin Grzebieluch

grzebieluch@me.com

21.11.2017

grzebiel 21.11.2017 1 / 77

The worst feature of modern C++: default behavior

Marcin Grzebieluch

grzebieluch@me.com

21.11.2017

grzebiel 21.11.2017 2 / 77

Questions

grzebiel 21.11.2017 3 / 77

Plan

1 auto

2 decltype

3 default args

4 rvalue reference

5 syntax

grzebiel 21.11.2017 4 / 77

1 auto

2 decltype

3 default args

4 rvalue reference

5 syntax

auto grzebiel 21.11.2017 5 / 77

first use of c++11 auto1 #include <cassert>2 int& referenceToInt();34 void modifyFoo()5 {6 auto x = referenceToInt();7 x = 5;8 }9

10 int main()11 {12 modifyFoo();13 assert(referenceToInt() == 5);14 return 0;15 }

auto grzebiel 21.11.2017 6 / 77

first use of c++11 auto1 #include <cassert>2 int& referenceToInt();34 void modifyFoo()5 {6 auto x = referenceToInt();7 x = 5;8 }9

10 int main()11 {12 modifyFoo();13 assert(referenceToInt() == 5);14 return 0;15 }

auto grzebiel 21.11.2017 6 / 77

first use of c++11 auto1 #include <cassert>2 int& referenceToInt();34 void modifyFoo()5 {6 auto x = referenceToInt();7 x = 5;8 }9

10 int main()11 {12 modifyFoo();13 assert(referenceToInt() == 5);14 return 0;15 }

auto grzebiel 21.11.2017 6 / 77

first use of c++11 auto1 #include <cassert>2 int& referenceToInt();34 void modifyFoo()5 {6 auto x = referenceToInt();7 x = 5;8 }9

10 int main()11 {12 modifyFoo();13 assert(referenceToInt() == 5);14 return 0;15 }

auto grzebiel 21.11.2017 6 / 77

first use of c++11 auto1 #include <cassert>2 int& referenceToInt();34 void modifyFoo()5 {6 auto x = referenceToInt();7 x = 5;8 }9

10 int main()11 {12 modifyFoo();13 assert(referenceToInt() == 5);14 return 0;15 }

auto grzebiel 21.11.2017 6 / 77

cpp11 standard:Once the type of a declarator-id has been determinedaccording to 8.3, the type of the declared variable using thedeclarator-id is determined from the type of itsinitializer using the rules for template argumentdeduction.

auto grzebiel 21.11.2017 7 / 77

cpp11 standard:If template parameter type P is a reference type, the typereferred to by P is used for type deduction.

auto grzebiel 21.11.2017 8 / 77

lets fix code1 #include <cassert>2 int& referenceToInt();34 void modifyFoo()5 {6 auto x = referenceToInt();7 x = 5;8 }9

10 int main()11 {12 modifyFoo();13 assert(referenceToInt() == 5);14 return 0;15 }

auto grzebiel 21.11.2017 9 / 77

lets fix code1 #include <cassert>2 int& referenceToInt();34 void modifyFoo()5 {6 auto x = referenceToInt();7 x = 5;8 }9

10 int main()11 {12 modifyFoo();13 assert(referenceToInt() == 5);14 return 0;15 }

auto grzebiel 21.11.2017 9 / 77

lets fix code1 #include <cassert>2 int& referenceToInt();34 void modifyFoo()5 {6 auto& x = referenceToInt();7 x = 5;8 }9

10 int main()11 {12 modifyFoo();13 assert(referenceToInt() == 5);14 return 0;15 }

auto grzebiel 21.11.2017 9 / 77

what have I learned?

• before the usage, always read at leset 10 setencesabout the future

• auto does not deduce consts, references and volatiles

auto grzebiel 21.11.2017 10 / 77

what have I learned?

• before the usage, always read at leset 10 setencesabout the future

• auto does not deduce consts, references and volatiles

auto grzebiel 21.11.2017 10 / 77

what have I learned?

• before the usage, always read at leset 10 setencesabout the future

• auto does not deduce consts, references and volatiles

auto grzebiel 21.11.2017 10 / 77

it was not only me!

auto grzebiel 21.11.2017 11 / 77

it was not only me!

auto grzebiel 21.11.2017 11 / 77

Lets imagine that we are in alternative universe in which:

1 int& foo();23 auto a = foo();4 // type of a would be int&

auto grzebiel 21.11.2017 12 / 77

a magical place

https://en.wikipedia.org/wiki/File:Bliss.pngauto grzebiel 21.11.2017 13 / 77

now it works1 #include <cassert>2 int& referenceToInt();34 void modifyFoo()5 {6 auto x = referenceToInt();7 x = 5;8 }9

10 int main()11 {12 modifyFoo();13 assert(referenceToInt() == 5);14 return 0;15 }

auto grzebiel 21.11.2017 14 / 77

in this alternative world

1 int a = 5;2 int* b = &a;3 auto c = *b;4 ++c;5 assert(c != a);

auto grzebiel 21.11.2017 15 / 77

in this alternative world

1 int a = 5;2 int* b = &a;3 auto c = *b;4 ++c;5 assert(c != a);

auto grzebiel 21.11.2017 15 / 77

in this alternative world

1 int a = 5;2 int* b = &a;3 auto c = *b;4 ++c;5 assert(c != a);

auto grzebiel 21.11.2017 15 / 77

in this alternative world

1 int a = 5;2 int* b = &a;3 auto c = *b;4 ++c;5 assert(c != a);

auto grzebiel 21.11.2017 15 / 77

in this alternative world

1 int a = 5;2 int* b = &a;3 auto c = *b;4 ++c;5 assert(c != a);

auto grzebiel 21.11.2017 15 / 77

in this alternative world

1 int a = 5;2 int* b = &a;3 auto c = *b;4 ++c;5 assert(c != a);

auto grzebiel 21.11.2017 15 / 77

in this alternative world

1 auto a = 5;2 auto b = a;

type of variable bwould be int &

auto grzebiel 21.11.2017 16 / 77

in this alternative world

1 auto a = 5;2 auto b = a;

type of variable bwould be int &

auto grzebiel 21.11.2017 16 / 77

back to normal world

auto grzebiel 21.11.2017 17 / 77

auto means template type deduction

auto grzebiel 21.11.2017 18 / 77

1 auto foo() -> int;

auto grzebiel 21.11.2017 19 / 77

auto means template type deduction

except when it’s not

auto grzebiel 21.11.2017 20 / 77

auto means template type deductionexcept when it’s not

auto grzebiel 21.11.2017 20 / 77

1 template <typename T, typename U>

2 auto add(T t, U u) -> decltype(t + u);

auto grzebiel 21.11.2017 21 / 77

1 #include <utility>23 template<typename T, typename U>4 decltype(std::declval<T>() + std::declval<U>())5 add(T t, U u);

auto grzebiel 21.11.2017 22 / 77

1 template <typename T, typename U>

2 auto add(T t, U u) -> decltype(t + u);

auto grzebiel 21.11.2017 23 / 77

1 #include <memory>23 template <typename T>4 struct unique_ptr_wrapper5 {6 std::unique_ptr<T> uptr;7 //...8 auto operator*() -> decltype(*uptr)9 {

10 return *uptr;11 }12 //...13 };

auto grzebiel 21.11.2017 24 / 77

1 #include <memory>23 template <typename T>4 struct unique_ptr_wrapper5 {6 std::unique_ptr<T> uptr;7 //...8 auto operator*() -> decltype(*uptr)9 {

10 return *uptr;11 }12 //...13 };

auto grzebiel 21.11.2017 24 / 77

1 #include <memory>23 template <typename T>4 struct unique_ptr_wrapper5 {6 std::unique_ptr<T> uptr;7 //...8 auto operator*() -> decltype(*uptr)9 {

10 return *uptr;11 }12 //...13 };

auto grzebiel 21.11.2017 24 / 77

1 #include <memory>23 template <typename T>4 struct unique_ptr_wrapper5 {6 std::unique_ptr<T> uptr;7 //...8 auto operator*() -> decltype(*uptr)9 {

10 return *uptr;11 }12 //...13 };

auto grzebiel 21.11.2017 24 / 77

1 #include <memory>23 template <typename T>4 struct unique_ptr_wrapper5 {6 std::unique_ptr<T> uptr;7 //...8 auto operator*()9 {

10 return *uptr;11 }12 //...13 };

auto grzebiel 21.11.2017 25 / 77

1 #include <memory>23 template <typename T>4 struct unique_ptr_wrapper5 {6 std::unique_ptr<T> uptr;7 //...8 auto operator*()9 {

10 return *uptr;11 }12 //...13 };

auto grzebiel 21.11.2017 25 / 77

1 #include <memory>23 template <typename T>4 struct unique_ptr_wrapper5 {6 std::unique_ptr<T> uptr;7 //...8 auto& operator*()9 {

10 return *uptr;11 }12 //...13 };

auto grzebiel 21.11.2017 25 / 77

1 #include <memory>23 template <typename T>4 struct unique_ptr_wrapper5 {6 std::unique_ptr<T> uptr;7 //...8 decltype(auto) operator*()9 {

10 return *uptr;11 }12 //...13 };

auto grzebiel 21.11.2017 26 / 77

1 auto

2 decltype

3 default args

4 rvalue reference

5 syntax

decltype grzebiel 21.11.2017 27 / 77

quiz time!

what is a type of variable y?

decltype grzebiel 21.11.2017 28 / 77

quiz time!

1 int x;2 decltype(x) y;

int

decltype grzebiel 21.11.2017 29 / 77

quiz time!

1 int x;2 decltype(x) y;

int

decltype grzebiel 21.11.2017 29 / 77

quiz time!

1 int x;2 auto& z = x;3 decltype(z) y;

int &

decltype grzebiel 21.11.2017 30 / 77

quiz time!

1 int x;2 auto& z = x;3 decltype(z) y;

int &

decltype grzebiel 21.11.2017 30 / 77

quiz time!

1 int x;2 decltype(&x) y;

int *

decltype grzebiel 21.11.2017 31 / 77

quiz time!

1 int x;2 decltype(&x) y;

int *

decltype grzebiel 21.11.2017 31 / 77

quiz time!

1 int x;2 decltype(x + 3.2) y;

double

decltype grzebiel 21.11.2017 32 / 77

quiz time!

1 int x;2 decltype(x + 3.2) y;

double

decltype grzebiel 21.11.2017 32 / 77

quiz time!

1 struct S { int m; };23 S s{};4 decltype(s.m) y;

int

decltype grzebiel 21.11.2017 33 / 77

quiz time!

1 struct S { int m; };23 S s{};4 decltype(s.m) y;

int

decltype grzebiel 21.11.2017 33 / 77

quiz time!

1 int* x;2 decltype(*x) y;

int&

decltype grzebiel 21.11.2017 34 / 77

quiz time!

1 int* x;2 decltype(*x) y;

int&

decltype grzebiel 21.11.2017 34 / 77

quiz time!

1 int x;2 decltype((x)) y;

int&

decltype grzebiel 21.11.2017 35 / 77

quiz time!

1 int x;2 decltype((x)) y;

int&

decltype grzebiel 21.11.2017 35 / 77

quiz time!

1 struct S{int m;};23 const S* sptr;4 decltype((sptr->m)) y;

const int&

decltype grzebiel 21.11.2017 36 / 77

quiz time!

1 struct S{int m;};23 const S* sptr;4 decltype((sptr->m)) y;

const int&

decltype grzebiel 21.11.2017 36 / 77

quiz time!

1 auto string = "string literal";2 decltype(string) y;

const char*

decltype grzebiel 21.11.2017 37 / 77

quiz time!

1 auto string = "string literal";2 decltype(string) y;

const char*

decltype grzebiel 21.11.2017 37 / 77

quiz time!

1 decltype("string literal") y;

const char (&)[15]

decltype grzebiel 21.11.2017 38 / 77

quiz time!

1 decltype("string literal") y;

const char (&)[15]

decltype grzebiel 21.11.2017 38 / 77

decltype has two seperate usecases which yield differentresults:

• get type of entity

• get type of expression

decltype grzebiel 21.11.2017 39 / 77

decltype has two seperate usecases which yield differentresults:

• get type of entity

• get type of expression

decltype grzebiel 21.11.2017 39 / 77

decltype has two seperate usecases which yield differentresults:

• get type of entity

• get type of expression

decltype grzebiel 21.11.2017 39 / 77

1 int x;2 decltype(x); // an entity3 decltype(5); // expression4 decltype((x)); // expression

decltype grzebiel 21.11.2017 40 / 77

1 int x;2 decltype(x); // an entity3 decltype(5); // expression4 decltype((x)); // expression

decltype grzebiel 21.11.2017 40 / 77

1 int x;2 decltype(x); // an entity3 decltype(5); // expression4 decltype((x)); // expression

decltype grzebiel 21.11.2017 40 / 77

1 int x;2 decltype(x); // an entity3 decltype(5); // expression4 decltype((x)); // expression

decltype grzebiel 21.11.2017 40 / 77

1 struct S{int m;};23 const S* sptr;4 decltype((sptr->m)) y;

decltype grzebiel 21.11.2017 41 / 77

1 auto string = "string literal";2 decltype(string) y;

decltype grzebiel 21.11.2017 42 / 77

1 decltype("string literal") y;

decltype grzebiel 21.11.2017 43 / 77

1 auto

2 decltype

3 default args

4 rvalue reference

5 syntax

default args grzebiel 21.11.2017 44 / 77

inheritance!

1 void say(std::string who,2 int what)3 {4 std::cout << who << " says: "5 << what << std::endl;6 }78 struct Parent9 {

10 virtual void say(int a = 5)11 {12 ::say("Parent", a);13 }1415 virtual ~Parent() = default;16 };

1718 class Child : public Parent19 {20 void say(int a = 7) override21 {22 ::say("Child", a);23 }24 };2526 int main() {27 Child c{};28 Parent* p = &c;2930 p->say();31 }

default args grzebiel 21.11.2017 45 / 77

inheritance!

1 void say(std::string who,2 int what)3 {4 std::cout << who << " says: "5 << what << std::endl;6 }78 struct Parent9 {

10 virtual void say(int a = 5)11 {12 ::say("Parent", a);13 }1415 virtual ~Parent() = default;16 };

1718 class Child : public Parent19 {20 void say(int a = 7) override21 {22 ::say("Child", a);23 }24 };2526 int main() {27 Child c{};28 Parent* p = &c;2930 p->say();31 }

default args grzebiel 21.11.2017 45 / 77

inheritance!

1 void say(std::string who,2 int what)3 {4 std::cout << who << " says: "5 << what << std::endl;6 }78 struct Parent9 {

10 virtual void say(int a = 5)11 {12 ::say("Parent", a);13 }1415 virtual ~Parent() = default;16 };

1718 class Child : public Parent19 {20 void say(int a = 7) override21 {22 ::say("Child", a);23 }24 };2526 int main() {27 Child c{};28 Parent* p = &c;2930 p->say();31 }

default args grzebiel 21.11.2017 45 / 77

inheritance!

1 void say(std::string who,2 int what)3 {4 std::cout << who << " says: "5 << what << std::endl;6 }78 struct Parent9 {

10 virtual void say(int a = 5)11 {12 ::say("Parent", a);13 }1415 virtual ~Parent() = default;16 };

1718 class Child : public Parent19 {20 void say(int a = 7) override21 {22 ::say("Child", a);23 }24 };2526 int main() {27 Child c{};28 Parent* p = &c;2930 p->say();31 }

default args grzebiel 21.11.2017 45 / 77

inheritance!

1 void say(std::string who,2 int what)3 {4 std::cout << who << " says: "5 << what << std::endl;6 }78 struct Parent9 {

10 virtual void say(int a = 5)11 {12 ::say("Parent", a);13 }1415 virtual ~Parent() = default;16 };

1718 class Child : public Parent19 {20 void say(int a = 7) override21 {22 ::say("Child", a);23 }24 };2526 int main() {27 Child c{};28 Parent* p = &c;2930 p->say();31 }

default args grzebiel 21.11.2017 45 / 77

inheritance!

1 void say(std::string who,2 int what)3 {4 std::cout << who << " says: "5 << what << std::endl;6 }78 struct Parent9 {

10 virtual void say(int a = 5)11 {12 ::say("Parent", a);13 }1415 virtual ~Parent() = default;16 };

1718 class Child : public Parent19 {20 void say(int a = 7) override21 {22 ::say("Child", a);23 }24 };2526 int main() {27 Child c{};28 Parent* p = &c;2930 p->say();31 }

default args grzebiel 21.11.2017 45 / 77

inheritance!

1 void say(std::string who,2 int what)3 {4 std::cout << who << " says: "5 << what << std::endl;6 }78 struct Parent9 {

10 virtual void say(int a = 5)11 {12 ::say("Parent", a);13 }1415 virtual ~Parent() = default;16 };

1718 class Child : public Parent19 {20 void say(int a = 7) override21 {22 ::say("Child", a);23 }24 };2526 int main() {27 Child c{};28 Parent* p = &c;2930 p->say();31 }

default args grzebiel 21.11.2017 45 / 77

inheritance!

1 void say(std::string who,2 int what)3 {4 std::cout << who << " says: "5 << what << std::endl;6 }78 struct Parent9 {

10 virtual void say(int a = 5)11 {12 ::say("Parent", a);13 }1415 virtual ~Parent() = default;16 };

1718 class Child : public Parent19 {20 void say(int a = 7) override21 {22 ::say("Child", a);23 }24 };2526 int main() {27 Child c{};28 Parent* p = &c;2930 p->say();31 }

default args grzebiel 21.11.2017 45 / 77

inheritance!

1 void say(std::string who,2 int what)3 {4 std::cout << who << " says: "5 << what << std::endl;6 }78 struct Parent9 {

10 virtual void say(int a = 5)11 {12 ::say("Parent", a);13 }1415 virtual ~Parent() = default;16 };

1718 class Child : public Parent19 {20 void say(int a = 7) override21 {22 ::say("Child", a);23 }24 };2526 int main() {27 Child c{};28 Parent* p = &c;2930 p->say();31 }

default args grzebiel 21.11.2017 45 / 77

and the output is

Child says: 5

default args grzebiel 21.11.2017 46 / 77

and the output is

Child says:

5

default args grzebiel 21.11.2017 46 / 77

and the output is

Child says: 5

default args grzebiel 21.11.2017 46 / 77

default args grzebiel 21.11.2017 47 / 77

function call phases

default args grzebiel 21.11.2017 48 / 77

function call phases

• name lookup

default args grzebiel 21.11.2017 48 / 77

function call phases

• name lookup

• template type deduction

default args grzebiel 21.11.2017 48 / 77

function call phases

• name lookup

• template type deduction

• overload resolution

default args grzebiel 21.11.2017 48 / 77

function call phases

• name lookup

• template type deduction

• overload resolution

• access control

default args grzebiel 21.11.2017 48 / 77

function call phases

• name lookup

• template type deduction

• overload resolution

• access control

• virtual function call

default args grzebiel 21.11.2017 48 / 77

function call phases

• name lookup

• template type deduction

• overload resolution

• access control

• virtual function call

default args grzebiel 21.11.2017 48 / 77

after finding default argument

1 void say(std::string who,2 int what)3 {4 std::cout << who << " says: "5 << what << std::endl;6 }78 struct Parent9 {

10 virtual void say(int a = 5)11 {12 ::say("Parent", a);13 }1415 virtual ~Parent() = default;16 };

1718 class Child : public Parent19 {20 void say(int a = 7) override21 {22 ::say("Child", a);23 }24 };2526 int main() {27 Child c{};28 Parent* p = &c;2930 p->say();31 }

default args grzebiel 21.11.2017 49 / 77

after finding default argument

1 void say(std::string who,2 int what)3 {4 std::cout << who << " says: "5 << what << std::endl;6 }78 struct Parent9 {

10 virtual void say(int a)11 {12 ::say("Parent", a);13 }1415 virtual ~Parent() = default;16 };

1718 class Child : public Parent19 {20 void say(int a) override21 {22 ::say("Child", a);23 }24 };2526 int main() {27 Child c{};28 Parent* p = &c;2930 p->say(5);31 }

default args grzebiel 21.11.2017 49 / 77

function call phases

• name lookup

• template type deduction

• overload resolution

• access control

• virtual function call

default args grzebiel 21.11.2017 50 / 77

function call phases

• name lookup

• template type deduction

• overload resolution

• access control

• virtual function call

default args grzebiel 21.11.2017 50 / 77

access control

1 void say(std::string who,2 int what)3 {4 std::cout << who << " says: "5 << what << std::endl;6 }78 struct Parent9 {

10 virtual void say(int a)11 {12 ::say("Parent", a);13 }1415 virtual ~Parent() = default;16 };

1718 class Child : public Parent19 {20 void say(int a) override21 {22 ::say("Child", a);23 }24 };2526 int main() {27 Child c{};28 Parent* p = &c;2930 p->say(5);31 }

default args grzebiel 21.11.2017 51 / 77

access control

1 void say(std::string who,2 int what)3 {4 std::cout << who << " says: "5 << what << std::endl;6 }78 struct Parent9 {

10 virtual void say(int a)11 {12 ::say("Parent", a);13 }1415 virtual ~Parent() = default;16 };

1718 class Child : public Parent19 {20 void say(int a) override21 {22 ::say("Child", a);23 }24 };2526 int main() {27 Child c{};28 Parent* p = &c;2930 p->say(5);31 }

default args grzebiel 21.11.2017 51 / 77

access control

1 void say(std::string who,2 int what)3 {4 std::cout << who << " says: "5 << what << std::endl;6 }78 struct Parent9 {

10 virtual void say(int a)11 {12 ::say("Parent", a);13 }1415 virtual ~Parent() = default;16 };

1718 class Child : public Parent19 {20 void say(int a) override21 {22 ::say("Child", a);23 }24 };2526 int main() {27 Child c{};28 Parent* p = &c;2930 p->say(5);31 }

default args grzebiel 21.11.2017 51 / 77

access control

1 void say(std::string who,2 int what)3 {4 std::cout << who << " says: "5 << what << std::endl;6 }78 struct Parent9 {

10 virtual void say(int a)11 {12 ::say("Parent", a);13 }1415 virtual ~Parent() = default;16 };

1718 class Child : public Parent19 {20 void say(int a) override21 {22 ::say("Child", a);23 }24 };2526 int main() {27 Child c{};28 Parent* p = &c;2930 p->say(5);31 }

default args grzebiel 21.11.2017 51 / 77

argument redeclaration1 int foo(int a, int b = 5);23 int main()4 {5 foo(1); // a = 1, b = 567 int foo(int a, int b = 7);8 foo(2); // a = 2, b = 7;9 {

10 int foo(int a = 3, int b = 12);11 foo(); // a = 3, b = 12;12 // ::foo(); // compilation error13 ::foo(4); // a = 4, b = 5;14 }15 }

default args grzebiel 21.11.2017 52 / 77

argument redeclaration1 int foo(int a, int b = 5);23 int main()4 {5 foo(1); // a = 1, b = 567 int foo(int a, int b = 7);8 foo(2); // a = 2, b = 7;9 {

10 int foo(int a = 3, int b = 12);11 foo(); // a = 3, b = 12;12 // ::foo(); // compilation error13 ::foo(4); // a = 4, b = 5;14 }15 }

default args grzebiel 21.11.2017 52 / 77

argument redeclaration1 int foo(int a, int b = 5);23 int main()4 {5 foo(1); // a = 1, b = 567 int foo(int a, int b = 7);8 foo(2); // a = 2, b = 7;9 {

10 int foo(int a = 3, int b = 12);11 foo(); // a = 3, b = 12;12 // ::foo(); // compilation error13 ::foo(4); // a = 4, b = 5;14 }15 }

default args grzebiel 21.11.2017 52 / 77

argument redeclaration1 int foo(int a, int b = 5);23 int main()4 {5 foo(1); // a = 1, b = 567 int foo(int a, int b = 7);8 foo(2); // a = 2, b = 7;9 {

10 int foo(int a = 3, int b = 12);11 foo(); // a = 3, b = 12;12 // ::foo(); // compilation error13 ::foo(4); // a = 4, b = 5;14 }15 }

default args grzebiel 21.11.2017 52 / 77

argument redeclaration1 int foo(int a, int b = 5);23 int main()4 {5 foo(1); // a = 1, b = 567 int foo(int a, int b = 7);8 foo(2); // a = 2, b = 7;9 {

10 int foo(int a = 3, int b = 12);11 foo(); // a = 3, b = 12;12 // ::foo(); // compilation error13 ::foo(4); // a = 4, b = 5;14 }15 }

default args grzebiel 21.11.2017 52 / 77

argument redeclaration1 int foo(int a, int b = 5);23 int main()4 {5 foo(1); // a = 1, b = 567 int foo(int a, int b = 7);8 foo(2); // a = 2, b = 7;9 {

10 int foo(int a = 3, int b = 12);11 foo(); // a = 3, b = 12;12 // ::foo(); // compilation error13 ::foo(4); // a = 4, b = 5;14 }15 }

default args grzebiel 21.11.2017 52 / 77

argument redeclaration1 int foo(int a, int b = 5);23 int main()4 {5 foo(1); // a = 1, b = 567 int foo(int a, int b = 7);8 foo(2); // a = 2, b = 7;9 {

10 int foo(int a = 3, int b = 12);11 foo(); // a = 3, b = 12;12 // ::foo(); // compilation error13 ::foo(4); // a = 4, b = 5;14 }15 }

default args grzebiel 21.11.2017 52 / 77

argument redeclaration1 int foo(int a, int b = 5);23 int main()4 {5 foo(1); // a = 1, b = 567 int foo(int a, int b = 7);8 foo(2); // a = 2, b = 7;9 {

10 int foo(int a = 3, int b = 12);11 foo(); // a = 3, b = 12;12 // ::foo(); // compilation error13 ::foo(4); // a = 4, b = 5;14 }15 }

default args grzebiel 21.11.2017 52 / 77

argument redeclaration1 int foo(int a, int b = 5);23 int main()4 {5 foo(1); // a = 1, b = 567 int foo(int a, int b = 7);8 foo(2); // a = 2, b = 7;9 {

10 int foo(int a = 3, int b = 12);11 foo(); // a = 3, b = 12;12 // ::foo(); // compilation error13 ::foo(4); // a = 4, b = 5;14 }15 }

default args grzebiel 21.11.2017 52 / 77

multiple declarations

1 #include <iostream>23 void foo(int d, float u = 3.14);4 void foo(int p = 5, float a);56 int main()7 {8 foo();9

10 return 0;11 }

default args grzebiel 21.11.2017 53 / 77

multiple declarations

1 #include <iostream>23 void foo(int d, float u = 3.14);4 void foo(int p = 5, float a);56 int main()7 {8 foo();9

10 return 0;11 }

default args grzebiel 21.11.2017 53 / 77

multiple declarations

1 #include <iostream>23 void foo(int d, float u = 3.14);4 void foo(int p = 5, float a);56 int main()7 {8 foo();9

10 return 0;11 }

default args grzebiel 21.11.2017 53 / 77

CppCon 2017: Michael Price “Function default arguments:Slingshot or Shotgun?”

default args grzebiel 21.11.2017 54 / 77

1 auto

2 decltype

3 default args

4 rvalue reference

5 syntax

rvalue reference grzebiel 21.11.2017 55 / 77

1 #include <iostream>2 #include <string>34 void foo(std::string&) {5 std::cout << "got lvalue "6 << std::endl;7 }89 void foo(std::string&&) {

10 std::cout << "got rvalue "11 << std::endl;12 }1314 int main() {15 std::string&& a{"this it the string"};16 foo(a);17 return 0;18 }

rvalue reference grzebiel 21.11.2017 56 / 77

1 #include <iostream>2 #include <string>34 void foo(std::string&) {5 std::cout << "got lvalue "6 << std::endl;7 }89 void foo(std::string&&) {

10 std::cout << "got rvalue "11 << std::endl;12 }1314 int main() {15 std::string&& a{"this it the string"};16 foo(a);17 return 0;18 }

rvalue reference grzebiel 21.11.2017 56 / 77

1 #include <iostream>2 #include <string>34 void foo(std::string&) {5 std::cout << "got lvalue "6 << std::endl;7 }89 void foo(std::string&&) {

10 std::cout << "got rvalue "11 << std::endl;12 }1314 int main() {15 std::string&& a{"this it the string"};16 foo(a);17 return 0;18 }

rvalue reference grzebiel 21.11.2017 56 / 77

1 #include <iostream>2 #include <string>34 void foo(std::string&) {5 std::cout << "got lvalue "6 << std::endl;7 }89 void foo(std::string&&) {

10 std::cout << "got rvalue "11 << std::endl;12 }1314 int main() {15 std::string&& a{"this it the string"};16 foo(a);17 return 0;18 }

rvalue reference grzebiel 21.11.2017 56 / 77

1 #include <iostream>2 #include <string>34 void foo(std::string&) {5 std::cout << "got lvalue "6 << std::endl;7 }89 void foo(std::string&&) {

10 std::cout << "got rvalue "11 << std::endl;12 }1314 int main() {15 std::string&& a{"this it the string"};16 foo(a);17 return 0;18 }

rvalue reference grzebiel 21.11.2017 56 / 77

1 #include <iostream>2 #include <string>34 void foo(std::string&) {5 std::cout << "got lvalue "6 << std::endl;7 }89 void foo(std::string&&) {

10 std::cout << "got rvalue "11 << std::endl;12 }1314 int main() {15 std::string&& a{"this it the string"};16 foo(a);17 return 0;18 }

rvalue reference grzebiel 21.11.2017 56 / 77

and we got

lvalue

rvalue reference grzebiel 21.11.2017 57 / 77

and we got lvalue

rvalue reference grzebiel 21.11.2017 57 / 77

rvalue reference grzebiel 21.11.2017 58 / 77

The variable of type rvalue reference to type T is

an lvalue itself.

rvalue reference grzebiel 21.11.2017 59 / 77

The variable of type rvalue reference to type T is

an lvalue itself.

rvalue reference grzebiel 21.11.2017 59 / 77

rvalue reference grzebiel 21.11.2017 60 / 77

Lets imagine that we are in alternative universe in whichvariable of type rvalue reference is always an rvalue

rvalue reference grzebiel 21.11.2017 61 / 77

rvalue reference grzebiel 21.11.2017 62 / 77

1 #include <iostream>2 #include <string>34 void foo(std::string&) {5 std::cout << "got lvalue "6 << std::endl;7 }89 void foo(std::string&&) {

10 std::cout << "got rvalue "11 << std::endl;12 }1314 int main() {15 std::string&& a{"this it the string"};16 foo(a);17 return 0;18 }

rvalue reference grzebiel 21.11.2017 63 / 77

1 #include <iostream>2 #include <string>34 void foo(std::string&) {5 std::cout << "got lvalue "6 << std::endl;7 }89 void foo(std::string&&) {

10 std::cout << "got rvalue "11 << std::endl;12 }1314 int main() {15 std::string&& a{"this it the string"};16 foo(a);17 return 0;18 }

rvalue reference grzebiel 21.11.2017 63 / 77

1 #include <iostream>2 #include <string>34 void foo(std::string&) {5 std::cout << "got lvalue "6 << std::endl;7 }89 void foo(std::string&&) {

10 std::cout << "got rvalue "11 << std::endl;12 }1314 int main() {15 std::string&& a{"this it the string"};16 foo(a);17 return 0;18 }

rvalue reference grzebiel 21.11.2017 63 / 77

in this magical place

1 void foo(std::string s);23 void bar(std::string&& s)4 {5 foo(s);6 std::cout << s7 << std::endl;8 };

rvalue reference grzebiel 21.11.2017 64 / 77

in this magical place

1 void foo(std::string s);23 void bar(std::string&& s)4 {5 foo(s);6 std::cout << s7 << std::endl;8 };

rvalue reference grzebiel 21.11.2017 64 / 77

in this magical place

1 void foo(std::string s);23 void bar(std::string&& s)4 {5 foo(s);6 std::cout << s7 << std::endl;8 };

rvalue reference grzebiel 21.11.2017 64 / 77

in this magical place

1 void foo(std::string s);23 void bar(std::string&& s)4 {5 foo(s);6 std::cout << s7 << std::endl;8 };

rvalue reference grzebiel 21.11.2017 64 / 77

in this magical place

1 void foo(std::string s);23 void bar(std::string&& s)4 {5 foo(s);6 std::cout << s7 << std::endl;8 };

rvalue reference grzebiel 21.11.2017 64 / 77

in this magical place

1 void foo(std::string s);23 void bar(std::string&& s)4 {5 foo(s);6 std::cout << s7 << std::endl;8 };

rvalue reference grzebiel 21.11.2017 64 / 77

back to normal world

rvalue reference grzebiel 21.11.2017 65 / 77

1 void foo(std::string&);2 void foo(std::string&&);3 //...45 template<typename T>6 void bar(const T& t)7 {8 foo(t);9 }

1011 template<typename T>12 void bar(T&& t)13 {14 foo(std::move(t));15 }

rvalue reference grzebiel 21.11.2017 66 / 77

1 void foo(std::string&);2 void foo(std::string&&);3 //...45 template<typename T>6 void bar(const T& t)7 {8 foo(t);9 }

1011 template<typename T>12 void bar(T&& t)13 {14 foo(std::move(t));15 }

rvalue reference grzebiel 21.11.2017 66 / 77

1 void foo(std::string&);2 void foo(std::string&&);3 //...45 template<typename T>6 void bar(const T& t)7 {8 foo(t);9 }

1011 template<typename T>12 void bar(T&& t)13 {14 foo(std::move(t));15 }

rvalue reference grzebiel 21.11.2017 66 / 77

1 void foo(std::string&);2 void foo(std::string&&);3 //...45 template<typename T>6 void bar(const T& t)7 {8 foo(t);9 }

1011 template<typename T>12 void bar(T&& t)13 {14 foo(std::move(t));15 }

rvalue reference grzebiel 21.11.2017 66 / 77

1 void foo(std::string&);2 void foo(std::string&&);3 //...45 template<typename T>6 void bar(const T& t)7 {8 foo(t);9 }

1011 template<typename T>12 void bar(T&& t)13 {14 foo(std::move(t));15 }

rvalue reference grzebiel 21.11.2017 66 / 77

1 void foo(std::string&);2 void foo(std::string&&);3 //...45 template<typename T>6 void bar(const T& t)7 {8 foo(t);9 }

1011 template<typename T>12 void bar(T&& t)13 {14 foo(std::move(t));15 }

rvalue reference grzebiel 21.11.2017 66 / 77

forwarding reference

1 void foo(std::string&);2 void foo(std::string&&);3 //...45 template<typename T>6 void bar(T&& t)7 {8 foo(std::forward<T>(t));9 }

rvalue reference grzebiel 21.11.2017 67 / 77

forwarding reference

1 void foo(std::string&);2 void foo(std::string&&);3 //...45 template<typename T>6 void bar(T&& t)7 {8 foo(std::forward<T>(t));9 }

rvalue reference grzebiel 21.11.2017 67 / 77

forwarding reference

1 void foo(std::string&);2 void foo(std::string&&);3 //...45 template<typename T>6 void bar(T&& t)7 {8 foo(std::forward<T>(t));9 }

rvalue reference grzebiel 21.11.2017 67 / 77

this is not forwarding1 template<typename T>2 struct Foo3 {4 void bar(T&& t);5 };67 int main()8 {9 std::string s = "I don’t fit small string";

10 Foo<std::string> f;11 //f.bar(s); // compilation error12 f.bar(std::move(s));13 };

rvalue reference grzebiel 21.11.2017 68 / 77

this is not forwarding1 template<typename T>2 struct Foo3 {4 void bar(T&& t);5 };67 int main()8 {9 std::string s = "I don’t fit small string";

10 Foo<std::string> f;11 //f.bar(s); // compilation error12 f.bar(std::move(s));13 };

rvalue reference grzebiel 21.11.2017 68 / 77

this is not forwarding1 template<typename T>2 struct Foo3 {4 void bar(T&& t);5 };67 int main()8 {9 std::string s = "I don’t fit small string";

10 Foo<std::string> f;11 //f.bar(s); // compilation error12 f.bar(std::move(s));13 };

rvalue reference grzebiel 21.11.2017 68 / 77

this is not forwarding1 template<typename T>2 struct Foo3 {4 void bar(T&& t);5 };67 int main()8 {9 std::string s = "I don’t fit small string";

10 Foo<std::string> f;11 //f.bar(s); // compilation error12 f.bar(std::move(s));13 };

rvalue reference grzebiel 21.11.2017 68 / 77

this is not forwarding1 template<typename T>2 struct Foo3 {4 void bar(T&& t);5 };67 int main()8 {9 std::string s = "I don’t fit small string";

10 Foo<std::string> f;11 //f.bar(s); // compilation error12 f.bar(std::move(s));13 };

rvalue reference grzebiel 21.11.2017 68 / 77

this is not forwarding1 template<typename T>2 struct Foo3 {4 void bar(T&& t);5 };67 int main()8 {9 std::string s = "I don’t fit small string";

10 Foo<std::string> f;11 //f.bar(s); // compilation error12 f.bar(std::move(s));13 };

rvalue reference grzebiel 21.11.2017 68 / 77

wait a second

what if all I want is an rvalue referemce?

rvalue reference grzebiel 21.11.2017 69 / 77

1 #include <type_traits>23 template <4 typename T,5 typename = std::enable_if_t<6 std::is_rvalue_reference<T>::value> >7 void bar(T&& t)8 {9 foo(std::move(t));

10 }

rvalue reference grzebiel 21.11.2017 70 / 77

1 #include <type_traits>23 template <4 typename T,5 typename = std::enable_if_t<6 std::is_rvalue_reference<T>::value> >7 void bar(T&& t)8 {9 foo(std::move(t));

10 }

rvalue reference grzebiel 21.11.2017 70 / 77

1 auto

2 decltype

3 default args

4 rvalue reference

5 syntax

syntax grzebiel 21.11.2017 71 / 77

1 struct Foo2 {3 Foo() {4 std::cout << "default\n";5 }67 Foo(int) {8 std::cout << "param\n";9 }

10 };1112 int main()13 {14 int a = 5;15 { Foo(a); }16 return 0;17 }

syntax grzebiel 21.11.2017 72 / 77

1 struct Foo2 {3 Foo() {4 std::cout << "default\n";5 }67 Foo(int) {8 std::cout << "param\n";9 }

10 };1112 int main()13 {14 int a = 5;15 { Foo(a); }16 return 0;17 }

syntax grzebiel 21.11.2017 72 / 77

1 struct Foo2 {3 Foo() {4 std::cout << "default\n";5 }67 Foo(int) {8 std::cout << "param\n";9 }

10 };1112 int main()13 {14 int a = 5;15 { Foo(a); }16 return 0;17 }

syntax grzebiel 21.11.2017 72 / 77

1 struct Foo2 {3 Foo() {4 std::cout << "default\n";5 }67 Foo(int) {8 std::cout << "param\n";9 }

10 };1112 int main()13 {14 int a = 5;15 { Foo(a); }16 return 0;17 }

syntax grzebiel 21.11.2017 72 / 77

1 struct Foo2 {3 Foo() {4 std::cout << "default\n";5 }67 Foo(int) {8 std::cout << "param\n";9 }

10 };1112 int main()13 {14 int a = 5;15 { Foo(a); }16 return 0;17 }

syntax grzebiel 21.11.2017 72 / 77

1 #include <stdio.h>2 int main()3 {4 int(x) = 38;5 x += 4;6 printf("%d", x);78 return 0;9 }

syntax grzebiel 21.11.2017 73 / 77

syntax grzebiel 21.11.2017 74 / 77

1 int foo(int);23 int main()4 {5 int (*x)(int) = foo;6 return 0;7 }

syntax grzebiel 21.11.2017 75 / 77

1 int foo(int);23 int main()4 {5 int (*x)(int) = foo;6 return 0;7 }

syntax grzebiel 21.11.2017 75 / 77

1 int foo(int);23 int main()4 {5 int (*x)(int) = foo;6 return 0;7 }

syntax grzebiel 21.11.2017 75 / 77

1 struct Foo2 {3 Foo() {4 std::cout << "default\n";5 }67 Foo(int) {8 std::cout << "param\n";9 }

10 };1112 int main()13 {14 int a = 5;15 { Foo(a); }16 return 0;17 }

syntax grzebiel 21.11.2017 76 / 77

1 struct Foo2 {3 Foo() {4 std::cout << "default\n";5 }67 Foo(int) {8 std::cout << "param\n";9 }

10 };1112 int main()13 {14 int a = 5;15 { Foo(a); }16 return 0;17 }

syntax grzebiel 21.11.2017 76 / 77

?syntax grzebiel 21.11.2017 77 / 77

top related