C++17 and Beyond. Mark Isaacson

Similar documents
Fundamentals of Type-Dependent Code Reuse in C++ Mark Isaacson

Source-Code Information Capture

Elevate your Code to Modern C++ with Automated Tooling. Peter Sommerlad

6.S096 Lecture 4 Style and Structure

From Java to C++ From Java to C++ CSE250 Lecture Notes Weeks 1 2, part of 3. Kenneth W. Regan University at Buffalo (SUNY) September 10, 2009

Lecture 2 Polymorphism, Traits, Policies, and Inheritance

Advanced Systems Programming

Friendship in Service of Testing

Wentworth Institute of Technology COMP201 Computer Science II Spring 2015 Derbinsky. C++ Kitchen Sink. Lecture 14.

The Set of Natural Code. Mark Isaacson

QStringView. everywhere. Marc Mutz, Senior Software Engineer at KDAB

Programming Abstractions

Linked List using a Sentinel

Agenda. The main body and cout. Fundamental data types. Declarations and definitions. Control structures

C The new standard

Pointers, Dynamic Data, and Reference Types

An Introduction to Template Metaprogramming

Value Semantics and Concept Based Polymorphism Sean Parent Principal Scientist Adobe Systems Incorporated. All Rights Reserved.

Bind Returned/Initialized Objects to the Lifetime of Parameters, Rev0

05-01 Discussion Notes

A Proposal to Add a Logical Const Wrapper to the Standard Library Technical Report

A Proposal to Add a Const-Propagating Wrapper to the Standard Library

Debug C++ Without Running. Anastasia Kazakova

std::optional from Scratch

1d: tests knowing about bitwise fields and union/struct differences.

Intermediate Programming, Spring 2017*

C++ Pub Quiz. A 90 minute quiz session ACCU April by Olve Maudal, with Lars Gullik Bjønnes. Sponsored by:

Introduction to Linked Lists. Introduction to Recursion Search Algorithms CS 311 Data Structures and Algorithms

Making New Pseudo-Languages with C++

C++ Programming: Polymorphism

Polymorphism. Zimmer CSCI 330

III. Classes (Chap. 3)

COSC 320 Exam 2 Key Spring Part 1: Hash Functions

POLYMORPHISM 2 PART. Shared Interface. Discussions. Abstract Base Classes. Abstract Base Classes and Pure Virtual Methods EXAMPLE

POLYMORPHISM 2 PART Abstract Classes Static and Dynamic Casting Common Programming Errors

MODERN AND LUCID C++ ADVANCED

CS

Midterm Review. PIC 10B Spring 2018

TDDD38 - Advanced programming in C++

Software Engineering Concepts: Invariants Silently Written & Called Functions Simple Class Example

Logistics. Templates. Plan for today. Logistics. A quick intro to Templates. A quick intro to Templates. Project. Questions? Introduction to Templates

Lambda functions. Zoltán Porkoláb: C++11/14 1

Compiler aided optimization of the pimpl-idiom

a data type is Types

Modern and Lucid C++ Advanced for Professional Programmers. Part 12 Advanced Library Design. Department I - C Plus Plus Advanced

More on Templates. Shahram Rahatlou. Corso di Programmazione++

04-24/26 Discussion Notes

C++17. Antony Polukhin Полухин Антон

Structured Data. CIS 15 : Spring 2007

C++14 (Preview) Alisdair Meredith, Library Working Group Chair. Thursday, July 25, 13

Homework 4. Any questions?

STRICT_VARIANT. A simpler variant in C++ Chris Beck

Modern C++, From the Beginning to the Middle. Ansel Sermersheim & Barbara Geller ACCU / C++ November 2017

Introduction to C++11 and its use inside Qt

Exercise 6.2 A generic container class

boost::enable_if Deep Down Boostimagical Fun Christian Bay and Kasper A Andersen Department of Computer Science University of Copenhagen

Homework 5. Yuji Shimojo CMSC 330. Instructor: Prof. Reginald Y. Haseltine

Value categories. PRvalues. Lvalues

Engineering Tools III: OOP in C++

Intermediate Programming & Design (C++) Classes in C++

Advanced C++ 4/13/2017. The user. Types of users. Const correctness. Const declaration. This pointer and const.

The following is an excerpt from Scott Meyers new book, Effective C++, Third Edition: 55 Specific Ways to Improve Your Programs and Designs.

Operating Systems CMPSCI 377, Lec 2 Intro to C/C++ Prashant Shenoy University of Massachusetts Amherst

I m sure you have been annoyed at least once by having to type out types like this:

Remedial C Now that we can actually use it Pete Williamson

Intermediate Programming, Spring 2017*

An application: foreign function bindings

Design Patterns in C++

B-Trees. nodes with many children a type node a class for B-trees. an elaborate example the insertion algorithm removing elements

Creating Templates and Implementing Smart Pointers CS193D 2/27/06

C++ Programming Lecture 4 Software Engineering Group

CSCI-1200 Data Structures Spring 2018 Lecture 8 Templated Classes & Vector Implementation

The C++ Type System is your Friend

Software Development with C++ Templates

6 Architecture of C++ programs

Const Correctness. Ali Malik

Templates. Zoltán Porkoláb: C++11/14 1

Graphs. directed and undirected graphs weighted graphs adjacency matrices. abstract data type adjacency list adjacency matrix

A brief introduction to C programming for Java programmers

UNDEFINED BEHAVIOR IS AWESOME

Using Enum Structs as Bitfields

Improving the Return Value of Erase-Like Algorithms

Variant: a typesafe union. ISO/IEC JTC1 SC22 WG21 N4218

C++14 Reflections Without Macros, Markup nor External Tooling

COMP 2355 Introduction to Systems Programming

EL2310 Scientific Programming

COEN244: Class & function templates

Overload Resolution. Ansel Sermersheim & Barbara Geller Amsterdam C++ Group March 2019

Java Basic Syntax. Java vs C++ Wojciech Frohmberg / OOP Laboratory. Poznan University of Technology

Design Patterns in C++

Type Erasure. Nevin :-) Liber Friday, October 29, Chicago C/C++ Users Group Nevin J. Liber All Rights Reserved.

GEA 2017, Week 4. February 21, 2017

Rvalue References, Move Semantics, Universal References

A polymorphic value-type for C++

CSE 303: Concepts and Tools for Software Development

P1267R0: Custom Constraint Diagnostics

September 19,

GridKa School 2013: Effective Analysis C++ Templates

Smart Pointers, deleted functions, and 2-3 trees

CSCI 104 Templates. Mark Redekopp David Kempe

Transcription:

C++17 and Beyond Mark Isaacson 1

Roadmap What s coming in C++17 and C++20 The surprising utility of std::string_view C++20 s most deliciously scary feature: operator dot Making templates more accessible with if constexpr 2

What made it to C++17 Filesystem TS Special Math TS Parallelism TS if constexpr [[fallthrough]] [[nodiscard]] logical operator type traits variable templates polymorphic allocators removed exception specifications Type deduction for constructors Stronger evaluation order Structured bindings Library Fundamentals 1 TS: std::not_fn std::string_view std::any (unconstrained) std::variant (constrained) std::optional std::shared_ptr for arrays std::uncaught_exceptions std::invoke std::apply 3

C++20 Horizon Concurrency TS Transactional Memory TS Concepts TS Ranges TS Networking TS Library Fundamentals 2 TS Parallelism 2 TS Coroutine TS Numerics TS Reflection TS Modules TS Operator dot Longer? Concurrency 2 TS 2D Graphics TS Automatic comparison operators 4

Now the fun stuff What s coming in C++17 and C++20 The surprising utility of std::string_view C++17 s most deliciously scary feature: operator dot Making templates more accessible with if constexpr 5

Subtle Bug // Foo.h #include <string> extern const string kfoo; // main.cpp #include "Foo.h" const string kbar = kfoo; // Foo.cpp #include "Foo.h" const string kfoo = "foo"; int main() { return 0; 6

Good News This is automatically detectable Best practices avoid this entirely (for string constants) ASAN_OPTIONS=check_initialization_order=1:strict_init_order=1: detect_odr_violation=1 7

Pre-C++17 // Foo.h extern const char* const kfoo; // main.cpp #include "Foo.h" const char* const kbar = kfoo; // Foo.cpp #include "Foo.h" const char* const kfoo = "foo"; int main() { return 0; 8

Post-C++17 // Foo.h #include <string_view> const constexpr string_view kfoo = "foo"; // main.cpp #include "Foo.h" const constexpr string_view kbar = kfoo; int main() { return 0; 9

Safety & Convenience It knows its size() It works cleanly with the STL String comparisons are always intuitive const char* const kfoo = "foo"; const constexpr string_view kfoo2 = "foo"; assert(kfoo == "foo"); // Oops assert(kfoo2 == "foo"); // Ok assert(kfoo2 == kfoo); // Ok 10

Performance void foo(const string& x); void bar(string_view x); string a = "hello"; const char* const b = "world"; foo(a); foo(b); bar(a); bar(b); 11

Performance // main string x = "hello"; Widget w; w.foo(x); struct Widget { unordered_map<string, int> mymap; void foo(/*??? */ intermediate) { return mymap.find(intermediate)!== mymap.end(); ; 12

Performance // main string x = "hello"; Widget w; w.foo(x); struct Widget { unordered_map<string, int> mymap; void foo(const string& intermediate) { return mymap.find(intermediate)!== mymap.end(); ; 13

Performance // main string x = "hello"; Widget w; w.foo(x); struct Widget { unordered_map<string, int> mymap; void foo(string_view intermediate) { return mymap.find(intermediate)!== mymap.end(); ; 14

...big caveat I must explain the dangers 15

Operator Dot struct IntProxy { int& operator.() { return value; int value = 0; ; IntProxy x; x = 5; x += 5; cout << x << endl; 16

Operator Dot struct IntProxy { int& operator.() { return value; int value = 0; ; IntProxy x; x = 5; x += 5; cout << x << endl; "Lowers" to x.operator+=(5); 17

Operator Dot struct IntProxy { int& operator.() { return value; string tostring() { return to_string(value); int value = 0; ; IntProxy x; x = 5; x += 5; cout << x << endl; string msg = "The magic number is " + x.tostring(); 18

Contracts w/ Operator Dot Goal: an int with the invariant: 0 <= x <= 100 BoundedInt x = 5; x += 5; //Ok x = 1000; //Error, exceeded bound of 100 19

Contracts w/ Operator Dot struct BoundedInt { int& operator.() { return val; int val = 0; ; 20

Preconditions w/ Operator Dot struct BoundedInt { int& operator.() { return val; int val = 0; ; 21

Preconditions w/ Operator Dot struct BoundedInt { int& operator.() { if (val < 0 val > 100) throw exception{"boundserror"; return val; int val = 0; ; 22

End of Life Condtions struct BoundedInt { ~BoundedInt() { if (val < 0 val > 100) LOG(ERROR) << "BoundsError"; int& operator.() {return val; int val = 0; ; 23

Postconditions w/ Operator Dot struct BoundedInt { Impl operator.() {return Impl{val; int val = 0; ; struct Impl { Impl(int& x): ref{x {; ~Impl() { if (ref < 0 ref > 100) LOG(ERROR) << "BoundsError"; // Example use: BoundedInt x = 5; x += 5; //Ok x = 1000; //Error int& operator.() {return ref; int& ref; ; 24

Postconditions w/ Operator Dot struct BoundedInt { Impl operator.() {return Impl{val; int val = 0; ; 2 4 struct Impl { Impl(int& x): ref{x {; ~Impl() { if (ref < 0 ref > 100) LOG(ERROR) << "BoundsError"; // Example use: BoundedInt x = 5; x += 5; //Ok x = 1000; //Error 1 3 int& operator.() {return ref; int& ref; ; 25

Postconditions w/ Operator Dot struct BoundedInt { Impl operator.() {return Impl{val; int val = 0; ; // Example use: BoundedInt x = 5; x += 5; //Ok x = 1000; //Error struct Impl { Impl(int& x): ref{x,copy{x {; ~Impl() { if (copy < 0 copy > 100) LOG(ERROR) << "BoundsError"; else { ref = copy; int& operator.() {return copy; int& ref; int copy; ; 26

Operator Dot Potential uses I won't outline: Smart references Pimpl idiom Proxies/Mixins (add operators) - see my other talk :) 27

Operator Dot vs Inheritance Can extend primitive types (like int) No notion of final or protected Wrapped type can't call Wrapper's functions (no NVI pattern) 28

Compile-time branching template<typename T> struct default_delete { void operator()(t* ptr) const { delete ptr; ; template<typename T> struct default_delete<t[]> { template<typename U> void operator()(u* ptr) const { delete[] ptr; ; 29

Compile-time branching template<typename T> struct default_delete { void operator()(t* ptr) const { delete ptr; ; template<typename T> struct default_delete<t[]> { template<typename U> void operator()(u* ptr) const { delete[] ptr; ; 30

Compile-time branching template<typename T> struct default_delete { template<typename U> void operator()(u* ptr) const { if (is_array<t>::value) { delete[] ptr; else { delete ptr; ; 31

Compile-time branching constexpr bool example1 = conjunction(true); // true constexpr bool example2 = conjunction(false); // false constexpr bool example3 = conjunction(true, true); // true constexpr bool example4 = conjunction(true, false, true); // false 32

Compile-time branching template<typename Bool> constexpr bool conjunction(bool&& b) { return b; template<typename Bool, typename... Rest> constexpr bool conjunction(bool&& b, Rest&&... rest) { return b && conjunction(std::forward<rest>(rest)...); constexpr bool enabled = conjunction(true, false, true); 33

Compile-time branching template<typename Bool> constexpr bool conjunction(bool&& b) { return b; template<typename Bool, typename... Rest> constexpr bool conjunction(bool&& b, Rest&&... rest) { return b && conjunction(std::forward<rest>(rest)...); constexpr bool enabled = conjunction(true, false, true); 34

Compile-time branching template<typename Bool, typename... Rest> constexpr bool conjunction(bool&& b, Rest&&... rest) { if constexpr(sizeof...(rest)) { return b && conjunction(std::forward<rest>(rest)...); else { return b; constexpr bool enabled = conjunction(true, false, true); 35

Why if constexpr? template<typename Bool, typename... Rest> constexpr bool conjunction(bool&& b, Rest&&... rest) { if (sizeof...(rest)) { return b && conjunction(std::forward<rest>(rest)...); else { return b; constexpr bool enabled = conjunction(true); 36

Fold Expressions template<typename Bool, typename... Rest> constexpr bool conjunction(bool&& b, Rest&&... rest) { return b &&...; constexpr bool enabled = conjunction(true, false, true); 37

if constexpr vs Concepts if constexpr => Template branching Concepts => Template constraints 38

Design by Introspection template<typename ITR> void advance(itr& itr, size_t n) { using C = typename iterator_traits<itr>::iterator_category; if constexpr(is_same_v<c, random_access_iterator_tag>) { itr += n; else { for (auto i = 0u; i < n; ++i) ++itr; 39

if constexpr in C++14 IF_CONSTEXPR(true, { cout << "hi"; ); template<bool b, typename F> struct CallIfImpl { ; CallIfImpl(F func) { template<typename F> struct CallIfImpl<true, F> { CallIfImpl(F func) { ; func( ); 40

if constexpr in C++14 IF_CONSTEXPR(true, { cout << "hi"; ); template<bool b, typename F> void callif(f&& func) { CallIfImpl<b, F>{forward<F>(func); template<bool b, typename F> struct CallIfImpl { ; CallIfImpl(F func) { template<typename F> struct CallIfImpl<true, F> { CallIfImpl(F func) { ; func( ); 41

if constexpr in C++14 IF_CONSTEXPR(true, { cout << "hi"; ); template<bool b, typename F> void callif(f&& func) { CallIfImpl<b, F>{forward<F>(func); #define IF_CONSTEXPR(condition, code) \ callif<condition>([&](auto) code); template<bool b, typename F> struct CallIfImpl { ; CallIfImpl(F func) { template<typename F> struct CallIfImpl<true, F> { CallIfImpl(F func) { auto dummyargument = true; func(dummyargument); ; 42

Review string_view provides correctness, efficiency, and interoperability Operator dot is black magic if constexpr makes branching templates easy 43

return 0; Mark Isaacson http://modernmaintainablecode.com 44