Skip to content

Instantly share code, notes, and snippets.

@nbingham1
Created November 30, 2017 02:48
Show Gist options
  • Save nbingham1/c108392b624104366431c924b5bae427 to your computer and use it in GitHub Desktop.
Save nbingham1/c108392b624104366431c924b5bae427 to your computer and use it in GitHub Desktop.
Go-like Interfaces in C++
// 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