Skip to content

jzcurious/poly

Folders and files

NameName
Last commit message
Last commit date

Latest commit

3b4ea54 · Jan 21, 2025

History

63 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

poly

The implementation of polymorphism without vtables

Benchmark result

Running ./poly-benchmarks
Run on (16 X 3546.03 MHz CPU s)
CPU Caches:
L1 Data 32 KiB (x8)
L1 Instruction 32 KiB (x8)
L2 Unified 512 KiB (x8)
L3 Unified 16384 KiB (x1)
Load Average: 2.38, 1.66, 1.62

Benchmark Time CPU Iterations
poly_explicit_mean 6.89 ms 6.88 ms 3
poly_explicit_median 6.87 ms 6.86 ms 3
poly_explicit_stddev 0.044 ms 0.046 ms 3
poly_explicit_cv 0.63 % 0.66 % 3
poly_implicit_mean 7.05 ms 7.04 ms 3
poly_implicit_median 7.05 ms 7.04 ms 3
poly_implicit_stddev 0.004 ms 0.003 ms 3
poly_implicit_cv 0.06 % 0.05 % 3
poly_known_types_mean 1.78 ms 1.77 ms 3
poly_known_types_median 1.78 ms 1.77 ms 3
poly_known_types_stddev 0.002 ms 0.001 ms 3
poly_known_types_cv 0.14 % 0.07 % 3
cpp_mean 58.4 ms 58.2 ms 3
cpp_median 58.4 ms 58.2 ms 3
cpp_stddev 0.047 ms 0.059 ms 3
cpp_cv 0.08 % 0.10 % 3
cpp_known_types_mean 28.9 ms 28.8 ms 3
cpp_known_types_median 28.9 ms 28.8 ms 3
cpp_known_types_stddev 0.073 ms 0.058 ms 3
cpp_known_types_cv 0.25 % 0.20 % 3

(see benchmarks.cpp)

Sample

#include "poly/poly.hpp"
#include <iostream>

class Base {
  POLY_SET_CLASS_ID(0);

 public:
  int val = 8;

  void overrided_function() const {
    std::cout << __PRETTY_FUNCTION__ << std::endl;
  }

  float not_overrided_function(float x) {
    std::cout << __PRETTY_FUNCTION__ << std::endl;
    return val + x + 1;
  }

  int partial_overrided_function(int x, int y) {
    std::cout << __PRETTY_FUNCTION__ << std::endl;
    return val + x + y;
  }
};

class DerivedA : public Base {
  POLY_SET_CLASS_ID(1);

 public:
  int y = 3;

  void overrided_function() const POLY_OVERRIDE {
    std::cout << __PRETTY_FUNCTION__ << std::endl;
  }

  int partial_overrided_function(int x, int y) POLY_OVERRIDE {
    std::cout << __PRETTY_FUNCTION__ << std::endl;
    return x * y - val;
  }
};

class DerivedB : public Base {
  POLY_SET_CLASS_ID(2);

 public:
  void overrided_function() const POLY_OVERRIDE {
    std::cout << __PRETTY_FUNCTION__ << std::endl;
  }
};

class DerivedC : public Base {
  POLY_SET_CLASS_ID(3);

 public:
  void overrided_function() const POLY_OVERRIDE {
    std::cout << __PRETTY_FUNCTION__ << std::endl;
  }
};

POLY_DECL_DISPATCHER(
    Dispatcher,
    {
      POLY_DISPATCH(overrided_function);
      POLY_DISPATCH(not_overrided_function);
      POLY_DISPATCH(partial_overrided_function);
    },
    Base,
    DerivedA,
    DerivedB,
    DerivedC);

int main() {
  auto dispatcher = Dispatcher{};

  auto base = new Base();
  auto derived_a = reinterpret_cast<Base*>(new DerivedA());
  auto derived_b = reinterpret_cast<Base*>(new DerivedB());
  auto derived_c = reinterpret_cast<Base*>(new DerivedC());

  dispatcher.dispatch_overrided_function(base);
  dispatcher.forward(derived_a).overrided_function();
  dispatcher.dispatch_overrided_function(derived_b);
  dispatcher.dispatch_overrided_function(derived_c);

  dispatcher.dispatch_not_overrided_function(base, 1);
  dispatcher.dispatch_not_overrided_function(derived_a, 10);
  dispatcher.forward(derived_b).not_overrided_function(10);
  dispatcher.dispatch_not_overrided_function(derived_c, 101);

  dispatcher.dispatch_partial_overrided_function(base, 1, 2);
  dispatcher.dispatch_partial_overrided_function(derived_a, 10, 15);
  dispatcher.dispatch_partial_overrided_function(derived_b, 101, 4);
  dispatcher.forward(derived_c).partial_overrided_function(10, 8);

  dispatcher.destroy(base);
  dispatcher.destroy(derived_a);
  dispatcher.destroy(derived_b);
  dispatcher.destroy(derived_c);
}

About

Implementation of polymorphism without vtables

Resources

License

Stars

Watchers

Forks

Packages

No packages published