#include <memory> #include <iostream> // https://www.modernescpp.com/index.php/c-is-still-lazy // // CRTP base class of pin // /* avoiding virtual call (static polymorphism) */ template <typename Derived> struct PinBase { void set(bool logic) { static_cast<Derived*>(this)->setImp(logic); } void toggle() { static_cast<Derived*>(this)->toggleImp(); } bool get(void) { return static_cast<Derived*>(this)->getImp(); } private: // // base implementations // void setImp() { std::cout << "base implementation of set()!" << std::endl; } void toggleImp() { std::cout << "base implementation of toggle()!" << std::endl; } bool getImp(void) { std::cout << "base implementation of get()!" << std::endl; return true; } }; // // implementations // struct STM32_Pin : PinBase<STM32_Pin> { STM32_Pin() { std::cout << "created STM32_Pin" << std::endl; } void setImp(bool logic) { std::cout << "stm32 pin set to " << logic << std::endl; } void toggleImp() { std::cout << "toggled stm32 pin" << std::endl; } bool getImp() { return true; } void STM32_stuff() { std::cout << "STM_32 specific stuff" << std::endl; } }; struct AVR_Pin : PinBase<AVR_Pin> { AVR_Pin() { std::cout << "created AVR_Pin" << std::endl; } void setImp(bool logic) { std::cout << "AVR pin set to " << logic << std::endl; } void toggleImp() { std::cout << "toggled AVR pin" << std::endl; } bool getImp() { return true; } void avr_stuff() { std::cout << "AVR specific stuff" << std::endl; } }; template<typename T> void foo(T& base) { base.set(true); base.set(false); base.toggle(); } template<typename T> void baa(PinBase<T>& pin) { pin.toggle(); //foo(pin); } int main(void) { STM32_Pin pin1; AVR_Pin pin2; pin1.STM32_stuff(); pin2.avr_stuff(); foo(pin1); foo(pin2); baa(pin1); while(1); return 0; }