KrisLibrary  1.0.0
AnyValue.h
1 #ifndef ANY_VALUE_H
2 #define ANY_VALUE_H
3 
4 // polymorphic container class
5 // adapted from boost::any
6 
7 #include <typeinfo>
8 #include <algorithm>
9 #include <string>
10 #include <sstream>
11 #include <utility>
12 #include <KrisLibrary/errors.h>
13 
14 //forward declarations for Clang on OSX
15 class AnyValue;
16 template<typename ValueType>
17 ValueType* AnyCast(AnyValue * operand);
18 template<typename ValueType>
19 const ValueType* AnyCast(const AnyValue * operand);
20 
25 class AnyValue
26 {
27  public:
28  // intializers
29  AnyValue()
30  : content(0)
31  {}
32  template<typename ValueType>
33  AnyValue(const ValueType & value)
34  : content(new holder<ValueType>(value))
35  {}
36  AnyValue(const AnyValue & other)
37  : content(other.content ? other.content->clone() : 0)
38  {}
39  AnyValue(AnyValue && other) noexcept
40  : content(other.content)
41  {
42  other.content = NULL;
43  }
44  ~AnyValue() { delete content; }
45 
46  //operators
47  AnyValue & swap(AnyValue & rhs) {
48  std::swap(content, rhs.content);
49  return *this;
50  }
51  template<typename ValueType>
52  AnyValue & operator=(const ValueType & rhs) {
53  AnyValue(rhs).swap(*this);
54  return *this;
55  }
56  AnyValue & operator=(const AnyValue & rhs) {
57  AnyValue(rhs).swap(*this);
58  return *this;
59  }
60  bool empty() const { return !content; }
61  const std::type_info & type() const {
62  return content ? content->type() : typeid(void);
63  }
64  template <class T>
65  bool hastype() const {
66  return &type() == &typeid(T);
67  }
68  template <class ValueType>
69  bool operator == (const ValueType &rhs) const {
70  if(&type() != &typeid(ValueType)) return false;
71  return *AnyCast<ValueType>(this) == rhs;
72  }
73 
74  template <class ValueType>
75  bool operator != (const ValueType &rhs) const {
76  return !operator == (rhs);
77  }
78 
79  private:
80  struct placeholder
81  {
82  virtual ~placeholder() { }
83  virtual const std::type_info & type() const = 0;
84  virtual placeholder * clone() const = 0;
85  };
86 
87  template<typename ValueType>
88  struct holder : public placeholder
89  {
90  holder(const ValueType & value) : held(value) {}
91  virtual const std::type_info & type() const { return typeid(ValueType); }
92  virtual placeholder * clone() const { return new holder(held); }
93 
94  ValueType held;
95  };
96 
97  template<typename ValueType> friend ValueType * AnyCast(AnyValue *);
98  template<typename ValueType> friend ValueType * AnyCast_Quick(AnyValue *);
99  template<typename ValueType> friend ValueType * AnyCast_Raw(AnyValue *);
100 
101  placeholder * content;
102 };
103 
105 template<typename ValueType>
106 ValueType * AnyCast(AnyValue * operand)
107 {
108  return operand && operand->type() == typeid(ValueType)
109  ? &static_cast<AnyValue::holder<ValueType> *>(operand->content)->held
110  : 0;
111 }
112 
114 template<typename ValueType>
115 const ValueType * AnyCast(const AnyValue * operand)
116 {
117  return AnyCast<ValueType>(const_cast<AnyValue *>(operand));
118 }
119 
125 template<typename ValueType>
126 ValueType * AnyCast_Raw(AnyValue * operand)
127 {
128  return operand
129  ? &static_cast<AnyValue::holder<ValueType> *>(operand->content)->held
130  : 0;
131 }
132 
138 template<typename ValueType>
139 const ValueType * AnyCast_Raw(const AnyValue * operand)
140 {
141  return AnyCast_Raw<ValueType>(const_cast<AnyValue *>(operand));
142 }
143 
144 
149 template<typename ValueType>
150 ValueType * AnyCast_Quick(AnyValue * operand)
151 {
152  return operand && (&operand->type() == &typeid(ValueType))
153  ? &static_cast<AnyValue::holder<ValueType> *>(operand->content)->held
154  : 0;
155 }
156 
161 template<typename ValueType>
162 const ValueType * AnyCast_Quick(const AnyValue * operand)
163 {
164  return AnyCast_Quick<ValueType>(const_cast<AnyValue *>(operand));
165 }
166 
172 template <class T>
173 bool CoerceCast(const AnyValue& value,T& result)
174 {
175  const T* val = AnyCast<T>(&value);
176  if(val) {
177  result = *val;
178  return true;
179  }
180  return false;
181 }
182 
183 template <> bool CoerceCast<bool>(const AnyValue& value,bool& result);
184 template <> bool CoerceCast<char>(const AnyValue& value,char& result);
185 template <> bool CoerceCast<unsigned char>(const AnyValue& value,unsigned char& result);
186 template <> bool CoerceCast<int>(const AnyValue& value,int& result);
187 template <> bool CoerceCast<unsigned int>(const AnyValue& value,unsigned int& result);
188 template <> bool CoerceCast<float>(const AnyValue& value,float& result);
189 template <> bool CoerceCast<double>(const AnyValue& value,double& result);
190 template <class T> bool LexicalCast(const T& value,std::string& result);
191 template <> bool LexicalCast(const AnyValue& value,std::string& result);
192 template <class T> std::string LexicalCast(const T& value);
193 template <class T> bool LexicalCast(const std::string& value,T& result);
194 template <> bool LexicalCast(const std::string& value,AnyValue& result);
195 
196 
197 template <class T> bool LexicalCast(const T& value,std::string& result)
198 {
199  std::stringstream ss;
200  ss<<value;
201  if(ss) {
202  result = ss.str();
203  return true;
204  }
205  return false;
206 }
207 
208 template <class T> std::string LexicalCast(const T& value)
209 {
210  std::string result;
211  if(!LexicalCast(value,result)) { return ""; }
212  return result;
213 }
214 
215 template <class T> bool LexicalCast(const std::string& value,T& result)
216 {
217  std::stringstream ss(value);
218  ss>>result;
219  if(ss) return true;
220  return false;
221 }
222 
223 
224 #endif
A polymorphic container class that can contain data of any type.
Definition: AnyValue.h:25
friend ValueType * AnyCast(AnyValue *)
Retreive the data within the operand, or NULL if not of the correct type.
Definition: AnyValue.h:106
friend ValueType * AnyCast_Raw(AnyValue *)
Definition: AnyValue.h:126
friend ValueType * AnyCast_Quick(AnyValue *)
Definition: AnyValue.h:150