More in Modern C++ John van Krieken tussen accolades B.V. {tussen} - - PowerPoint PPT Presentation

more in modern c
SMART_READER_LITE
LIVE PREVIEW

More in Modern C++ John van Krieken tussen accolades B.V. {tussen} - - PowerPoint PPT Presentation

More in Modern C++ John van Krieken tussen accolades B.V. {tussen} Smart pointers Naked * Ownership? {tussen} Pointers in classes struct X { X(): a(new A), b(new B) {} X(const X& src) : a(new A (*src.a)), b(new B (*src.b)) {}


slide-1
SLIDE 1

More in Modern C++

John van Krieken tussen accolades B.V.

{tussen}

slide-2
SLIDE 2

{tussen}

Smart pointers

Naked * Ownership?

slide-3
SLIDE 3

{tussen}

Pointers in classes

struct X { X(): a(new A), b(new B) {} X(const X& src) : a(new A (*src.a)), b(new B (*src.b)) {} X(X&& src) : a(src.a), b(src.b) { src.a = src.b = nullptr; } X& operator= (const X&) = delete; X& operator= (X&&) = delete; ~X() { delete a; delete b: } A *a; B *b; }; Everyone knows how to do this, right?

slide-4
SLIDE 4

{tussen}

unique_ptr

unique_ptr<T> unique_ptr<T[]> unique_ptr<X> clone() const { return unique_ptr<X>(new X(*this)); } auto clone2() const // (14) { return make_unique<X>(*this); }

slide-5
SLIDE 5

{tussen}

Smart pointers in classes

struct X { X(): a(new A), b(new B) {} X(const X& src) : a(new A (*src.a)), b(new B (*src.b)) {} X(X&& src) : a(std::move(src.a)), b(std::move(src.b)){} X& operator= (const X&) = delete; X& operator= (X&&) = default; ~X() = default; std::unique_ptr<A> a; std::unique_ptr<B> b; }; X(X&& src) = default; // unless you have non-movables Need I say more?

slide-6
SLIDE 6

{tussen}

Moving pointers around

class X { X& operator=(const X&) = delete; protected: X(const X&) = default; public: X() = default; X* clone() const { return new X(*this); } }; X x1; auto x2 = x1.clone(); //X x3(x1); // forbidden X x4; //x4 = x1; // forbidden x1.clone(); clone obviously gives ownership memory leak

slide-7
SLIDE 7

{tussen}

Moving ownership

class X { public: unique_ptr<X> clone() const { return unique_ptr<X>(new X(*this)); } [[nodiscard]] auto clone2() const { return make_unique<X>(*this); } } class Y { public: Y() : ptr(nullptr) {} void set(unique_ptr<X>&& p) { ptr = std::move(p); } private: unique_ptr<X> ptr; }; auto x3 = x1.clone2(); Y y1; y1.set(std::move(x3)); y1.set(x1.clone()); x1.clone(); x1.clone2(); destructor called no leak warning [[nodiscard]] (17)

slide-8
SLIDE 8

{tussen}

Shared pointers

shared_ptr<T> shared_ptr<T[]> // (17) shared_ptr<T> s = make_unique<T[]>(new T[n]) // (14) shared_ptr<T[]> s = make_unique<T[]>(new T[n]) // (17)

incompatible! (but logical)

slide-9
SLIDE 9

{tussen}

Interoperability

  • bserver<T>

unique_ptr<T> T* shared_ptr<T>

release() reset() c’tor c’tor replacement for naked *(20) start here

slide-10
SLIDE 10

{tussen}

auto_ptr

Removed from C++17 including the constructors for unique_ptr and shared_ptr that “steal” ownership from it. Chapter closed!

slide-11
SLIDE 11

{tussen}

𝛍-functions

slide-12
SLIDE 12

{tussen}

syntaxis of 𝛍-functions

[] ()->type {}

Captures & : reference = : all by value local=var+4 : by value (14) this : object *this : object copy (17) Parameters (optional, but) auto (14) defaults (14) returns (optional) defaults to type of single return multiple returns allowed (14) body

slide-13
SLIDE 13

{tussen}

return type deduction

Return type of lambda is either supplied with -> type

  • r deduced from the single return in the body.

C++14 relaxes this, so you can have multiple return-statements as long as they have the same type.

auto g_mr(int a) /* ->bool */ { if(a > 7) return true; else return false; }; auto mr = [](int a) { if(a > 7) return true; else return false; }; static_assert(std::is_same<decltype(mr(9)), bool>::value, "multiple return"); static_assert(std::is_same<decltype(g_mr(9)), bool>::value, "function multiple return");

slide-14
SLIDE 14

{tussen}

Mutable & constexpr

auto y = 77; auto mut_l = [y] () mutable { y+=4; cout << y << endl; }; mut_l(); mut_l(); cout << y << endl; 81 85 77 auto cf_t = [](auto a, auto b) constexpr {return a+b;}; static_assert(cf_t(3,4) == 7, "generic lambda”); auto cf = [](int a, int b) constexpr noexcept(true) -> int {return a+b;}; static_assert(cf(3,4) == 7, "constexpr lambda"); [[deprecated(“Yup”)]] auto cf_d = [](int a, int b) constexpr -> int {return a+b;}; static_assert(cf_d(3,4) == 7, "deprecated lambda"); C++17 C++14

slide-15
SLIDE 15

{tussen}

Initialisers and defaults

auto x = 5; auto l = [mine=x+4](auto a, string b="Hallo"s) { cout << a << ' ' << b << ' ' << mine << endl; }; l(3); l(3.4, "seven"); 3 Hallo 9 3.4 seven 9

auto with default value doesn’t work (for me)?

slide-16
SLIDE 16

{tussen}

Templated lambdas (C++20)

auto templated_lambda = []<typename T>(T, T, auto){}; templated_lambda(3, 4, "Hello"s); // templated_lambda(3, 4.5, "Hello"s);

wrong: 3 and 4.5 are of different types

slide-17
SLIDE 17

{tussen}

Meta programming

slide-18
SLIDE 18

{tussen}

Meta functions

meta_fct<A> meta_fct<A>::type mate_fct<A>::value template <typename T> using f_t<T> = typename f<T>::type; // (14) template <typename T> using f_v = f<T>::value; // (17)

typename is a nuisance more

  • rthogonal

for meta-functions with value, that value is wrapped in integral_constant<int, 7>. for predicates: is_… true_type, integral_constant<bool, true> false_type, integral_constant<bool, false>

slide-19
SLIDE 19

{tussen}

Type computations

typename std::add_pointer<T>::type t_ptr = &t; std::add_pointer_t<T> t_ptr2 = &t; static_assert(std::is_same<decltype(t_ptr), T*>::value, ""); static_assert(std::is_same_v<decltype(t_ptr2), T*>, ""); // think template <typename T> … T t;

slide-20
SLIDE 20

{tussen}

Conditionals

template <typename T> struct add_pointer_if { using type = std::conditional_t<std::is_pointer_v<T>, T, T*>; }; template <typename T> using add_pointer_if_t = typename add_pointer_if<T>::type; static_assert(std::is_same<add_pointer_if_t<int>, int*>::value, "int -> int*"); static_assert(std::is_same_v<add_pointer_if<int*>::type, int*>, "int* == int*");

slide-21
SLIDE 21

{tussen}

SFINA

"Substitution Failure Is Not An Error"

template<typename T, typename …Types> typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type make_unique(Types&& …args){ return std::unique_ptr<T> (new T(std::forwad<Type>(args)…)); } template <typename T> typename std::enable_if<std::is_array<T>::value && std::extend<T>::value == 0, std::unique_ptr<T>>::type make_unique(size_t size){ using Elem = typename std::remove_extend<T>::type; return std::unique_ptr<T[]> (new Elem[size]); } template<typename T, typename …Types> typename std::enable_if<std::extent<T>::value != 0, std::unique_ptr<T>>::type make_unique(Types&& …args) = delete; make_unique<T>(x, y,…); make_unique<T[]>(7); make_unique<T[7]>();

slide-22
SLIDE 22

{tussen}

boost.hana

#include <boost/hana.hpp> namespace hana = boost::hana; struct Bird { std::string name; }; struct Fish { std::string name; }; struct Cat { std::string name; }; auto animals = hana::make_tuple(Bird{"Tweety"}, Fish{"Wanda"}, Cat{"Loki"}); auto anders = hana::reverse(animals); static_assert(std::is_same_v< decltype(anders) , hana::tuple<Cat, Fish, Bird> >, "");

slide-23
SLIDE 23

{tussen}

Hana types are objects

auto four = hana::int_c<4>; using namespace hana::literals; static_assert(four == 4_c, “int_c<N> == N_c”); static_assert(four + 3_c == 7_c, "adding"); Template variable (14)

slide-24
SLIDE 24

{tussen}

Filesystem library

slide-25
SLIDE 25

{tussen}

Paths and functions

#include <experimental/filesystem> namespace fs = std::experimental::filesystem; using namespace std::literals::string_literals; using namespace std; fs::path: file name manipulation fs::functions: manipulate files and directories

slide-26
SLIDE 26

{tussen}

Path manipulations

auto cwd = fs::current_path(); auto assets = cwd / "040coders" / "assets"; cout << cwd << endl;

"/Users/john/c++"

cout << assets << endl;

"/Users/john/c++/040coders/assets"

slide-27
SLIDE 27

{tussen}

Path components

fs::path src("fs.cpp"); cout << src << endl; src.replace_extension(); cout << src << endl; src.replace_extension(".o"); cout <<src << endl;

Source: "fs.cpp" Basename: "fs" Object: "fs.o"

absolute(src): "/Users/john/c++/fs.o" root_name: "" root_directory: "/" root_path: "/" relative_path: "Users/john/c++/fs.o" parent_path: "/Users/john/c++" filename: "fs.o" stem: "fs" extension: ".o" For loop: “/Users/john/c++/fs.o" "/" "Users" "john" "c++" "fs.o"

slide-28
SLIDE 28

{tussen}

Directory listings

fs::directory_iterator cur_dir(cwd); fs::directory_iterator no_file; for(auto f: cur_dir){ cout << f << endl; } for_each(begin(cur_dir), end(cur_dir), [](const auto& f) { cout << f << endl; });

"/Users/john/c++/clone" "/Users/john/c++/clone.cpp" "/Users/john/c++/clone.dSYM" "/Users/john/c++/fs" "/Users/john/c++/fs.cpp" "/Users/john/c++/fs.dSYM"

slide-29
SLIDE 29

{tussen}

Recursive listings

fs::recursive_directory_iterator cur_r(cwd); for(fs::directory_entry f: cur_r){ cout << f << endl; }

"/Users/john/c++/clone" "/Users/john/c++/clone.cpp" "/Users/john/c++/clone.dSYM" "/Users/john/c++/clone.dSYM/Contents" "/Users/john/c++/clone.dSYM/Contents/Info.plist" "/Users/john/c++/clone.dSYM/Contents/Resources" "/Users/john/c++/clone.dSYM/Contents/Resources/DWARF" "/Users/john/c++/clone.dSYM/Contents/Resources/DWARF/clone" "/Users/john/c++/fs" "/Users/john/c++/fs.cpp" "/Users/john/c++/fs.dSYM" "/Users/john/c++/fs.dSYM/Contents"

slide-30
SLIDE 30

{tussen}

File attributes

fs::is_block_file(const fs::path&) fs::is_character_file fs::is_directory fs::is_empty fs::status_known fs::is_fifo fs::is_other fs::is_regular_file fs::is_socket fs::is_symlink Also available as member functions of fs::directory_entry (no luck with my compilers) fs::directory_entry converts to fs::path

slide-31
SLIDE 31

{tussen}

Temporary files

auto tmpdir = fs::temp_directory_path(); cout << tmpdir << endl; auto tmp = tmpdir / "subdir"; cout << tmp << endl; fs::create_directory(tmp);

  • fstream tmp_out(tmp / “out.txt"); tmp_out.close();

auto cmd = "ls -R “s + tmp.c_str(); system(cmd.c_str()); fs::remove_all(tmp); system(cmd.c_str());

Tmpdir: “/tmp/sgx00000gn/T/“ Append: “/tmp/sgx00000gn/T/subdir"

  • ut.txt

ls: /tmp/sgx00000gn/T/subdir: No such file or director

slide-32
SLIDE 32

{tussen}

Questions?

slide-33
SLIDE 33

{tussen}

Bonus

constexpr type deduction (vector v{3, 4, 5}) fold expression (( var + … ))

  • ptional, variant, any

structured binding (auto [a, b] = make_tuple(6, 8.7);) init statements (if) compile time if (if constexpr) string views nested namespaces (namespace A::B::C) template variables (hana::int_c) fall through attribute ([[fallthrough]])