Created
November 30, 2017 02:48
-
-
Save nbingham1/c108392b624104366431c924b5bae427 to your computer and use it in GitHub Desktop.
Go-like Interfaces in C++
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
// Taken from here: | |
// http://wall.org/~lewis/2012/07/23/go-style-interfaces-in-cpp.html | |
// | |
// Some of the code didn't render correctly on the site, here is a full compilable version. | |
#include <stdlib.h> | |
#include <stdio.h> | |
using namespace std; | |
struct Unknown { }; | |
class Person | |
{ | |
// Vtable | |
template <class T> | |
struct implemented_by | |
{ | |
const char* (T::*name) (); | |
void (T::*talk) (); | |
static const implemented_by vtable; | |
}; | |
// Interface struct is two pointers long | |
const implemented_by<Unknown>* const vt; | |
Unknown* const p; | |
public: | |
// Methods | |
inline const char* name () { return (p->*(vt->name))(); } | |
inline void talk () { return (p->*(vt->talk))(); } | |
// Conversion | |
template <class T> | |
Person (T* x) : vt(reinterpret_cast<const implemented_by<Unknown> *> | |
(&implemented_by<T>::vtable)), | |
p(reinterpret_cast<Unknown*>(x)) | |
{ } | |
}; | |
// Define vtables for all compatible types | |
template <class T> | |
const Person::implemented_by<T> Person::implemented_by<T>::vtable = { | |
&T::name, | |
&T::talk | |
}; | |
// Person is an interface type with these methods... | |
// const char* name () | |
// void talk () | |
// This function takes one as an argument | |
void talkabout (Person t) | |
{ | |
printf("%s says:\n", t.name()); | |
t.talk(); | |
} | |
// No "implements" declaration, no virtual methods | |
struct Foo | |
{ | |
int x; | |
const char* name () { return "Foo"; } | |
void talk () { printf("I'm a Foo with a %d!\n", this->x); } | |
}; | |
// Watch the magic | |
int main () | |
{ | |
Foo x = {24}; | |
talkabout(&x); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment