Slide 1

Slide 1 text

[Objective] C++ Peter Steinberger, @steipete AltConference, San Francisco, June 2015

Slide 2

Slide 2 text

Audience — You've seen C++ before. — You care about elegant, performant code. — The world doesn't end with iOS. — You wanna come to the dark side.

Slide 3

Slide 3 text

$ whoami @steipete

Slide 4

Slide 4 text

$ whoami

Slide 5

Slide 5 text

Every malloc is a mistake.

Slide 6

Slide 6 text

What about Swift?

Slide 7

Slide 7 text

C++ — Actively improved (C++11, C++14, C++17) — Great tooling, great compiler, great ecosystem — Cross-Platform — Really fast — Powerful standard library (STL) — Many 3rd-party libraries available0 0 https://github.com/fffaraz/awesome-cpp

Slide 8

Slide 8 text

Cocoapods won't like you

Slide 9

Slide 9 text

This is not your grandmother's C++! — auto — shared_ptr — weak — lambdas — move semantics

Slide 10

Slide 10 text

auto & range-based for loops // C++98 for (vector::iterator i = v.begin(), e = v.end(); i != e; ++i) { reticulateSpline(*i); } // C++11 for (CGPoint& point : v) { reticulateSpline(point); }

Slide 11

Slide 11 text

auto & range-based for loops // C++98 for (vector::iterator i = v.begin(), e = v.end(); i != e; ++i) { reticulateSpline(*i); } // C++11 for (auto& point : v) { reticulateSpline(point); }

Slide 12

Slide 12 text

auto & range-based for loops // C++98 for (vector::iterator i = v.begin(), e = v.end(); i != e; ++i) { reticulateSpline(*i); } // C++17 for (point : v) { reticulateSpline(point); }

Slide 13

Slide 13 text

std::vector — Continuous block of memory — Stack or Heap — Throws exceptions on access out of bounds — powerful mutators like rotate2 2 http://channel9.msdn.com/Events/GoingNative/2013/Cpp-Seasoning

Slide 14

Slide 14 text

Initializer Lists // C++98 std::vector v; v.push_back(1); // ... v.push_back(5); // C++11 std::vector v = {1, 2, 3, 4, 5};

Slide 15

Slide 15 text

Smart Pointers // Returns all developers. Delete when done. vector get_developers();

Slide 16

Slide 16 text

Smart Pointers // Returns all developers. Delete when done. vector get_developers(); // cleanup for (vector::iterator i = v.begin(); i != v.end(); ++i) { delete *i; }

Slide 17

Slide 17 text

Smart Pointers // Returns all developers (C++11) vector> get_developers();

Slide 18

Slide 18 text

Smart Pointers // Returns all developers (C++11) vector> get_developers(); // adding a new element (C++11) devs.push_back(unique_ptr(new Developer("steipete")));

Slide 19

Slide 19 text

Smart Pointers // Returns all developers (C++11) vector> get_developers(); // adding a new element (C++11, more efficient) devs.emplace_back(unique_ptr(new Developer("steipete")));

Slide 20

Slide 20 text

Smart Pointers // Returns all developers (C++11) vector> get_developers(); // adding a new element (C++14) devs.emplace_back(make_unique("steipete"));

Slide 21

Slide 21 text

Smart Pointers — auto_ptr — unique_ptr — shared_ptr — weak_ptr

Slide 22

Slide 22 text

Smart Pointers // Returns all developers. vector> get_developers(); // later on auto developers = get_developers(); shared_ptr developer = developers[0];

Slide 23

Slide 23 text

Move semantics // get all the points vector points = get_points();

Slide 24

Slide 24 text

Move semantics // get all the points vector points = get_points(); vector(const vector& that) { size_t size = strlen(that.data) + 1; data = new char[size]; memcpy(data, that.data, size); }

Slide 25

Slide 25 text

Move semantics // get all the points vector points = get_points(); vector(vector&& that) { data = that.data; that.data = nullptr; }

Slide 26

Slide 26 text

Move semantics auto a = b; // copy auto a = x + y; // move

Slide 27

Slide 27 text

Lambdas std::sort(people.begin(), people.end(), [](const Person& p1, const Person& p2) { return p1.getId() < p2.getId(); } );

Slide 28

Slide 28 text

Lambdas [] Capture nothing [&] Capture by reference [=] Capture by making a copy [this] Capture enclosing class [=, &foo] [bar]

Slide 29

Slide 29 text

Lambdas void PSPDFParseFont(const char *key, CGPDFObjectRef value, void *info) { NSLog(@"key: %s", key); }; // later, in another function CGPDFDictionaryApplyFunction(fontDict, dictIterator, (__bridge void *)self);

Slide 30

Slide 30 text

Lambdas auto parseFont = [] (const char *key, CGPDFObjectRef value, void *info) { NSLog(@"key: %s", key); }; CGPDFDictionaryApplyFunction(fontDict, parseFont, (__bridge void *)self);

Slide 31

Slide 31 text

How do I start?

Slide 32

Slide 32 text

Objective-C++ — Freely mix C++ and Objective-C3 — Enable by renaming files to .hpp and .mm 3 http://web.archive.org/web/20101203170217/http://developer.apple.com/library/mac/#/ web/20101204020949/http://developer.apple.com/library/mac/documentation/Cocoa/ Conceptual/ObjectiveC/Articles/ocCPlusPlus.html

Slide 33

Slide 33 text

Objective-C++ Gotchas — Compile time — Properties — "Stricter" compiler

Slide 34

Slide 34 text

Popular Projects using Objective-C++ — The Objective-C Runtime — WebKit — Realm — pop — ComponentKit — djinni

Slide 35

Slide 35 text

Why Objective-C++4 [CKStackLayoutComponent newWithStyle:{ .direction = CKStackLayoutComponentDirectionVertical, } children:{ {[HeaderComponent newWithArticle:article]}, {[MessageComponent newWithArticle:article]}, {[FooterComponent newWithArticle:article]}, }]; 4 http://componentkit.org/docs/why-cpp.html

Slide 36

Slide 36 text

Why Objective-C++ [CKStackLayoutComponent newWithStyle:[[CKStackLayoutComponentStyle alloc] initWithDirection:CKStackLayoutComponentDirectionVertical justifyContent:CKStackLayoutComponentJustifyContentStart alignItems:CKStackLayoutComponentAlignItemsStart spacing:0] children:@[ [CKStackLayoutComponentChild childWithComponent:[HeaderComponent newWithArticle:article] topPadding:0 leftPadding:0 bottomPadding:0], [CKStackLayoutComponentChild childWithComponent:[MessageComponent newWithArticle:article] topPadding:0 leftPadding:0 bottomPadding:0], [CKStackLayoutComponentChild childWithComponent:[FooterComponent newWithArticle:article] topPadding:0 leftPadding:0 bottomPadding:0] ]];

Slide 37

Slide 37 text

Aggregate Initialization CGPoint p1 = (CGPoint){ .x = 3 }; CGPoint p2 = (CGPoint){3, 0};

Slide 38

Slide 38 text

Type Safety — "Objective-C generics"

Slide 39

Slide 39 text

Efficiency

Slide 40

Slide 40 text

Nil Safety NSArray *array = @[@"a", @"b", (NSString *)nil, @"d"]; auto vector = vector{@"a", @"b", nullptr, @"d"};

Slide 41

Slide 41 text

Nil Safety auto vector = vector{@"a", @"b", nullptr, @"d"}; vector.erase(remove_if(begin(vector), end(vector), [](NSString *string) { return string == nullptr; }), end(vector));

Slide 42

Slide 42 text

Nil Safety auto vector = vector{@"a", @"b", nullptr, @"d"}; vector.erase(remove(begin(vector), end(vector), nullptr), end(vector));

Slide 43

Slide 43 text

Nil Safety children:{ headerComponent, messageComponent, attachmentComponent, footerComponent }

Slide 44

Slide 44 text

Nil Safety NSMutableArray *children = [NSMutableArray array]; if (headerComponent) { [children addObject:headerComponent]; } if (messageComponent) { [children addObject:messageComponent]; } if (attachmentComponent) { [children addObject:attachmentComponent]; } if (footerComponent) { [children addObject:footerComponent]; }

Slide 45

Slide 45 text

Inline blocks void (^handler)(NSData *data, NSURLResponse *response, NSError *error) = ^(NSData *data, NSURLResponse *response, NSError *error) { // parse data }; [NSURLSession sharedSession] dataTaskWithURL:URL completionHandler:handler];

Slide 46

Slide 46 text

Inline blocks auto handler = ^(NSData *data, NSURLResponse *response, NSError *error) { // parse data }; [NSURLSession sharedSession] dataTaskWithURL:URL completionHandler:handler];

Slide 47

Slide 47 text

Universal comparison function for value types template inline NSComparisonResult PSPDFCompare(const T value1, const T value2) { if (value1 < value2) return (NSComparisonResult)NSOrderedAscending; else if (value1 > value2) return (NSComparisonResult)NSOrderedDescending; else return (NSComparisonResult)NSOrderedSame; }

Slide 48

Slide 48 text

Operator overloading for CGPoint inline CGPoint operator+(const CGPoint &p1, const CGPoint &p2) { return { p1.x + p2.x, p1.y + p2.y }; } inline CGPoint operator-(const CGPoint &p1, const CGPoint &p2) { return { p1.x - p2.x, p1.y - p2.y }; }

Slide 49

Slide 49 text

Practical Example void CreatePathsForLineEndType(PSPDFLineEndType const endType, CGPoint const* points, NSUInteger const pointsCount, CGFloat const lineWidth, CGPathRef *storedFillPath, CGPathRef *storedStrokePath);

Slide 50

Slide 50 text

Convert raw pointer to a vector reference void CreatePathsForLineEndType(PSPDFLineEndType const endType, std::vector const& points, CGFloat const lineWidth, CGPathRef *storedFillPath, CGPathRef *storedStrokePath); // copy points into a vector auto vector = std::vector(points, points+pointsCount); auto vector = std::vector{point1, point2, point3};

Slide 51

Slide 51 text

Improve the output tuple FillAndStrokePathForLineEndType(PSPDFLineEndType endType, std::vector const& points, CGFloat lineWidth);

Slide 52

Slide 52 text

With custom auto pointers5 tuple, CFPointer> FillAndStrokePathForLineEndType(PSPDFLineEndType endType, std::vector const& points, CGFloat lineWidth); 5 https://gist.github.com/steipete/0f65c234ee843ed514ff

Slide 53

Slide 53 text

// old void CreatePathsForLineEndType(PSPDFLineEndType endType, CGPoint const* points, NSUInteger pointsCount, CGFloat lineWidth, CGPathRef *storedFillPath, CGPathRef *storedStrokePath); // new tuple, CFPointer> FillAndStrokePathForLineEndType(PSPDFLineEndType endType, std::vector const& points, CGFloat lineWidth);

Slide 54

Slide 54 text

Debugging works great

Slide 55

Slide 55 text

Thanks! Peter Steinberger, @steipete References - http://blog.petrzemek.net/2014/12/07/improving-cpp98-code-with-cpp11 - http://componentkit.org/docs/why-cpp.html - http://en.wikipedia.org/wiki/Erase%E2%80%93remove_idiom - http://en.cppreference.com/w/cpp/language/aggregate_initialization - http://stackoverflow.com/questions/3106110/what-are-move-semantics - http://web.archive.org/web/20101203170217/http://developer.apple.com/library/ mac/#/web/20101204020949/http://developer.apple.com/library/mac/documentation/Cocoa/ Conceptual/ObjectiveC/Articles/ocCPlusPlus.html - http://channel9.msdn.com/Events/GoingNative/2013/Cpp-Seasoning - https://developer.apple.com/library/ios/documentation/DeveloperTools/ Conceptual/WhatsNewXcode/Articles/xcode_5_0.html - https://gist.github.com/steipete/0f65c234ee843ed514ff