Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Type Safe C++? - LOL! :-)

Type Safe C++? - LOL! :-)

So called "strong types", genuinely type safe alternatives to "typedef:s" are often seen as a way to prevent bugs, but they can also be used to improve clarity in your code, and even increase performance. It is underappreciated how strong the type safety guarantees in C++ are, because it takes knowledge and a bit of discipline to make use of it.

In this session, I give motivating examples for why strong types are good, and present some of the techniques for creating them. The simplest techniques requires no library support, but I will also show some more sophisticated solutions from open source libraries available on github. We will go through what happens with both production code and test code when you use them, and also discuss the pros and cons of the different approaches.

Björn Fahller

April 14, 2018
Tweet

More Decks by Björn Fahller

Other Decks in Programming

Transcript

  1. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 1/144 Type Safe C++? - LOL! :-) Björn Fahller
  2. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 2/144 Type Safe C++? - LOL! :-) Björn Fahller
  3. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 3/144 Type Safe C++? - LOL! :-) What is type safety?
  4. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 4/144 What is type safety? type safety (Noun) the extent to which a programming language discourages or prevents type errors -- Wiktionary
  5. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 5/144 A type safe system discourages or prevents... • ... use of one type when another is intended • ... operations that do not make sense • ... use of values outside the defined space
  6. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 6/144 • Introduction to type safety • Type safety in C++ • Simple library solution for strong types • Sophisticated libraries – scouting github! • What strong types does with your code Type Safe C++? - LOL! :-)
  7. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 7/144 using request_id = uint32_t; using receiver_id = uint32_t; token remove(request_id req, receiver_id rec); token initiate_remove(receiver_id receiver) { auto req = new_request(); return remove(receiver, req); } My story begins
  8. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 8/144 using request_id = uint32_t; using receiver_id = uint32_t; token remove(request_id req, receiver_id rec); token initiate_remove(receiver_id receiver) { auto req = new_request(); return remove(receiver, req); } My story begins
  9. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 9/144 using request_id = uint32_t; using receiver_id = uint32_t; token remove(request_id req, receiver_id rec); token initiate_remove(receiver_id receiver) { auto req = new_request(); return remove(receiver, req); } My story begins
  10. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 10/144 void other(A const& a); void func(B b) { other(b); } When is this call allowed?
  11. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 11/144 using A = double; using B = enum { aa, bb, cc }; void other(A const& a); void func(B b) { other(b); }
  12. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 12/144 struct A { int value; }; struct B { int value; }; void other(A const& a); void func(B b) { other(b); }
  13. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 13/144 struct A { int value; }; struct B { int value; }; void other(A const& a); void func(B b) { other(b); } If we want this to compile, we can add:
  14. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 14/144 struct A { int value; }; struct B { int value; }; void other(A const& a); void func(B b) { other(b); } If we want this to compile, we can add: A::A(B const&); // not explicit
  15. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 15/144 struct A { int value; }; struct B { int value; }; void other(A const& a); void func(B b) { other(b); } If we want this to compile, we can add: A::A(B const&); // not explicit B::operator A(); // not explicit
  16. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 16/144 struct A { int value; }; struct B { int value; }; void other(A const& a); void func(B b) { other(b); } If we want this to compile, we can add: A::A(B const&); // not explicit B::operator A(); // not explicit A as a public base class to B
  17. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 17/144 struct request_id { uint32_t value; }; struct receiver_id { uint32_t value; }; token remove(request_id req, receiver_id rec); token initiate_remove(receiver_id receiver) { request_id req = new_request(); return remove(receiver, req); } A different story begins
  18. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 18/144 struct request_id { uint32_t value; }; struct receiver_id { uint32_t value; }; token remove(request_id req, receiver_id rec); token initiate_remove(receiver_id receiver) { request_id req = new_request(); return remove(receiver, req); } error: no matching function for call to 'remove' return remove(receiver, req); ^~~~~~ note: candidate function not viable: no known conversion from 'receiver_id' to 'request_id' for 1st argument token remove(request_id req, receiver_id rec); ^
  19. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 19/144 We have control over when the compiler will allow a conversion!
  20. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 20/144 class receiver_id { public: explicit receiver_id(uint32_t v) : value{v} {} operator uint32_t() const { return value; } private: uint32_t value; };
  21. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 21/144 class receiver_id { public: explicit receiver_id(uint32_t v) : value{v} {} operator uint32_t() const { return value; } bool operator==(receiver_id v) const { return value == v.value; } bool operator!=(receiver_id v) const; private: uint32_t value; };
  22. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 22/144 class receiver_id { public: explicit receiver_id(uint32_t v) : value{v} {} operator uint32_t() const { return value; } bool operator==(receiver_id v) const { return value == v.value; } bool operator!=(receiver_id v) const; bool operator<(receiver_id v) const; ... private: uint32_t value; };
  23. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 23/144 class receiver_id { public: explicit receiver_id(uint32_t v) : value{v} {} operator uint32_t() const { return value; } bool operator==(receiver_id v) const { return value == v.value; } bool operator!=(receiver_id v) const; bool operator<(receiver_id v) const; ... private: uint32_t value; }; enum class receiver_id : uint32_t {};
  24. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 24/144 class receiver_id { public: explicit receiver_id(uint32_t v) : value{v} {} operator uint32_t() const { return value; } bool operator==(receiver_id v) const { return value == v.value; } bool operator!=(receiver_id v) const; bool operator<(receiver_id v) const; ... private: uint32_t value; }; enum class receiver_id : uint32_t {};
  25. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 25/144 class receiver_id { public: explicit receiver_id(uint32_t v) : value{v} {} operator uint32_t() const { return value; } bool operator==(receiver_id v) const { return value == v.value; } bool operator!=(receiver_id v) const; bool operator<(receiver_id v) const; ... private: uint32_t value; }; enum class receiver_id : uint32_t {};
  26. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 26/144 class receiver_id { public: explicit receiver_id(uint32_t v) : value{v} {} operator uint32_t() const { return value; } bool operator==(receiver_id v) const { return value == v.value; } bool operator!=(receiver_id v) const; bool operator<(receiver_id v) const; ... private: uint32_t value; }; enum class receiver_id : uint32_t {};
  27. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 27/144 class receiver_id { public: explicit receiver_id(uint32_t v) : value{v} {} operator uint32_t() const { return value; } bool operator==(receiver_id v) const { return value == v.value; } bool operator!=(receiver_id v) const; bool operator<(receiver_id v) const; ... private: uint32_t value; }; enum class receiver_id : uint32_t {};
  28. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 28/144 class receiver_id { public: explicit receiver_id(uint32_t v) : value{v} {} operator uint32_t() const { return value; } bool operator==(receiver_id v) const { return value == v.value; } bool operator!=(receiver_id v) const; bool operator<(receiver_id v) const; ... private: uint32_t value; }; enum class receiver_id : uint32_t {};
  29. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 29/144 class receiver_id { public: explicit receiver_id(uint32_t v) : value{v} {} operator uint32_t() const { return value; } bool operator==(receiver_id v) const { return value == v.value; } bool operator!=(receiver_id v) const; bool operator<(receiver_id v) const; ... private: uint32_t value; };
  30. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 30/144 class receiver_id { public: explicit receiver_id(uint32_t v) : value{v} {} operator uint32_t() const { return value; } bool operator==(receiver_id v) const { return value == v.value; } bool operator!=(receiver_id v) const; bool operator<(receiver_id v) const; ... private: uint32_t value; }; There’s an awful lot of boiler plate code here!
  31. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 31/144 class receiver_id { public: explicit receiver_id(uint32_t v) : value{v} {} operator uint32_t() const { return value; } bool operator==(receiver_id v) const { return value == v.value; } bool operator!=(receiver_id v) const; bool operator<(receiver_id v) const; ... private: uint32_t value; }; There’s an awful lot of boiler plate code here! Repeat once more for request_id
  32. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 32/144 • Introduction to type safety • Type safety in C++ • Simple library solution for strong types • Sophisticated libraries – scouting github! • What strong types does with your code Type Safe C++? - LOL! :-)
  33. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 33/144 template <typename T, typename tag> class safe_type { public: private: T value_; };
  34. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 34/144 template <typename T, typename tag> class safe_type { public: safe_type(T t) : value_(std::move(t)) {} operator T() const { return value_; } // operators... private: T value_; };
  35. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 35/144 template <typename T, typename tag> class safe_type { public: safe_type(T t) : value_(std::move(t)) {} template <typename T2, typename tag2> safe_type(safe_type<T2, tag2> const&) = delete; operator T() const { return value_; } // operators... private: T value_; };
  36. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 36/144 template <typename T, typename tag> class safe_type { public: safe_type(T t) : value_(std::move(t)) {} template <typename T2, typename tag2> safe_type(safe_type<T2, tag2> const&) = delete; operator T() const { return value_; } // operators... private: T value_; }; using int1 = safe_type<int, struct int1_>; using int2 = safe_type<int, struct int2_>;
  37. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 37/144 using request_id = safe_type<uint32_t, struct request_id_tag>; using receiver_id = safe_type<uint32_t, struct receiver_id_tag>; token remove(request_id req, receiver_id rec); token initiate_remove(receiver_id receiver) { auto req = new_request(); return remove(receiver, req); }
  38. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 38/144 using request_id = safe_type<uint32_t, struct request_id_tag>; using receiver_id = safe_type<uint32_t, struct receiver_id_tag>; token remove(request_id req, receiver_id rec); token initiate_remove(receiver_id receiver) { auto req = new_request(); return remove(receiver, req); }
  39. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 39/144 using request_id = safe_type<uint32_t, struct request_id_tag>; using receiver_id = safe_type<uint32_t, struct receiver_id_tag>; token remove(request_id req, receiver_id rec); token initiate_remove(receiver_id receiver) { auto req = new_request(); return remove(receiver, req); }
  40. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 40/144 using request_id = safe_type<uint32_t, struct request_id_tag>; using receiver_id = safe_type<uint32_t, struct receiver_id_tag>; token remove(request_id req, receiver_id rec); token initiate_remove(receiver_id receiver) { auto req = new_request(); return remove(receiver, req); } error: no matching function for call to 'remove' remove(receiver, req); ^~~~~~ note: candidate function not viable: no known conversion from 'safe_type<[...], struct receiver_id_tag>' to 'safe_type<[...], struct request_id_tag>' for 1st argument token remove(request_id req, receiver_id rec); ^
  41. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 41/144 using request_id = safe_type<uint32_t, struct request_id_tag>; using receiver_id = safe_type<uint32_t, struct receiver_id_tag>; token remove(request_id req, receiver_id rec); token initiate_remove(receiver_id receiver) { auto req = new_request(); return remove(receiver, req); }
  42. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 42/144 struct request_id : safe_type<uint32_t, request_id> { using safe_type::safe_type; }; struct receiver_id : safe_type<uint32_t, receiver_id> { using safe_type::safe_type; }; token remove(request_id req, receiver_id rec); token initiate_remove(receiver_id receiver) { auto req = new_request(); return remove(receiver, req); }
  43. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 43/144 struct request_id : safe_type<uint32_t, request_id> { using safe_type::safe_type; }; struct receiver_id : safe_type<uint32_t, receiver_id> { using safe_type::safe_type; }; token remove(request_id req, receiver_id rec); token initiate_remove(receiver_id receiver) { auto req = new_request(); return remove(receiver, req); } error: no matching function for call to 'remove' remove(receiver, req); ^~~~~~ note: candidate function not viable: no known conversion from 'receiver_id' to 'request_id' for 1st argument token remove(request_id req, receiver_id rec); ^
  44. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 44/144 struct request_id : safe_type<uint32_t, request_id> { using safe_type::safe_type; }; struct receiver_id : safe_type<uint32_t, receiver_id> { using safe_type::safe_type; }; token remove(request_id req, receiver_id rec); token initiate_remove(receiver_id receiver) { auto req = new_request(); return remove(receiver, req); } #define SAFE_TYPE(name, base_type) \ struct name : safe_type<base_type, name> { \ using safe_type::safe_type; \ }
  45. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 45/144 SAFE_TYPE(request_id, uint32_t); SAFE_TYPE(receiver_id, uint32_t); token remove(request_id req, receiver_id rec); token initiate_remove(receiver_id receiver) { auto req = new_request(); return remove(receiver, req); } #define SAFE_TYPE(name, base_type) \ struct name : safe_type<base_type, name> { \ using safe_type::safe_type; \ }
  46. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 46/144 SAFE_TYPE(interface_name, std::string); SAFE_TYPE(customer_name, std::string); void label_interface(interface_name const& ifname, customer_name const& customer); interface_name lookup_interface(MAC_address mac); void setup_customer(MAC_address mac, customer_name const& customer) { assert(!customer.empty()); auto if_name = lookup_interface(mac); assert(if_name.find(':') != std::string::npos); label_interface(customer, if_name); }
  47. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 47/144 SAFE_TYPE(interface_name, std::string); SAFE_TYPE(customer_name, std::string); void label_interface(interface_name const& ifname, customer_name const& customer); interface_name lookup_interface(MAC_address mac); void setup_customer(MAC_address mac, customer_name const& customer) { assert(!customer.empty()); auto if_name = lookup_interface(mac); assert(if_name.find(':') != std::string::npos); label_interface(customer, if_name); }
  48. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 48/144 SAFE_TYPE(interface_name, std::string); SAFE_TYPE(customer_name, std::string); void label_interface(interface_name const& ifname, customer_name const& customer); interface_name lookup_interface(MAC_address mac); void setup_customer(MAC_address mac, customer_name const& customer) { assert(!customer.empty()); auto if_name = lookup_interface(mac); assert(if_name.find(':') != std::string::npos); label_interface(customer, if_name); } Accidental swap!
  49. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 49/144 SAFE_TYPE(interface_name, std::string); SAFE_TYPE(customer_name, std::string); void label_interface(interface_name const& ifname, customer_name const& customer); interface_name lookup_interface(MAC_address mac); void setup_customer(MAC_address mac, const customer_name& customer) { assert(!customer.empty()); auto if_name = lookup_interface(mac); assert(if_name.find(':') != std::string::npos); label_interface(customer, if_name); } Accidertal swap! template <typename T, typename tag, bool = std::is_class<T>{} && !std::is_final<T>{}> class safe_type { /* as before */};
  50. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 50/144 SAFE_TYPE(interface_name, std::string); SAFE_TYPE(customer_name, std::string); void label_interface(interface_name const& ifname, customer_name const& customer); interface_name lookup_interface(MAC_address mac); void setup_customer(MAC_address mac, const customer_name& customer) { assert(!customer.empty()); auto if_name = lookup_interface(mac); assert(if_name.find(':') != std::string::npos); label_interface(customer, if_name); } Accidertal swap! template <typename T, typename tag, bool = std::is_class<T>{} && !std::is_final<T>{}> class safe_type { /* as before */}; template <typename T, typename tag> struct safe_type<T, tag, true> : T { using T::T; template <typename T2, typename tag2> safe_type(safe_type<T2,tag2> const&) = delete; };
  51. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 51/144 SAFE_TYPE(interface_name, std::string); SAFE_TYPE(customer_name, std::string); void label_interface(interface_name const& ifname, customer_name const& customer); interface_name lookup_interface(MAC_address mac); void setup_customer(MAC_address mac, customer_name const& customer) { assert(!customer.empty()); auto if_name = lookup_interface(mac); assert(if_name.find(':') != std::string::npos); label_interface(customer, if_name); } Accidental swap! error: no matching function for call to 'label_interface' label_interface(customer, if_name); ^~~~~~~~~~~~~~~ note: candidate function not viable: no known conversion from 'customer_name' to 'const interface_name' for 1st argument void label_interface(const interface_name& ifname, ^
  52. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 52/144 SAFE_TYPE(interface_name, std::string); SAFE_TYPE(customer_name, std::string); void label_interface(interface_name const& ifname, customer_name const& customer); interface_name lookup_interface(MAC_address mac); void setup_customer(MAC_address mac, const customer_name& customer) { assert(!customer.empty()); auto if_name = lookup_interface(mac); assert(if_name.find(':') != std::string::npos); label_interface(customer, if_name); } Accidertal swap! template <typename T, typename tag, bool = std::is_class<T>{} && !std::is_final<T>{}> class safe_type { /* as before */}; template <typename T, typename tag> struct safe_type<T, tag, true> : T { using T::T; template <typename T2, typename tag2> safe_type(safe_type<T2,tag2> const&) = delete; };
  53. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 53/144 SAFE_TYPE(interface_name, std::string); SAFE_TYPE(customer_name, std::string); void label_interface(interface_name const& ifname, customer_name const& customer); interface_name lookup_interface(MAC_address mac); void setup_customer(MAC_address mac, const customer_name& customer) { assert(!customer.empty()); auto if_name = lookup_interface(mac); assert(if_name.find(':') != std::string::npos); label_interface(customer, if_name); } Accidertal swap! template <typename T, typename tag, bool = std::is_class<T>{} && !std::is_final<T>{}> class safe_type { /* as before */}; template <typename T, typename tag> struct safe_type<T, tag, true> : T { using T::T; template <typename T2, typename tag2> safe_type(safe_type<T2,tag2> const&) = delete; };
  54. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 54/144 SAFE_TYPE(interface_name, std::string); SAFE_TYPE(customer_name, std::string); void label_interface(interface_name const& ifname, customer_name const& customer); interface_name lookup_interface(MAC_address mac); void setup_customer(MAC_address mac, const customer_name& customer) { assert(!customer.empty()); auto if_name = lookup_interface(mac); assert(if_name.find(':') != std::string::npos); label_interface(customer, if_name); } Accidertal swap! template <typename T, typename tag, bool = std::is_class<T>{} && !std::is_final<T>{}> class safe_type { /* as before */}; template <typename T, typename tag> struct safe_type<T, tag, true> : T { using T::T; template <typename T2, typename tag2> safe_type(safe_type<T2,tag2> const&) = delete; }; Oh, no, I violated the Liskov Substitution Principle!
  55. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 55/144 SAFE_TYPE(interface_name, std::string); SAFE_TYPE(customer_name, std::string); void label_interface(interface_name const& ifname, customer_name const& customer); interface_name lookup_interface(MAC_address mac); void setup_customer(MAC_address mac, const customer_name& customer) { assert(!customer.empty()); auto if_name = lookup_interface(mac); assert(if_name.find(':') != std::string::npos); label_interface(customer, if_name); } Accidertal swap! template <typename T, typename tag, bool = std::is_class<T>{} && !std::is_final<T>{}> class safe_type { /* as before */}; template <typename T, typename tag> struct safe_type<T, tag, true> : T { using T::T; template <typename T2, typename tag2> safe_type(safe_type<T2,tag2> const&) = delete; }; Liskov Substitution Principle Subtype Requirement: Let φ(x) be a property provable about objects x of type T. Then φ(y) should be true for objects y of type S where S is a subtype of T.
  56. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 56/144 SAFE_TYPE(interface_name, std::string); SAFE_TYPE(customer_name, std::string); void label_interface(interface_name const& ifname, customer_name const& customer); interface_name lookup_interface(MAC_address mac); void setup_customer(MAC_address mac, const customer_name& customer) { assert(!customer.empty()); auto if_name = lookup_interface(mac); assert(if_name.find(':') != std::string::npos); label_interface(customer, if_name); } Accidertal swap! template <typename T, typename tag, bool = std::is_class<T>{} && !std::is_final<T>{}> class safe_type { /* as before */}; template <typename T, typename tag> struct safe_type<T, tag, true> : T { using T::T; template <typename T2, typename tag2> safe_type(safe_type<T2,tag2> const&) = delete; }; Liskov Substitution Principle Subtype Requirement: Let φ(x) be a property provable about objects x of type T. Then φ(y) should be true for objects y of type S where S is a subtype of T. Robert (Uncle Bob) Martin Functions that use pointers or references to base classes must be able to use objects of derived classes without knowing it.
  57. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 57/144 SAFE_TYPE(interface_name, std::string); SAFE_TYPE(customer_name, std::string); void label_interface(interface_name const& ifname, customer_name const& customer); interface_name lookup_interface(MAC_address mac); void setup_customer(MAC_address mac, customer_name const& customer) { assert(!customer.empty()); auto if_name = lookup_interface(mac); assert(if_name.find(':') != std::string::npos); label_interface(customer, if_name); } Liskov Substitution Principle Subtype Requirement: Let φ(x) be a property provable about objects x of type T. Then φ(y) should be true for objects y of type S where S is a subtype of T. Robert (Uncle Bob) Martin Functions that use pointers or references to base classes must be able to use objects of derived classes without knowing it. customer_name and interface_name are different types implemented in terms of strings
  58. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 58/144 SAFE_TYPE(interface_name, std::string); SAFE_TYPE(customer_name, std::string); void label_interface(interface_name const& ifname, customer_name const& customer); interface_name lookup_interface(MAC_address mac); void setup_customer(MAC_address mac, customer_name const& customer) { assert(!customer.empty()); auto if_name = lookup_interface(mac); assert(if_name.find(':') != std::string::npos); label_interface(customer, if_name); } Liskov Substitution Principle Subtype Requirement: Let φ(x) be a property provable about objects x of type T. Then φ(y) should be true for objects y of type S where S is a subtype of T. Robert (Uncle Bob) Martin Functions that use pointers of reference to base classes must be able to use objects of derived classes without knowing it. customer_name and interface_name are different types implemented in terms of strings
  59. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 59/144 SAFE_TYPE(interface_name, std::string); SAFE_TYPE(customer_name, std::string); void label_interface(interface_name const& ifname, customer_name const& customer); interface_name lookup_interface(MAC_address mac); void setup_customer(MAC_address mac, customer_name const& customer) { assert(!customer.empty()); auto if_name = lookup_interface(mac); assert(if_name.find(':') != std::string::npos); label_interface(customer, if_name); } Liskov Substitution Principle Subtype Requirement: Let φ(x) be a property provable about objects x of type T. Then φ(y) should be true for objects y of type S where S is a subtype of T. Robert (Uncle Bob) Martin Functions that use pointers of reference to base classes must be able to use objects of derived classes without knowing it. customer_name and interface_name are different types implemented in terms of strings, but they are not strings.
  60. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 60/144 SAFE_TYPE(interface_name, std::string); SAFE_TYPE(customer_name, std::string); void label_interface(interface_name const& ifname, customer_name const& customer); interface_name lookup_interface(MAC_address mac); void setup_customer(MAC_address mac, customer_name const& customer) { assert(!customer.empty()); auto if_name = lookup_interface(mac); assert(if_name.find(':') != std::string::npos); label_interface(customer, if_name); } Liskov Substitution Principle Subtype Requirement: Let φ(x) be a property provable about objects x of type T. Then φ(y) should be true for objects y of type S where S is a subtype of T. Robert (Uncle Bob) Martin Functions that use pointers of reference to base classes must be able to use objects of derived classes without knowing it. customer_name and interface_name are different types implemented in terms of strings, but they are not strings. Maybe it makes sense to allow unlimited access to the non-mutating functions of std::string, but not to all mutating ones.
  61. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 61/144 • Introduction to type safety • Type safety in C++ • Simple library solution for strong types • Sophisticated libraries – scouting github! • What strong types does with your code Type Safe C++? - LOL! :-)
  62. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 62/144 Jonathan Müller @foonathan type_safe Zero overhead utilities for preventing bugs at compile time https://github.com/foonathan/type_safe
  63. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 63/144 Jonathan Müller @foonathan type_safe Zero overhead utilities for preventing bugs at compile time https://github.com/foonathan/type_safe A rich type library, with which you can piece together the exact behaviour of a type that you want. It also includes a number of predefined neat type templates, and other features like improved optional<T> and variant<T...>
  64. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 64/144 Jonathan Müller @foonathan type_safe Zero overhead utilities for preventing bugs at compile time https://github.com/foonathan/type_safe A rich type library, with which you can piece together the exact behaviour of a type that you want. It also includes a number of predefined neat type templates, and other features like improved optional<T> and variant<T...> Since October 2016
  65. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 65/144 // type_safe/strong_typedef.hpp template <class Tag, typename T> class type_safe::strong_typedef { public: constexpr strong_typedef(); explicit constexpr strong_typedef(const T& value); explicit constexpr strong_typedef(T&& value); explicit constexpr operator T&() & noexcept; explicit constexpr operator const T&() const & noexcept; explicit constexpr operator T&&() && noexcept; explicit constexpr operator const T&&() const && noexcept; }; https://github.com/foonathan/type_safe
  66. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 66/144 https://github.com/foonathan/type_safe #include <type_safe/strong_typedef.hpp> namespace ts = type_safe; namespace op = type_safe::strong_typedef_op; struct my_handle : ts::strong_typedef<my_handle, int> , op::equality_comparison<my_handle> , op::output_operator<my_handle> { using strong_typedef::strong_typedef; }; struct my_int : ts::strong_typedef<my_int, int> , op::integer_arithmetic<my_int> { using strong_typedef::strong_typedef; };
  67. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 67/144 https://github.com/foonathan/type_safe #include <type_safe/strong_typedef.hpp> namespace ts = type_safe; namespace op = type_safe::strong_typedef_op; struct my_handle : ts::strong_typedef<my_handle, int> , op::equality_comparison<my_handle> , op::output_operator<my_handle> { using strong_typedef::strong_typedef; }; struct my_int : ts::strong_typedef<my_int, int> , op::integer_arithmetic<my_int> { using strong_typedef::strong_typedef; };
  68. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 68/144 https://github.com/foonathan/type_safe #include <type_safe/strong_typedef.hpp> namespace ts = type_safe; namespace op = type_safe::strong_typedef_op; struct my_handle : ts::strong_typedef<my_handle, int> , op::equality_comparison<my_handle> , op::output_operator<my_handle> { using strong_typedef::strong_typedef; }; struct my_int : ts::strong_typedef<my_int, int> , op::integer_arithmetic<my_int> { using strong_typedef::strong_typedef; };
  69. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 69/144 https://github.com/foonathan/type_safe #include <type_safe/strong_typedef.hpp> namespace ts = type_safe; namespace op = type_safe::strong_typedef_op; struct my_handle : ts::strong_typedef<my_handle, int> , op::equality_comparison<my_handle> , op::output_operator<my_handle> { using strong_typedef::strong_typedef; }; struct my_int : ts::strong_typedef<my_int, int> , op::integer_arithmetic<my_int> { using strong_typedef::strong_typedef; };
  70. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 70/144 https://github.com/foonathan/type_safe #include <type_safe/strong_typedef.hpp> namespace ts = type_safe; namespace op = type_safe::strong_typedef_op; struct my_handle : ts::strong_typedef<my_handle, int> , op::equality_comparison<my_handle> , op::output_operator<my_handle> { using strong_typedef::strong_typedef; }; struct my_int : ts::strong_typedef<my_int, int> , op::integer_arithmetic<my_int> { using strong_typedef::strong_typedef; };
  71. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 71/144 https://github.com/foonathan/type_safe #include <type_safe/strong_typedef.hpp> namespace ts = type_safe; namespace op = type_safe::strong_typedef_op; struct my_handle : ts::strong_typedef<my_handle, int> , op::equality_comparison<my_handle> , op::output_operator<my_handle> { using strong_typedef::strong_typedef; }; struct my_int : ts::strong_typedef<my_int, int> , op::integer_arithmetic<my_int> { using strong_typedef::strong_typedef; };
  72. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 72/144 https://github.com/foonathan/type_safe #include <type_safe/strong_typedef.hpp> namespace ts = type_safe; namespace op = type_safe::strong_typedef_op; struct my_handle : ts::strong_typedef<my_handle, int> , op::equality_comparison<my_handle> { using strong_typedef::strong_typedef; friend std::ostream& operator<<(std::ostream& os, my_handle const& h) { return os << "H{" << static_cast<const int&>(h) << "}"; } };
  73. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 73/144 https://github.com/foonathan/type_safe #include <type_safe/strong_typedef.hpp> namespace ts = type_safe; namespace op = type_safe::strong_typedef_op; struct my_handle : ts::strong_typedef<my_handle, int> , op::equality_comparison<my_handle> { using strong_typedef::strong_typedef; friend std::ostream& operator<<(std::ostream& os, my_handle const& h) { return os << "H{" << ts::get(h) << "}"; } };
  74. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 74/144 Jonathan Boccara @joboccara NamedType Implementation of strong types in C++ https://github.com/joboccara/NamedType
  75. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 75/144 Jonathan Boccara @joboccara NamedType Implementation of strong types in C++ https://github.com/joboccara/NamedType A small type library with a simpler aim, but which still allows you to piece together the strong types with your desired behaviour. It also supports conversions between different types of the same kind, for example meters to feet, or non-linear like Watt to dB.
  76. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 76/144 Jonathan Boccara @joboccara NamedType Implementation of strong types in C++ https://github.com/joboccara/NamedType A small type library with a simpler aim, but which still allows you to piece together the strong types with your desired behaviour. It also supports conversions between different types of the same kind, for example meters to feet, or non-linear like Watt to dB. MeetingC++ https://www.youtube.com/watch?v=WVleZqzTw2k
  77. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 77/144 // NamedType/named_type.hpp using my_handle = fluent::NamedType< int, struct my_handle_tag >; https://github.com/joboccara/NamedType
  78. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 78/144 // NamedType/named_type.hpp using my_handle = fluent::NamedType< int, struct my_handle_tag, fluent::comparable, fluent::printable, fluent::hashable >; https://github.com/joboccara/NamedType
  79. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 79/144 // NamedType/named_type.hpp struct my_handle : fluent::NamedType< int, my_handle, fluent::comparable, fluent::printable, fluent::hashable > { using NamedType::NamedType; }; https://github.com/joboccara/NamedType
  80. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 80/144 // NamedType/named_type.hpp struct my_handle : fluent::NamedType< int, my_handle, fluent::comparable, fluent::printable, fluent::hashable, fluent::ImplicitlyConvertibleTo<int>::templ > { using NamedType::NamedType; }; https://github.com/joboccara/NamedType
  81. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 81/144 • Introduction to type safety • Type safety in C++ • Simple library solution for strong types • Sophisticated libraries – scouting github! • What strong types does with your code Type Safe C++? - LOL! :-)
  82. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 82/144 Network capacity utilisation 0 1 2 3 4 5 6 7 8 9 1011121314151617181920212223 Frame with 24 slots A slot is a network capacity quanta
  83. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 83/144 Network capacity utilisation 0 1 2 3 4 5 6 7 8 9 1011121314151617181920212223 Frame with 24 slots SlotCount SlotIndexes SlotRanges 8 3,4,7,8,13,14,15,16 {3-4},{7-8},{13-16} 3 5,9,10 {5},{9-10} 13 0,1,2,6,11,12,17,18, 19,20,21,22,23 {0-2},{6},{11-12},{17-23} A slot is a network capacity quanta
  84. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 84/144 Network capacity utilisation 0 1 2 3 4 5 6 7 8 9 1011121314151617181920212223 Frame with 24 slots SlotCount SlotIndexes SlotRanges 8 3,4,7,8,13,14,15,16 {3-4},{7-8},{13-16} 3 5,9,10 {5},{9-10} 13 0,1,2,6,11,12,17,18, 19,20,21,22,23 {0-2},{6},{11-12},{17-23} A slot is a network capacity quanta typename SlotIndex; typename SlotCount; struct SlotRange { SlotIndex start; SlotCount length; };
  85. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 85/144 Magic Numbers
  86. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 86/144 SlotCount availableCapacity(); ... if (availableCapacity() == 0) { ... }
  87. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 87/144 SlotCount availableCapacity(); ... if (availableCapacity() == SlotCount{0}) { ... }
  88. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 88/144 SlotCount availableCapacity(); constexpr SlotCount noSlots{0}; ... if (availableCapacity() == noSlots) { ... }
  89. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 89/144 Encapsulation
  90. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 90/144 class MessageBuffer { public: template <size_t bits> void serialize_bits(unsigned value); }; SlotCount capacity = ... MessageBuffer buffer ... buffer.serialize_bits<24>(capacity);
  91. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 91/144 class MessageBuffer { public: template <size_t bits> void serialize_bits(unsigned value); }; SlotCount capacity = ... MessageBuffer buffer ... buffer.serialize_bits<24>(capacity);
  92. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 92/144 class MessageBuffer { public: template <size_t bits> void serialize_bits(unsigned value); }; void serialize_data(MessageBuffer& b, SlotCount const& c) { b.serialize_bits<24>(c); } SlotCount capacity = ... MessageBuffer buffer ... serialize_data(buffer, capacity);
  93. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 93/144 class MessageBuffer { public: template <typename T> void serialize(T const& t) { serialize_data(*this, t); } template <size_t bits> void serialize_bits(unsigned value); }; void serialize_data(MessageBuffer& b, SlotCount const& c) { b.serialize_bits<24>(c); } SlotCount capacity = ... MessageBuffer buffer ... buffer.serialize(capacity);
  94. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 94/144 Type Semantics
  95. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 95/144 class SlotPool { public: void releaseCapacity(std::vector<SlotRange> const& ranges) SlotCount availableCapacity() const { return unusedSlots;} ... private: SlotCount unusedSlots; ... };
  96. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 96/144 class SlotPool { public: void releaseCapacity(std::vector<SlotRange> const& ranges) { for (auto& range : ranges) { ususedSlots += range.length; } ... } SlotCount availableCapacity() const { return unusedSlots;} ... private: SlotCount unusedSlots; ... };
  97. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 97/144 class SlotPool { public: void releaseCapacity(std::vector<SlotRange> const& ranges) { for (auto& range : ranges) { ususedSlots += range.length; } ... } SlotCount availableCapacity() const { return unusedSlots;} ... private: SlotCount unusedSlots; ... }; Does not compile! No operator += for SlotCount
  98. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 98/144 Which operations makes sense? SlotCount+SlotCount? 0 1 2 3 4 5 6 7 8 9 1011121314151617181920212223 Frame with 24 slots
  99. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 99/144 Which operations makes sense? SlotCount+SlotCount->SlotCount 0 1 2 3 4 5 6 7 8 9 1011121314151617181920212223 Frame with 24 slots
  100. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 100/144 Which operations makes sense? SlotCount+SlotCount->SlotCount SlotCount-SlotCount? 0 1 2 3 4 5 6 7 8 9 1011121314151617181920212223 Frame with 24 slots
  101. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 101/144 Which operations makes sense? SlotCount+SlotCount->SlotCount SlotCount-SlotCount->SlotCount 0 1 2 3 4 5 6 7 8 9 1011121314151617181920212223 Frame with 24 slots
  102. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 102/144 Which operations makes sense? SlotCount+SlotCount->SlotCount SlotCount-SlotCount->SlotCount SlotCount*SlotCount? 0 1 2 3 4 5 6 7 8 9 1011121314151617181920212223 Frame with 24 slots
  103. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 103/144 Which operations makes sense? SlotCount+SlotCount->SlotCount SlotCount-SlotCount->SlotCount SlotCount*SlotCount 0 1 2 3 4 5 6 7 8 9 1011121314151617181920212223 Frame with 24 slots
  104. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 104/144 Which operations makes sense? SlotCount+SlotCount->SlotCount SlotCount-SlotCount->SlotCount SlotCount*SlotCount SlotCount*Ratio? 0 1 2 3 4 5 6 7 8 9 1011121314151617181920212223 Frame with 24 slots
  105. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 105/144 Which operations makes sense? SlotCount+SlotCount->SlotCount SlotCount-SlotCount->SlotCount SlotCount*SlotCount SlotCount*Ratio->SlotCount 0 1 2 3 4 5 6 7 8 9 1011121314151617181920212223 Frame with 24 slots
  106. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 106/144 Which operations makes sense? SlotCount+SlotCount->SlotCount SlotCount-SlotCount->SlotCount SlotCount*SlotCount SlotCount*Ratio->SlotCount SlotCount/SlotCount? 0 1 2 3 4 5 6 7 8 9 1011121314151617181920212223 Frame with 24 slots
  107. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 107/144 Which operations makes sense? SlotCount+SlotCount->SlotCount SlotCount-SlotCount->SlotCount SlotCount*SlotCount SlotCount*Ratio->SlotCount SlotCount/SlotCount->Ratio 0 1 2 3 4 5 6 7 8 9 1011121314151617181920212223 Frame with 24 slots
  108. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 108/144 Which operations makes sense? SlotCount+SlotCount->SlotCount SlotCount-SlotCount->SlotCount SlotCount*SlotCount SlotCount*Ratio->SlotCount SlotCount/SlotCount->Ratio SlotCount/Ratio? 0 1 2 3 4 5 6 7 8 9 1011121314151617181920212223 Frame with 24 slots
  109. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 109/144 Which operations makes sense? SlotCount+SlotCount->SlotCount SlotCount-SlotCount->SlotCount SlotCount*SlotCount SlotCount*Ratio->SlotCount SlotCount/SlotCount->Ratio SlotCount/Ratio->SlotCount 0 1 2 3 4 5 6 7 8 9 1011121314151617181920212223 Frame with 24 slots
  110. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 110/144 Which operations makes sense? SlotCount+SlotCount->SlotCount SlotCount-SlotCount->SlotCount SlotCount*SlotCount SlotCount*Ratio->SlotCount SlotCount/SlotCount->Ratio SlotCount/Ratio->SlotCount SlotIndex+SlotIndex? 0 1 2 3 4 5 6 7 8 9 1011121314151617181920212223 Frame with 24 slots
  111. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 111/144 Which operations makes sense? SlotCount+SlotCount->SlotCount SlotCount-SlotCount->SlotCount SlotCount*SlotCount SlotCount*Ratio->SlotCount SlotCount/SlotCount->Ratio SlotCount/Ratio->SlotCount SlotIndex+SlotIndex 0 1 2 3 4 5 6 7 8 9 1011121314151617181920212223 Frame with 24 slots
  112. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 112/144 Which operations makes sense? SlotCount+SlotCount->SlotCount SlotCount-SlotCount->SlotCount SlotCount*SlotCount SlotCount*Ratio->SlotCount SlotCount/SlotCount->Ratio SlotCount/Ratio->SlotCount SlotIndex+SlotIndex SlotIndex+SlotCount? 0 1 2 3 4 5 6 7 8 9 1011121314151617181920212223 Frame with 24 slots
  113. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 113/144 Which operations makes sense? SlotCount+SlotCount->SlotCount SlotCount-SlotCount->SlotCount SlotCount*SlotCount SlotCount*Ratio->SlotCount SlotCount/SlotCount->Ratio SlotCount/Ratio->SlotCount SlotIndex+SlotIndex SlotIndex+SlotCount->SlotIndex 0 1 2 3 4 5 6 7 8 9 1011121314151617181920212223 Frame with 24 slots
  114. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 114/144 Which operations makes sense? SlotCount+SlotCount->SlotCount SlotCount-SlotCount->SlotCount SlotCount*SlotCount SlotCount*Ratio->SlotCount SlotCount/SlotCount->Ratio SlotCount/Ratio->SlotCount SlotIndex+SlotIndex SlotIndex+SlotCount->SlotIndex SlotIndex-SlotIndex? 0 1 2 3 4 5 6 7 8 9 1011121314151617181920212223 Frame with 24 slots
  115. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 115/144 Which operations makes sense? SlotCount+SlotCount->SlotCount SlotCount-SlotCount->SlotCount SlotCount*SlotCount SlotCount*Ratio->SlotCount SlotCount/SlotCount->Ratio SlotCount/Ratio->SlotCount SlotIndex+SlotIndex SlotIndex+SlotCount->SlotIndex SlotIndex-SlotIndex->SlotCount 0 1 2 3 4 5 6 7 8 9 1011121314151617181920212223 Frame with 24 slots
  116. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 116/144 Which operations makes sense? SlotCount+SlotCount->SlotCount SlotCount-SlotCount->SlotCount SlotCount*SlotCount SlotCount*Ratio->SlotCount SlotCount/SlotCount->Ratio SlotCount/Ratio->SlotCount SlotIndex+SlotIndex SlotIndex+SlotCount->SlotIndex SlotIndex-SlotIndex->SlotCount SlotIndex/SlotIndex? 0 1 2 3 4 5 6 7 8 9 1011121314151617181920212223 Frame with 24 slots
  117. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 117/144 Which operations makes sense? SlotCount+SlotCount->SlotCount SlotCount-SlotCount->SlotCount SlotCount*SlotCount SlotCount*Ratio->SlotCount SlotCount/SlotCount->Ratio SlotCount/Ratio->SlotCount SlotIndex+SlotIndex SlotIndex+SlotCount->SlotIndex SlotIndex-SlotIndex->SlotCount SlotIndex/SlotIndex 0 1 2 3 4 5 6 7 8 9 1011121314151617181920212223 Frame with 24 slots
  118. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 118/144 Which operations makes sense? SlotCount+SlotCount->SlotCount SlotCount-SlotCount->SlotCount SlotCount*SlotCount SlotCount*Ratio->SlotCount SlotCount/SlotCount->Ratio SlotCount/Ratio->SlotCount SlotIndex+SlotIndex SlotIndex+SlotCount->SlotIndex SlotIndex-SlotIndex->SlotCount SlotIndex/SlotIndex SlotIndex/SlotCount? 0 1 2 3 4 5 6 7 8 9 1011121314151617181920212223 Frame with 24 slots
  119. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 119/144 Which operations makes sense? SlotCount+SlotCount->SlotCount SlotCount-SlotCount->SlotCount SlotCount*SlotCount SlotCount*Ratio->SlotCount SlotCount/SlotCount->Ratio SlotCount/Ratio->SlotCount SlotIndex+SlotIndex SlotIndex+SlotCount->SlotIndex SlotIndex-SlotIndex->SlotCount SlotIndex/SlotIndex SlotIndex/SlotCount 0 1 2 3 4 5 6 7 8 9 1011121314151617181920212223 Frame with 24 slots
  120. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 120/144 Which operations makes sense? SlotCount+SlotCount->SlotCount SlotCount-SlotCount->SlotCount SlotCount*SlotCount SlotCount*Ratio->SlotCount SlotCount/SlotCount->Ratio SlotCount/Ratio->SlotCount SlotIndex+SlotIndex SlotIndex+SlotCount->SlotIndex SlotIndex-SlotIndex->SlotCount SlotIndex/SlotIndex SlotIndex/SlotCount SlotIndex/Ratio? 0 1 2 3 4 5 6 7 8 9 1011121314151617181920212223 Frame with 24 slots
  121. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 121/144 Which operations makes sense? SlotCount+SlotCount->SlotCount SlotCount-SlotCount->SlotCount SlotCount*SlotCount SlotCount*Ratio->SlotCount SlotCount/SlotCount->Ratio SlotCount/Ratio->SlotCount SlotIndex+SlotIndex SlotIndex+SlotCount->SlotIndex SlotIndex-SlotIndex->SlotCount SlotIndex/SlotIndex SlotIndex/SlotCount SlotIndex/Ratio 0 1 2 3 4 5 6 7 8 9 1011121314151617181920212223 Frame with 24 slots
  122. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 122/144 Which operations makes sense? SlotCount+SlotCount->SlotCount SlotCount-SlotCount->SlotCount SlotCount*SlotCount SlotCount*Ratio->SlotCount SlotCount/SlotCount->Ratio SlotCount/Ratio->SlotCount SlotIndex+SlotIndex SlotIndex+SlotCount->SlotIndex SlotIndex-SlotIndex->SlotCount SlotIndex/SlotIndex SlotIndex/SlotCount SlotIndex/Ratio SlotIndex*SlotIndex? 0 1 2 3 4 5 6 7 8 9 1011121314151617181920212223 Frame with 24 slots
  123. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 123/144 Which operations makes sense? SlotCount+SlotCount->SlotCount SlotCount-SlotCount->SlotCount SlotCount*SlotCount SlotCount*Ratio->SlotCount SlotCount/SlotCount->Ratio SlotCount/Ratio->SlotCount SlotIndex+SlotIndex SlotIndex+SlotCount->SlotIndex SlotIndex-SlotIndex->SlotCount SlotIndex/SlotIndex SlotIndex/SlotCount SlotIndex/Ratio SlotIndex*SlotIndex 0 1 2 3 4 5 6 7 8 9 1011121314151617181920212223 Frame with 24 slots
  124. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 124/144 Which operations makes sense? SlotCount+SlotCount->SlotCount SlotCount-SlotCount->SlotCount SlotCount*SlotCount SlotCount*Ratio->SlotCount SlotCount/SlotCount->Ratio SlotCount/Ratio->SlotCount SlotIndex+SlotIndex SlotIndex+SlotCount->SlotIndex SlotIndex-SlotIndex->SlotCount SlotIndex/SlotIndex SlotIndex/SlotCount SlotIndex/Ratio SlotIndex*SlotIndex SlotIndex*SlotCount? 0 1 2 3 4 5 6 7 8 9 1011121314151617181920212223 Frame with 24 slots
  125. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 125/144 Which operations makes sense? SlotCount+SlotCount->SlotCount SlotCount-SlotCount->SlotCount SlotCount*SlotCount SlotCount*Ratio->SlotCount SlotCount/SlotCount->Ratio SlotCount/Ratio->SlotCount SlotIndex+SlotIndex SlotIndex+SlotCount->SlotIndex SlotIndex-SlotIndex->SlotCount SlotIndex/SlotIndex SlotIndex/SlotCount SlotIndex/Ratio SlotIndex*SlotIndex SlotIndex*SlotCount 0 1 2 3 4 5 6 7 8 9 1011121314151617181920212223 Frame with 24 slots
  126. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 126/144 Which operations makes sense? SlotCount+SlotCount->SlotCount SlotCount-SlotCount->SlotCount SlotCount*SlotCount SlotCount*Ratio->SlotCount SlotCount/SlotCount->Ratio SlotCount/Ratio->SlotCount SlotIndex+SlotIndex SlotIndex+SlotCount->SlotIndex SlotIndex-SlotIndex->SlotCount SlotIndex/SlotIndex SlotIndex/SlotCount SlotIndex/Ratio SlotIndex*SlotIndex SlotIndex*SlotCount SlotIndex*Ratio? 0 1 2 3 4 5 6 7 8 9 1011121314151617181920212223 Frame with 24 slots
  127. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 127/144 Which operations makes sense? SlotCount+SlotCount->SlotCount SlotCount-SlotCount->SlotCount SlotCount*SlotCount SlotCount*Ratio->SlotCount SlotCount/SlotCount->Ratio SlotCount/Ratio->SlotCount SlotIndex+SlotIndex SlotIndex+SlotCount->SlotIndex SlotIndex-SlotIndex->SlotCount SlotIndex/SlotIndex SlotIndex/SlotCount SlotIndex/Ratio SlotIndex*SlotIndex SlotIndex*SlotCount SlotIndex*Ratio 0 1 2 3 4 5 6 7 8 9 1011121314151617181920212223 Frame with 24 slots
  128. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 128/144 Which operations makes sense? SlotCount+SlotCount->SlotCount SlotCount-SlotCount->SlotCount SlotCount*SlotCount SlotCount*Ratio->SlotCount SlotCount/SlotCount->Ratio SlotCount/Ratio->SlotCount SlotIndex+SlotIndex SlotIndex+SlotCount->SlotIndex SlotIndex-SlotIndex->SlotCount SlotIndex/SlotIndex SlotIndex/SlotCount SlotIndex/Ratio SlotIndex*SlotIndex SlotIndex*SlotCount SlotIndex*Ratio Affine Space In mathematics, an affine space is a geometric structure that generalizes the properties of Euclidean spaces in such a way that these are independent of the concepts of distance and measure of angles, keeping only the properties related to parallelism and ratio of lengths for parallel line segments... -- Wikipedia 0 1 2 3 4 5 6 7 8 9 1011121314151617181920212223 Frame with 24 slots
  129. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 129/144 Test Code
  130. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 130/144 DestClient::newCapacity(RequestId, SlotCount); TestNode::throttleCapacityTo(RequestId, SlotCount total); TEST(capacity_decrease_is_notified_to_clients) { TestNode node; DestClient client1 = node.clientWithCapacity(5); DestClient client2 = node.clientWithCapacity(8); REQUIRE_CALL(client1, newCapacity(4, 2)); REQUIRE_CALL(client2, newCapacity(4, 3)); node.throttleCapacityTo(4, 5); }
  131. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 131/144 DestClient::newCapacity(RequestId, SlotCount); TestNode::throttleCapacityTo(RequestId, SlotCount total); TEST(capacity_decrease_is_notified_to_clients) { TestNode node; DestClient client1 = node.clientWithCapacity(5); DestClient client2 = node.clientWithCapacity(8); RequestId req{4}; REQUIRE_CALL(client1, newCapacity(req, 2)); REQUIRE_CALL(client2, newCapacity(req, 3)); node.throttleCapacityTo(req, 5); }
  132. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 132/144 DestClient::newCapacity(RequestId, SlotCount); TestNode::throttleCapacityTo(RequestId, SlotCount total); TEST(capacity_decrease_is_notified_to_clients) { TestNode node; SlotCount c1Capacity{5}, c2Capacity{8}; DestClient client1 = node.clientWithCapacity(c1Capacity); DestClient client2 = node.clientWithCapacity(c2Capacity); RequestId req{4}; SlotCount newC1Capacity{2}, newC2Capacity{3}; REQUIRE_CALL(client1, newCapacity(req, newC1Capacity)); REQUIRE_CALL(client2, newCapacity(req, newC2Capacity)); SlotCount newTotalCapacity{5}; node.throttleCapacityTo(req, newTotalCapacity); }
  133. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 133/144 DestClient::newCapacity(RequestId, SlotCount); TestNode::throttleCapacityTo(RequestId, SlotCount total); TEST(capacity_decrease_is_notified_to_clients) { TestNode node; SlotCount c1Capacity{5}, c2Capacity{8}; DestClient client1 = node.clientWithCapacity(c1Capacity); DestClient client2 = node.clientWithCapacity(c2Capacity); RequestId req{4}; SlotCount newC1Capacity{2}, newC2Capacity{3}; REQUIRE_CALL(client1, newCapacity(req, newC1Capacity)); REQUIRE_CALL(client2, newCapacity(req, newC2Capacity)); SlotCount newTotalCapacity{5}; node.throttleCapacityTo(req, newTotalCapacity); } WTF!
  134. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 134/144 DestClient::newCapacity(RequestId, SlotCount); TestNode::throttleCapacityTo(RequestId, SlotCount total); TEST(capacity_decrease_is_notified_to_clients) { TestNode node; DestClient client1 = node.clientWithCapacity(SlotCount{5}); DestClient client2 = node.clientWithCapacity(SlotCount{8}); RequestId req{4}; REQUIRE_CALL(client1, newCapacity(req, SlotCount{2})); REQUIRE_CALL(client2, newCapacity(req, SlotCount{3})); node.throttleCapacityTo(req, SlotCount{5}); }
  135. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 135/144 DestClient::newCapacity(RequestId, SlotCount); TestNode::throttleCapacityTo(RequestId, SlotCount total); TEST(capacity_decrease_is_notified_to_clients) { TestNode node; DestClient client1 = node.clientWithCapacity(SlotCount{5}); DestClient client2 = node.clientWithCapacity(SlotCount{8}); RequestId req{4}; REQUIRE_CALL(client1, newCapacity(req, SlotCount{2})); REQUIRE_CALL(client2, newCapacity(req, SlotCount{3})); node.throttleCapacityTo(req, SlotCount{5}); } constexpr SlotCount operator"" _slots(unsigned long long v) { auto cv = static_cast<unsigned>(v); return SlotCount{cv}; }
  136. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 136/144 DestClient::newCapacity(RequestId, SlotCount); TestNode::throttleCapacityTo(RequestId, SlotCount total); TEST(capacity_decrease_is_notified_to_clients) { TestNode node; DestClient client1 = node.clientWithCapacity(5_slots); DestClient client2 = node.clientWithCapacity(8_slots); RequestId req{4}; REQUIRE_CALL(client1, newCapacity(req, 2_slots)); REQUIRE_CALL(client2, newCapacity(req, 3_slots)); node.throttleCapacityTo(req, 5_slots); } constexpr SlotCount operator"" _slots(unsigned long long v) { auto cv = static_cast<unsigned>(v); return SlotCount{cv}; }
  137. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 137/144 • Introduction to type safety • Type safety in C++ • Simple library solution for strong types • Sophisticated libraries – scouting github! • What strong types does with your code Type Safe C++? - LOL! :-)
  138. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 138/144 • Safety for built in types is abysmal in C++ Type Safe C++? - LOL! :-)
  139. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 139/144 • Safety for built in types is abysmal in C++ • Structs/classes are as strong as you wish – You must add the functionality you want Type Safe C++? - LOL! :-)
  140. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 140/144 • Safety for built in types is abysmal in C++ • Structs/classes are as strong as you wish – You must add the functionality you want • Libraries exist that makes this easier Type Safe C++? - LOL! :-)
  141. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 141/144 • Safety for built in types is abysmal in C++ • Structs/classes are as strong as you wish – You must add the functionality you want • Libraries exist that makes this easier • Thinking about what operations your types should support makes you understand the problem better! – Beware of the urge for convencience! Type Safe C++? - LOL! :-)
  142. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 142/144 • Safety for built in types is abysmal in C++ • Structs/classes are as strong as you wish – You must add the functionality you want • Libraries exist that makes this easier • Thinking about what operations your types should support makes you understand the problem better! – Beware of the urge for convencience! • Strong types leads to more expressive code – Fewer magical numbers – More encapsulation – Explicit tests that express intent Type Safe C++? - LOL! :-)
  143. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 143/144 • Safety for built in types is abysmal in C++ • Structs/classes are as strong as you wish – You must add the functionality you want • Libraries exist that makes this easier • Thinking about what operations your types should support makes you understand the problem better! – Beware of the urge for convencience! • Strong types leads to more expressive code – Fewer magical numbers – More encapsulation – Explicit tests that express intent Type Safe C++? - LOL! :-) Avoid typedef
  144. Type Safe C++? - LOL! :-) – ACCU 2018 –

    © Björn Fahller @bjorn_fahller 144/144 Björn Fahller [email protected] @bjorn_fahller @rollbear cpplang, swedencpp Type Safe C++? - LOL! :-)