# Welcome # Who is this guy? # Goal(s) 1. Don't _WTF_ quite so much when looking at C++ PRs 2. **Know what you don't know** (so you know what to look up to learn more) # Agenda 1. Some new stuff 2. Some language oddities 3. Some OO specifics 5. Templating 6. Compilers, CMake, and you 7. Where to learn more? 8. Random topics as time allows # Hello, World! #include int main() { std::cout << "Hello, World!" << std::endl; return 0; } There can only be one `main`. # Hello, World! $ ls main.cc $ cat main.cc #include int main() { std::cout << "Hello, World!" << std::endl; return 0; } $ clang++ ./main.cc $ ./a.out Hello, World! # Agenda 1. **Some new stuff** 2. Some language oddities 3. Some OO specifics 5. Templating 6. Compilers, CMake, and you 7. Where to learn more? 8. Random topics as time allows # What's New C++14 and C++17: Not your father's C++ - More `auto` - `using` (templates for typedefs) - Lambdas - Range-based `for` - Smart(er) pointers - std::move and rvalue-refs - threading API # What's New: More `auto` For types: auto numbers = std::vector {1,2,3}; For return values: auto next(int i) { return i + 1; } **Later**: Force the compiler to tell us what the `auto` is deduced to. # What's New: Lambdas auto printer = [](auto c) { std::cout << c << std::endl; }; printer("Foo"); The `[]` lets you *capture* outside variables. # What's New: Range-based `for` auto numbers = std::vector {1,2,3}; for(auto number : numbers) { std::cout << number << std::endl; } # What's New: Smart(er) Pointers No more `new`: auto client = std::make_shared("mongo://..."); # What's New: rvals (`&&`) and `std::thread` - Too complex to talk about here. - Read more if you're going to work on framework or library code. (Meyers book is good for this.) # Agenda 1. Some new stuff 2. **Some language oddities** 3. Some OO specifics 5. Templating 6. Compilers, CMake, and you 7. Where to learn more? 8. Random topics as time allows # Language: Primitive Types #include int main() { std::cout << "Hello, World!" << std::endl; return 0; } `long`, `short`, `char`, `bool`, `int`, `double`, `float`, `long long`, `unsigned ...`, a few more but not that many. # Language: Assignment Syntax Sucks 🌟 Constructors: struct Point {int x; int y;}; Point p = Point {1, 2}; // if ctor is `explicit` Point p = {1, 2}; Point p {1, 2}; Point p (1, 2); // needs ctor! Primitives: int x = {7}; int x {7}; int x (7); int x = 7; Preferred: auto p = Point {1,2}; auto x = 7; # Language: Stack All The Things 🌟 int main() { Person x = Person("Ryan", "T"); Person y = x; print(x); print(y); x = y; } void print(Person x) { ... } # Language: Assignment isn't Real int main() { Person x = Person("Ryan", "T"); Person y = Person("Ryan", "S"); x = y; // ???? } # Language: Assignment isn't Real 🌟 Person x = Person("Ryan", "T"); Person y = Person("Ryan", "S"); // x = y is "really": x.operator=(y); # Language: Assignment isn't Real Foo x = ...; x = 6; // x.operator=(int 6) x = false; // x.operator=(bool false) # Language: Assignment isn't Real ++x; // x.operator++() x++; // x.operator++(int) x << "Hello"; // x.operator<<(string "Hello") x[7] = 8; // x.operator[](int 7) # Language: Assignment isn't Real x %= 7; // x.operator%=(int 7) x == 7; // x.operator==(int 7) x == x; // x.operator==(Foo x) *x; // x.operator*() x->foo(); // x.operator->().foo() if(x) // x.operator bool() x,6; // 😔 # Language: Assignment isn't Real 🌟 > Too much syntax sugar causes cancer of the semicolon struct Foo { int i; int operator ,(int other) { return i + 10; } }; auto y = Foo{6}; std::cout << (y,7) << std::endl; // 😔 'nuff said? # Language: Pass By Value int main() { auto d = Database(); } void print(Database d) { ... } 😱 Deep Copy! 😱 # Language: Pointers and Refs - C only has pointers (but is **always** pass-by-value) - Java and Python (implicitly) also only have pointers. (Except primitives which are passed by value. Usually.) # Language: Pointers and Refs 🌟 C++ plays by its own rules 🤠 - Pass by value (like C; pointers are values) - **Unless** signature takes a ref (then use that ref) void process(Database d); void process(Database& d); void process(const Database& d); # Language: Pointers and Refs int x = 7; **Pointers**: int* pointerToX = &x; // std::addressof(x); *pointerToX = 10; **Refs**: int& refToX = x; refToX = 10; Results: `x == 10`. # Language: Pointers and Refs How did this work?? x[7] = 8; It's just syntax sugar! struct Foo { int i; int& operator[](int) { return i; } } Cool tidbit: Refs can never be `nullptr`. Enforced at the language-level. # Language: Pointers and Refs Refs can be evil 😈 void evil(int& x) { ++x; } void doSomething() { int x = 7; evil(x); } # Language: Pointers and Refs 🌟 Usually use `const X&` to prevent calling non-consty things. int main() { auto d = Database(); } void print(const Database& d) { ... } 👯 No Deep-Copy 👯 # Language: Pointers and Refs void foo(Database* d) { ... } void foo(Database d) { ... } void foo(Database& d) { ... } 💅🏽 Can't have both ref **and** value overloads 💅🏽 # Language: Pointers and Refs **Q**: When do I use pointers? **A**: When you *know* that you don't own the thing **Q**: What do I use instead? **A**: Use `std::shared_ptr` (ref-counted, some overhead) **A**: or `std::unique_ptr` (faster but awkwarder) # Language: Pointers and Refs > Don't use `new` > (or at least never "naked `new`" 🙈) Instead of this: Database* d = new Database(1,2,3); ... 💥? delete d; Do this: auto d = std::make_shared(1,2,3); # Moving On: Code Organization! Linkers and Compilers: Scheme together to share object code across multiple executables # Language: Code Organization No de-facto standards on - directory-layout - class/method/file naming - documentation and where it goes - what should be "header-only" and what should be a compiled library 😩 Unlike Java. Kinda like Python. # Language: Code Organization 🌟 `include/lib.hpp`: #ifndef _HAVE_LIB_HPP #define _HAVE_LIB_HPP void add(int, int); void sub(int, int); #endif `src/lib.cpp`: #include void add(int a, int b) { return a + b; } .... `src/main.cpp`: #include int main() { return add(1,2); } # Language: Code Organization **Header files**: - Class declarations - Any templates and their definitions - Rarely: inline function definitions **Impl files**: - Include needed header files - Implementations # Language: (Named) Namespaces std::cout mongo::client() # Language: (Named) Namespaces namespace mongo { class client; } namespace std { ostream& cout; } # Language: (Named) Namespaces 🌟 // new in c++17 namespace foo::bar { ... } // instead of: namespace foo { namespace bar { ... } } # Language: Anonymous Namespaces 🌟 #include // best-practice! namespace { void printPerson(const Person& p) { ... } } void Person::inspect() { something(); } (Don't pollute the global namespace.) # Language: Argument-Dependent Lookup (ADL) 👹 std::cout << 7; Note that `operator<<(std::ostream&,int)` isn't in the global namespace... # Agenda 1. Some new stuff 2. Some language oddities 3. **Some OO specifics** 5. Templating 6. Compilers, CMake, and you 7. Where to learn more? 8. Random topics as time allows # OO: 👸🏽 Types 🤴🏿 - Your types == built-in types - Do as the `int`s do # OO: Initializer Syntax struct Point { int x; int y; } auto origin = Point {0,0}; # OO: Intializer Syntax (Reminder From Earlier) 🌟 struct Point {int x; int y;}; Point p = Point {1, 2}; // if ctor is `explicit` Point p = {1, 2}; Point p {1, 2}; Point p (1, 2); // needs ctor! # OO: Initializer Syntax What you "want" to do from Java/Python: struct Point { int x; int y; Point(int x, int y) { this->x = x; this->y = y; } }; **But**: Then can't make `x` and `y` `const`! # OO: Initializer Syntax **Solution**: struct Point { const int x; const int y; Point(int x, int y) : x{x}, y{y} {} }; **NB**: Conventions usually have class members with leading underscore: struct Point { const int _x; const int _y; } # OO: Default Constructors class Banner { public: Banner() = default; // equiv: // Banner() {} private: std::string msg = "Foo"; }; # OO: Constness (1/2) struct Point { const int x; const int y; Point(int x, int y) : x{x}, y{y} {} const Point up() const { return Point {this->x, this->y + 1} } } # OO: Constness (2/2) 🌟 `const` is like a separate interface for your class. void draw ( Point p) { } void drawRef ( Point &p) { } void drawConstRef (const Point &p) { } const Point origin = {0,0}; Point up = origin.up(); const Point cup = origin.up(); // OK(ish) draw(origin); draw(up); draw(cup); drawRef(origin); // Error! drawRef(up); drawRef(cup); // Error! // OK drawConstRef(origin); drawConstRef(up); drawConstRef(cup); # OO: Lvalue-ness & RValue-ness Ugh: struct Foo { void enact() &; // 1 void enact() &&; // 2 } void makeFoo() { auto out = Foo{}; return out; } Foo f; f.enact(); // 1 makeFoo().enact(); // 2 # OO: Assignment and Copy (1/2) struct Point { int x; int y Point(int x, int y, int z) : x{x}, y{y}, z{z} {} }; Point a = {0,0}; Point b = {1,1}; Point c = b; // copy a = c; // assign # OO: Assignment and Copy (2/2) 🌟 (Only occasionally necessary) struct Point { ... // Copy constructor // Point a = b Point(const Point& other) : x{other.x}, y{other.y} {} // Copy assignment // c = b Point& operator=(const Point& other) { this->x = other.x; this->y = other.y; return *this; } }; Point a = {0,0}; Point b = {1,1}; Point c = b; a = c; # OO: Destructors and RAII 🌟 struct Point { ... ~Point() { std::cout << "Destructing" << std::endl; } } This is how smart-pointers work. # OO: Visibility 🌟 - **Classes**: Default private - **Structs**: Default public - Create `public:`, `private:`, and `protected:` sections for class-functions and members # OO: Friendship class Printer { }; class SomeObject { friend class Printer; }; **OO Principles**: - "Long-distance" friendships are dangerous. - Consider Passkey idiom instead # OO: Private/Public Inheritance class Figure { }; class BetterFigure : public Figure { }; class SomethingElse : private Figure { }; **OO Principles**: - Hide unless designing to be visible - Composition >> inheritance # OO: Virtual Methods ("Interfaces") 🌟 struct Session { virtual void rollback() { std::cout << "Session"; }; }; struct Causal : public Session { void rollback() override { std::cout << "Causal"; } }; struct Normal : public Session { void rollback() override { std::cout << "Normal"; } }; void enact(bool causal) { std::unique_ptr session; if (causal) { session = std::make_unique(); } else { session = std::make_unique(); } session->rollback(); } # OO: Containers of Polymorphic Types class QueuedJob { public: virtual void run() = 0; }; class PrinterJob : public QueuedJob { void run() override { } }; void runJobs() { std::vector> jobs; jobs.push_back(std::make_unique()); for(auto& job : jobs) { job->run(); } } # OO: Exceptions (1/2) - They're not evil. - Most compilers: no overhead except when thrown - Uncaught exceptions cause the program to exit # OO: Exceptions (2/2) Throw by value and catch by reference void doSomething() { throw std::logic_error("unknown value"); } try { doSomething(); } catch(const std::exception& ex) { std::cerr << ex.what() << std::endl; } catch(...) { // avoid except in framework code ... } # Agenda 1. Some new stuff 2. Some language oddities 3. Some OO specifics 5. **Templating** 6. Compilers, CMake, and you 7. Where to learn more? 8. Random topics as time allows # Templating (1/4) 🌟 - A bit fancier than text-substitution (but not by much!) - Completely separate types ("duplicated" object-code) - Templates need to be defined in headers No "real" connection between these types/classes: std::vector std::vector std::vector # Aside: Templates Versus Java Generics Java version: void blatz(List foos) { for(Foo foo : foos) { explode(foo); } } "Direct translation" C++: template void blatz(const std::vector& foos) { for(auto& foo : foos) { explode(foo); } } More idiomatic: template void blatz(const Foos& foos) { for(auto foo : foos) { explode(foo); } } # Aside: Templates Versus Java Generics No real way to give an "interface" to template parameters. Standards committee is working on it. Calling it _concepts_. # Templating (2/4) 🦆 Hey C++ Does Have Duck-Typing! 🦆 template struct MyStruct { T myvar; void incr() { myvar++; } }; MyStruct m1 {7}; std::cout << m1.myvar << std::endl; m1.incr(); # Templating (2/4) 🦆 Hey C++ Does Have Duck-Typing! 🦆 template struct MyStruct { T myvar; void incr() { myvar++; } }; MyStruct m1 {7}; std::cout << m1.myvar << std::endl; m1.incr(); MyStruct m2 {"Foo"}; std::cout << m1.myvar << std::endl; Does this work? # Templating (2/4) 🦆 Hey C++ Does Have Duck-Typing! 🦆 template struct MyStruct { T myvar; void incr() { myvar++; } }; MyStruct m1 {7}; std::cout << m1.myvar << std::endl; m1.incr(); MyStruct m2 {"Foo"}; std::cout << m1.myvar << std::endl; m2.incr(); Does this work? # Templating (3/4) error: cannot increment value of type 'std::__1::basic_string' myvar++; ~~~~~^ # Templating (4/4) SFINAE 🌟 template struct MyClass { T myvar; void incr() { myvar++; } }; // 🎉 template<> struct MyClass { std::string myvar; void incr() { } }; MyClass m1 {7}; std::cout << m1.myvar << std::endl; m1.incr(); MyClass m2 {"Foo"}; std::cout << m1.myvar << std::endl; m1.incr(); # 🚨 Templating Bonus: Determining Type of `auto` 🚨 template class TD; void foo() { auto x = "123"; TD xType; } **Fancy**: error: implicit instantiation of undefined template 'TD' # Agenda 1. Some new stuff 2. Some language oddities 3. Some OO specifics 5. Templating 6. **Compilers, CMake, and you** 7. Where to learn more? 8. Random topics as time allows # Build Tooling (1/5) 😱🤮🤯🤞🔁 # Build Tooling (2/5) A Haiku about cmake: > CMake is garbage > CMake is garbage > CMake is garbage # Build Tooling (3/5) 🌟 - Use an IDE at first (CLion is nice!) - CMake GUI - `make VERBOSE=1` - Use latest version of CLang you can (xcode 10 beta) sudo xcode-select -s \ /Applications/Xcode-beta.app/Contents/Developer # Build Tooling (4/5) - Learn to read the matrix - SFINAE - Grok how header files, object files, and linkers play together - Use a STL Pretty-Printer (one header file gives you `<<` for many built-in types) # Build Tooling (5/5) CMake is garbage # Agenda 1. Some new stuff 2. Some language oddities 3. Some OO specifics 5. Templating 6. Compilers, CMake, and you 7. **Where to learn more?** 8. Random topics as time allows # Learning More 🌟 - Most books written for people who already know some C++ - [The C++ Programming Language, 4th Edition](https://www.amazon.com/C-Programming-Language-4th/dp/0321563840) ($40) - Meyers [Effective Modern C++](https://www.amazon.com/Effective-Modern-Specific-Ways-Improve/dp/1491903996) ($40) - Good for move, threading, some templating - ["C++ Coding Standards" by Andrei Alexandrescu](https://www.amazon.com/Coding-Standards-Rules-Guidelines-Practices/dp/0321113586) ($50 😼) # Agenda 1. Some new stuff 2. Some language oddities 3. Some OO specifics 5. Templating 6. Compilers, CMake, and you 7. Where to learn more? 8. **Random topics as time allows** # Closing Thoughts 🌟 > This is C++. There are no simple questions, and even fewer simple answers. - Ask on Slack `#cxx-discuss`! Everybody is really friendly and helpful. No n00b-shaming. Much shaming of the language (and of CMake) - Thanks to Henrik's Open-Source Project for [impress.js](https://impress.js.org/#/bored) for powering this presentation! # Random Topics - ABIs - `using X`, `using Y = Z`, don't say `using X` in headers - Implicit conversions - `explicit` constructors - `constexpr` - `assert` - passkey idiom - pimpl idiom My Reference: 8745WUT2P8NHYK1JGP5F4