]> git.tdb.fi Git - libs/core.git/blob - source/core/variant.h
Improve error reporting in Variant
[libs/core.git] / source / core / variant.h
1 /* $Id$
2
3 This file is part of libmspcore
4 Copyright © 2008 Mikko Rasa, Mikkosoft Productions
5 Distributed under the LGPL
6 */
7
8 #ifndef MSP_CORE_VARIANT_H_
9 #define MSP_CORE_VARIANT_H_
10
11 #include <stdexcept>
12 #include <typeinfo>
13 #include "meta.h"
14
15 namespace Msp {
16
17 class type_mismatch: public std::runtime_error
18 {
19 public:
20         type_mismatch(const std::type_info &, const std::type_info &);
21         ~type_mismatch() throw() { }
22 };
23
24
25 class Variant
26 {
27 private:
28         struct StoreBase
29         {
30                 virtual ~StoreBase() { }
31
32                 virtual const std::type_info &type_id() const = 0;
33                 virtual StoreBase *clone() const = 0;
34         };
35
36         template<typename T>
37         struct Store: public StoreBase
38         {
39                 T data;
40
41                 Store(T d): data(d) { }
42
43                 virtual const std::type_info &type_id() const { return typeid(T); }
44                 virtual StoreBase *clone() const { return new Store<T>(data); }
45         };
46
47         StoreBase *store;
48
49 public:
50         Variant(): store(0) { }
51         template<typename T>
52         Variant(const T &v): store(new Store<typename RemoveConst<T>::Type>(v)) { }
53         Variant(const Variant &v): store(v.store ? v.store->clone() : 0) { }
54         ~Variant() { delete store; }
55
56         template<typename T>
57         Variant &operator=(const T &v)
58         {
59                 delete store;
60                 store = new Store<typename RemoveConst<T>::Type>(v);
61                 return *this;
62         }
63
64         Variant &operator=(const Variant &v)
65         {
66                 delete store;
67                 store = (v.store ? v.store->clone() : 0);
68                 return *this;
69         }
70
71         template<typename T>
72         T &value() const
73         {
74                 typedef typename RemoveConst<T>::Type NCT;
75                 Store<NCT> *s = dynamic_cast<Store<NCT> *>(store);
76                 if(!s)
77                         throw type_mismatch(typeid(T), (store ? store->type_id() : typeid(void)));
78                 return s->data;
79         }
80
81         template<typename T>
82         bool check_type() const
83         {
84                 return dynamic_cast<Store<typename RemoveConst<T>::Type> *>(store)!=0;
85         }
86
87         template<typename T>
88         operator T() const
89         { return value<T>(); }
90 };
91
92 } // namespace Msp
93
94 #endif