Skip to content

Instantly share code, notes, and snippets.

@nyanpasu64
Last active December 9, 2019 14:53
Show Gist options
  • Save nyanpasu64/eace620481660f7dfee30b63a55c92f9 to your computer and use it in GitHub Desktop.
Save nyanpasu64/eace620481660f7dfee30b63a55c92f9 to your computer and use it in GitHub Desktop.
C++ Inheritance vs Trait-like Type Erasure

This is based off of code in my current program (https://gitlab.com/nyanpasu64/exotracker-cpp).

In practice, synth_run_clocks contains a very tight loop whose interior is called up to 1.79 million times a second (once per NES clock cycle). I thought it might be faster if the innermost method call was statically dispatched. (But if the loop is complex, does it generate instruction cache bloat?)

#include <iostream>
#include <memory>
#include <utility>
struct ChipSynthBase {
protected:
// "Virtual" is a lie. These methods are only called statically,
// and could be removed altogether.
virtual void advance(int x) = 0;
virtual void take_sample() = 0;
public:
virtual void synth_run_clocks() = 0;
};
struct Adder : ChipSynthBase {
int _x = 0;
void advance(int x) override {
_x += x;
}
void take_sample() override {
std::cout << _x << "\n";
}
};
// where ImplBase : ChipSynthBase
template<typename ImplBase>
struct ChipSynthLoop : ImplBase {
void synth_run_clocks() override {
int out;
for (int x = 0; x < 10; x++) {
this->advance(x);
this->take_sample();
}
}
};
int main() {
std::unique_ptr<ChipSynthBase> chip = std::make_unique<ChipSynthLoop<Adder>>();
chip->synth_run_clocks();
}
#include <iostream>
#include <memory>
#include <utility>
// "Virtual" is a lie. These methods are only called statically.
// ChipSynthInnerTrait could be removed altogether.
struct ChipSynthInnerTrait {
virtual void advance(int x) = 0;
virtual void take_sample() = 0;
};
struct ChipSynthLoopTrait {
virtual void synth_run_clocks() = 0;
};
struct Adder : ChipSynthInnerTrait {
int _x = 0;
void advance(int x) override {
_x += x;
}
void take_sample() override {
std::cout << _x << "\n";
}
};
// where ImplInner: impl ChipSynthInnerTrait
template<typename ImplInner>
struct ChipSynthLoop : ChipSynthLoopTrait {
ImplInner inner;
void synth_run_clocks() override {
int out;
for (int x = 0; x < 10; x++) {
inner.advance(x);
inner.take_sample();
}
}
};
int main() {
std::unique_ptr<ChipSynthLoopTrait> chip = std::make_unique<ChipSynthLoop<Adder>>();
chip->synth_run_clocks();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment