Last active
August 29, 2015 14:11
-
-
Save theopolis/aaddd99f2280f2793ffd to your computer and use it in GitHub Desktop.
C++ Non-static member binding and pseudo CRTP idioms
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <string> | |
#include <typeinfo> | |
#include <memory> | |
#include <functional> | |
using std::placeholders::_1; | |
typedef std::function<int(int)> CallbackFunc; | |
// Helper stdout callback usage. | |
void CallIt(CallbackFunc callback) { | |
printf("call: %d\n", callback(1)); | |
} | |
// Base template with traits templating. | |
template <typename Item> | |
class BaseClass { | |
public: | |
BaseClass() {} | |
~BaseClass() {} | |
int CallMe(int i) { | |
return i; | |
} | |
template<class T> | |
void Bind(std::shared_ptr<T> object, int (T::*entry)(int)) { | |
CallbackFunc fp = std::bind(entry, *object, _1); | |
CallIt(fp); | |
} | |
template<class T> | |
void Bind(T *object, int (T::*entry)(int)) { | |
CallbackFunc fp = std::bind(entry, *object, _1); | |
CallIt(fp); | |
} | |
// Combo traits-like recurring template scary-mode binding. | |
template<class T> | |
void Bind(int (T::*entry)(int), int value) { | |
auto self = reinterpret_cast<T*>(this); | |
CallbackFunc fp = std::bind(entry, self, value); | |
CallIt(fp); | |
} | |
}; | |
struct Trait {}; | |
struct DerivedTrait: public Trait {}; | |
class DerivedClass: public BaseClass<DerivedTrait> { | |
public: | |
int CallMe(int i) { | |
return i * 10; | |
} | |
// Binding API exposure. | |
void Init() { | |
Bind(&DerivedClass::CallMe, 8); | |
} | |
}; | |
typedef std::shared_ptr<BaseClass<Trait> > BaseRef; | |
typedef std::shared_ptr<DerivedClass> DerivedRef; | |
int main() { | |
DerivedClass d; | |
auto pt = std::make_shared<DerivedClass>(d); | |
auto npt = static_cast<DerivedRef>(pt); | |
auto bpt = reinterpret_cast<BaseRef&>(pt); | |
// Usually supply an object and templated member function (matching signature). | |
//pt->Bind(pt, &DerivedClass::CallMe); | |
pt->Init(); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment