Skip to content

Instantly share code, notes, and snippets.

@nathan-osman
Created April 22, 2013 18:28
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nathan-osman/5437314 to your computer and use it in GitHub Desktop.
Save nathan-osman/5437314 to your computer and use it in GitHub Desktop.
Demonstrates the implementation of a "variant" type in C++.
#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;
}
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
#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
#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