Created
April 22, 2013 18:28
-
-
Save nathan-osman/5437314 to your computer and use it in GitHub Desktop.
Demonstrates the implementation of a "variant" type in C++.
This file contains hidden or 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 <iostream> | |
#include <string> | |
#include "variant.h" | |
int main(int argc, char ** argv) | |
{ | |
Variant variant; | |
variant.setValue<int>(12345); | |
std::cout << "Value: " << variant.value<int>() << std::endl; | |
variant.setValue<std::string>("abcde"); | |
std::cout << "Value: " << variant.value<std::string>() << std::endl; | |
return 0; | |
} |
This file contains hidden or 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
CXX = g++ | |
LD = g++ | |
variant: main.o | |
$(LD) main.o -o variant | |
main.o: type.h variant.h main.cpp | |
$(CXX) -c main.cpp -o main.o |
This file contains hidden or 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
#ifndef TYPE_H | |
#define TYPE_H | |
#include <typeinfo> | |
/* Abstract base class that provides an interface for manipulating objects at runtime. */ | |
class TypeBase | |
{ | |
public: | |
TypeBase() : references(1) {} | |
/* Constructor, copy constructor, and destructor.*/ | |
virtual void * create() = 0; | |
virtual void * copy(void *) = 0; | |
virtual void destroy(void *) = 0; | |
/* Type comparison. */ | |
virtual bool compare(const std::type_info &) = 0; | |
/* Reference counting methods. */ | |
void acquire() | |
{ | |
++references; | |
} | |
void release() | |
{ | |
if(!--references) | |
delete this; | |
} | |
private: | |
int references; | |
}; | |
/* Implements the pure virtual methods in the base class for the specified type. */ | |
template <typename T> | |
class Type : public TypeBase | |
{ | |
public: | |
virtual void * create() | |
{ | |
return new T; | |
} | |
virtual void * copy(void * instance) | |
{ | |
return new T(*reinterpret_cast<T *>(instance)); | |
} | |
virtual void destroy(void * instance) | |
{ | |
delete reinterpret_cast<T *>(instance); | |
} | |
virtual bool compare(const std::type_info & type) | |
{ | |
return typeid(T) == type; | |
} | |
}; | |
#endif // TYPE_H |
This file contains hidden or 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
#ifndef VARIANT_H | |
#define VARIANT_H | |
#include <typeinfo> | |
#include "type.h" | |
class Variant | |
{ | |
public: | |
class EmptyVariant {}; | |
class TypeMismatch {}; | |
Variant() : type(0), data(0) {} | |
Variant(const Variant & original) | |
: type(0), data(0) | |
{ | |
*this = original; | |
} | |
~Variant() | |
{ | |
free(); | |
} | |
template <typename T> T value() const | |
{ | |
if(data) | |
{ | |
if(type->compare(typeid(T))) | |
return *reinterpret_cast<T *>(data); | |
else | |
throw TypeMismatch(); | |
} | |
else | |
throw EmptyVariant(); | |
} | |
template <typename T> void setValue(T value) | |
{ | |
free(); | |
type = new Type<T>; | |
data = type->copy(&value); | |
} | |
Variant & operator= (const Variant & rhs) | |
{ | |
free(); | |
type = rhs.type; | |
type->acquire(); | |
data = type->copy(rhs.data); | |
} | |
private: | |
void free() | |
{ | |
if(type && data) | |
{ | |
type->destroy(data); | |
type->release(); | |
type = 0; | |
data = 0; | |
} | |
} | |
TypeBase * type; | |
void * data; | |
}; | |
#endif // VARIANT_H |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment