- the worst feature of modern c++: default behavior di… · the worst feature of modern c++:...
TRANSCRIPT
The worst feature of modern C++: default behavior
Marcin Grzebieluch
21.11.2017
grzebiel 21.11.2017 1 / 77
The worst feature of modern C++: default behavior
Marcin Grzebieluch
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