Dynamic Polymorphism with Code Injection and Metaclasses

Dynamic Polymorphism with Code Injection and Metaclasses

1 (they/them), @TartanLlama C++ Developer Advocate at Microsoft 2 Dynamic Polymorphism 3 Polymorphism: The provision of a single interface to entities of different types 4 Dynamic Static Polymorphism Polymorphism 5 Dynamic Static Polymorphism Polymorphism Run-time Compile-time 6 Dynamic Static Polymorphism Polymorphism Run-time Compile-time Different behaviour based on Different behaviour based on dynamic type static type 7 Dynamic Static Polymorphism Polymorphism Run-time Compile-time Different behaviour based on Different behaviour based on dynamic type static type Typically implemented with Typically implemented with inheritance overloading and templates 8 9 10 Problems with inheritance 11 Often requires dynamic allocation Dynamic Allocation 12 struct base{}; struct a : base{}; struct b : base{}; base make_base(); std::vector<base> v; Dynamic Allocation 13 struct base{}; struct a : base{}; struct b : base{}; std::unique_ptr<base> make_base(); std::vector<std::unique_ptr<base>> v; Problems with inheritance 14 Often requires dynamic allocation Ownership and nullability considerations Problems with inheritance 15 Often requires dynamic allocation Ownership and nullability considerations Intrusive: requires modifying child classes Intrusive Polymorphism 16 namespace mylib { struct base { virtual void do_thing(); }; } namespace otherlib { struct x { virtual void do_thing(); }; } Intrusive Polymorphism 17 namespace mylib { struct base { virtual void do_thing(); }; } namespace otherlib { struct x { virtual void do_thing(); }; } mylib::base* b = new otherlib::x; Problems with inheritance 18 Often requires dynamic allocation Ownership and nullability considerations Intrusive: requires modifying child classes No more value semantics Problems with inheritance 19 Often requires dynamic allocation Ownership and nullability considerations Intrusive: requires modifying child classes No more value semantics Changes semantics for algorithms and containers 20 struct animal { virtual ~animal(); virtual void speak() = 0; }; struct cat : animal { void speak() override; }; struct dog : animal { void speak() override; }; 21 struct animal { virtual ~animal(); Felix virtual void speak() = 0; }; struct cat : animal { void speak() override; }; struct dog : animal { void speak() override; }; 22 struct animal { virtual ~animal(); Felix virtual void speak() = 0; }; struct cat : animal { void speak() override; }; vtable for cat struct dog : animal { void speak() override; }; 23 struct animal { virtual ~animal(); Felix virtual void speak() = 0; }; struct cat : animal { void speak() override; }; vtable for cat struct dog : animal { void speak() override; }; struct animal { 24 // magic }; struct cat { void speak(); }; struct dog { void speak(); }; struct animal { 25 // magic }; int main() { animal c = cat{}; struct cat { c.speak(); void speak(); }; animal d = dog{}; d.speak(); struct dog { } void speak(); }; Hand-written virtual functions 26 Declare vtable for the abstract interface Define vtable for a concrete type Capture the vtable pointers on construction Forward calls through the vtable 27 struct animal { virtual ~animal(); virtual void speak() = 0; }; struct cat : animal { void speak() override; }; struct dog : animal { void speak() override; }; Hand-written virtual functions 28 Declare vtable for the abstract interface Define vtable for a concrete type Capture the vtable pointers on construction Forward calls through the vtable 29 struct vtable { void (*speak)(void* ptr); void (*destroy_)(void* ptr); }; Hand-written virtual functions 30 Declare vtable for the abstract interface Define vtable for a concrete type Capture the vtable pointers on construction Forward calls through the vtable 31 template<class Concrete> constexpr vtable vtable_for { // function which calls speak // function which deletes object }; 32 template<class Concrete> constexpr vtable vtable_for { [] (void* ptr) { static_cast<Concrete*>(ptr)->speak(); }, [] (void* ptr) { delete static_cast<Concrete*>(ptr); } }; Hand-written virtual functions 33 Declare vtable for the abstract interface Define vtable for a concrete type Capture the vtable pointers on construction Forward calls through the vtable 34 struct animal { void* concrete_; vtable const* vtable_; }; 35 struct animal { void* concrete_; vtable const* vtable_; template<class T> animal(T const& t) : concrete_(new T(t)), vtable_(&vtable_for<T>) {} }; Hand-written virtual functions 36 Declare vtable for the abstract interface Define vtable for a concrete type Capture the vtable pointers on construction Forward calls through the vtable 37 struct animal { // ... void speak() { vtable_->speak(t_); } ~animal() { vtable_->destroy_(t_); } }; struct cat { 38 void speak(); }; struct dog { void speak(); }; struct cat { 39 void speak(); }; struct dog { void speak(); }; int main() { animal c = cat{}; c.speak(); animal d = dog{}; d.speak(); } Problems with inheritance 40 Often requires dynamic allocation Ownership and nullability considerations Intrusive: requires modifying child classes No more value semantics Changes semantics for algorithms and containers Problems with inheritance 41 Often requires dynamic allocation Ownership and nullability considerations Intrusive: requires modifying child classes No more value semantics Changes semantics for algorithms and containers Problems with inheritance 42 Often requires dynamic allocation Ownership and nullability considerations Intrusive: requires modifying child classes No more value semantics Changes semantics for algorithms and containers struct vtable { 43 void (*speak)(void* ptr); void (*destroy_)(void* ptr); void* (*clone_)(void* ptr); void* (*move_clone_)(void* ptr); }; struct vtable { 44 void (*speak)(void* ptr); void (*destroy_)(void* ptr); void* (*clone_)(void* ptr); void* (*move_clone_)(void* ptr); }; template<class T> constexpr vtable vtable_for { [] (void* ptr) { static_cast<T*>(ptr)->speak(); }, [] (void* ptr) { delete static_cast<T*>(ptr); }, [] (void* ptr) -> void* { return new T(*static_cast<T*>(ptr)); }, [] (void* ptr) -> void* { return new T(std::move(*static_cast<T*>(ptr))); } }; struct animal { 45 //... animal(animal const& rhs) : t_(rhs.vtable_->clone_(rhs.t_)), vtable_(rhs.vtable_) {} animal(animal&& rhs) : t_(rhs.vtable_->move_clone_(rhs.t_)), vtable_(rhs.vtable_) {} }; int main() { 46 animal a = cat{}; a.speak(); a = dog{}; a.speak(); animal b = a; b.speak(); } int main() { 47 std::vector<animal> animals { cat{}, dog{} }; for (auto&& a : animals) { a.speak(); } } Problems with inheritance 48 Often requires dynamic allocation Ownership and nullability considerations Intrusive: requires modifying child classes No more value semantics Changes semantics for algorithms and containers Problems with inheritance 49 Often requires dynamic allocation Ownership and nullability considerations Intrusive: requires modifying child classes No more value semantics Changes semantics for algorithms and containers Problems with inheritance 50 Often requires dynamic allocation Ownership and nullability considerations Intrusive: requires modifying child classes No more value semantics Changes semantics for algorithms and containers struct vtable { void (*speak)(void* ptr); void (*destroy_)(void* ptr); void* (*clone_)(void* ptr); void* (*move_clone_)(void* ptr); 51 }; template<class T> constexpr vtable vtable_for { [] (void* ptr) { static_cast<T*>(ptr)->speak(); }, [] (void* ptr) { delete static_cast<T*>(ptr); }, [] (void* ptr) -> void* { return new T(*static_cast<T*>(ptr)); }, [] (void* ptr) -> void* { return new T(std::move(*static_cast<T*>(ptr))); } }; struct animal { void* t_; vtable const* vtable_; void speak() { vtable_->speak(t_); } ~animal() { vtable_->destroy_(t_); } template<class T> animal(T const& t) : t_(new T(t)), vtable_(&vtable_for<T>) {} animal(animal const& rhs) : t_(rhs.vtable_->clone_(rhs.t_)), vtable_(rhs.vtable_) {} animal(animal&& rhs) : t_(rhs.vtable_->move_clone_(rhs.t_)), vtable_(rhs.vtable_) {} animal& operator=(animal const& rhs) { t_ = rhs.vtable_->clone_(rhs.t_); vtable_ = rhs.vtable_; return *this; } animal& operator=(animal&& rhs) { t_ = rhs.vtable_->move_clone_(rhs.t_); vtable_ = rhs.vtable_; return *this; } }; 52 Static Reflection 53 Reflection: The ability of a program to introspect its own structure 54 Static Reflection: The ability of a program to introspect its own structure at compile-time 55 std::is_array<T> 56 std::is_same<T, U> 57 Enum to string? Iterate over members? 58 59 template<Enum T> constexpr std::string to_string(T value) { } 60 template<Enum T> constexpr std::string to_string(T value) { for constexpr (auto e : std::meta::members_of(reflexpr(T)) { } } 61 template<Enum T> constexpr std::string to_string(T value) { for constexpr (auto e : std::meta::members_of(reflexpr(T)) { } } 62 template<Enum T> constexpr std::string to_string(T value) { for constexpr (auto e : std::meta::members_of(reflexpr(T)) { } } 63 template<Enum T> constexpr std::string to_string(T value) { for constexpr (auto e : std::meta::members_of(reflexpr(T)) { if (exprid(e) == value) { } } } 64 template<Enum T> constexpr std::string to_string(T value) { for constexpr (auto e : std::meta::members_of(reflexpr(T)) { if (exprid(e) == value) { } } } 65 template<Enum T> constexpr std::string to_string(T value) { for constexpr (auto e : std::meta::members_of(reflexpr(T)) { if (exprid(e) == value) { return std::meta::name_of(e); } } } 66 template<Enum T> constexpr std::string to_string(T value) { for constexpr

View Full Text

Details

  • File Type
    pdf
  • Upload Time
    -
  • Content Languages
    English
  • Upload User
    Anonymous/Not logged-in
  • File Pages
    155 Page
  • File Size
    -

Download

Channel Download Status
Express Download Enable

Copyright

We respect the copyrights and intellectual property rights of all users. All uploaded documents are either original works of the uploader or authorized works of the rightful owners.

  • Not to be reproduced or distributed without explicit permission.
  • Not used for commercial purposes outside of approved use cases.
  • Not used to infringe on the rights of the original creators.
  • If you believe any content infringes your copyright, please contact us immediately.

Support

For help with questions, suggestions, or problems, please contact us