More in Modern C++
John van Krieken tussen accolades B.V.
{tussen}
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)) {}
John van Krieken tussen accolades B.V.
{tussen}
{tussen}
{tussen}
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?
{tussen}
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); }
{tussen}
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?
{tussen}
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
{tussen}
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)
{tussen}
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)
{tussen}
unique_ptr<T> T* shared_ptr<T>
release() reset() c’tor c’tor replacement for naked *(20) start here
{tussen}
Removed from C++17 including the constructors for unique_ptr and shared_ptr that “steal” ownership from it. Chapter closed!
{tussen}
{tussen}
[] ()->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
{tussen}
Return type of lambda is either supplied with -> type
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");
{tussen}
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
{tussen}
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)?
{tussen}
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
{tussen}
{tussen}
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
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>
{tussen}
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;
{tussen}
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*");
{tussen}
"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]>();
{tussen}
#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> >, "");
{tussen}
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)
{tussen}
{tussen}
#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
{tussen}
auto cwd = fs::current_path(); auto assets = cwd / "040coders" / "assets"; cout << cwd << endl;
"/Users/john/c++"
cout << assets << endl;
"/Users/john/c++/040coders/assets"
{tussen}
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"
{tussen}
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"
{tussen}
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"
{tussen}
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
{tussen}
auto tmpdir = fs::temp_directory_path(); cout << tmpdir << endl; auto tmp = tmpdir / "subdir"; cout << tmp << endl; fs::create_directory(tmp);
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"
ls: /tmp/sgx00000gn/T/subdir: No such file or director
{tussen}
{tussen}
constexpr type deduction (vector v{3, 4, 5}) fold expression (( var + … ))
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]])