]> git.tdb.fi Git - libs/core.git/blobdiff - source/core/variant.h
Make sure all classes have sensible copy semantics
[libs/core.git] / source / core / variant.h
index 6632831e9efa4557f777f36e03f30d416a853d0b..515350de6ae5543158e20b6e2c20d4ef786163fb 100644 (file)
@@ -1,25 +1,29 @@
-/* $Id$
-
-This file is part of libmspcore
-Copyright © 2006-2007 Mikko Rasa, Mikkosoft Productions
-Distributed under the LGPL
-*/
-
 #ifndef MSP_CORE_VARIANT_H_
 #define MSP_CORE_VARIANT_H_
 
-#include "except.h"
+#include <stdexcept>
+#include <typeinfo>
 #include "meta.h"
 
 namespace Msp {
 
+class type_mismatch: public std::runtime_error
+{
+public:
+       type_mismatch(const std::type_info &, const std::type_info &);
+       ~type_mismatch() throw() { }
+};
+
+
 class Variant
 {
 private:
        struct StoreBase
        {
                virtual ~StoreBase() { }
-               virtual StoreBase *clone() const =0;
+
+               virtual const std::type_info &type_id() const = 0;
+               virtual StoreBase *clone() const = 0;
        };
 
        template<typename T>
@@ -27,7 +31,9 @@ private:
        {
                T data;
 
-               Store(T d): data(d) { }
+               Store(const T &d): data(d) { }
+
+               virtual const std::type_info &type_id() const { return typeid(T); }
                virtual StoreBase *clone() const { return new Store<T>(data); }
        };
 
@@ -44,25 +50,39 @@ public:
        Variant &operator=(const T &v)
        {
                delete store;
-               store=new Store<typename RemoveConst<T>::Type>(v);
+               store = new Store<typename RemoveConst<T>::Type>(v);
                return *this;
        }
 
        Variant &operator=(const Variant &v)
        {
                delete store;
-               store=(v.store ? v.store->clone() : 0);
+               store = (v.store ? v.store->clone() : 0);
                return *this;
        }
 
+private:
        template<typename T>
-       T &value() const
+       Store<typename RemoveConst<T>::Type> *get_typed_store() const
        {
                typedef typename RemoveConst<T>::Type NCT;
-               Store<NCT> *s=dynamic_cast<Store<NCT> *>(store);
+               Store<NCT> *s = dynamic_cast<Store<NCT> *>(store);
                if(!s)
-                       throw InvalidState("Type mismatch");
-               return s->data;
+                       throw type_mismatch(typeid(T), (store ? store->type_id() : typeid(void)));
+               return s;
+       }
+
+public:
+       template<typename T>
+       T &value()
+       {
+               return get_typed_store<T>()->data;
+       }
+
+       template<typename T>
+       const T &value() const
+       {
+               return get_typed_store<T>()->data;
        }
 
        template<typename T>