00001 #pragma ident "$Id: Any.hpp 2938 2011-10-23 19:39:11Z yanweignss $"
00002
00008 #ifndef GPSTK_ANY_HPP
00009 #define GPSTK_ANY_HPP
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 #include <algorithm>
00034 #include <typeinfo>
00035 #include "Exception.hpp"
00036
00037 namespace gpstk
00038 {
00045 class Any
00046 {
00047 public:
00048 Any():_content(0){}
00049
00050 template <typename ValueType>
00051 Any(const ValueType& value):_content(new Holder<ValueType>(value)) {}
00052
00053 Any(const Any& other):_content(other._content ? other._content->clone() : 0){}
00054
00055 ~Any(){delete _content;}
00056
00057 Any& swap(Any& rhs)
00058 {
00059 std::swap(_content, rhs._content);
00060 return *this;
00061 }
00062
00063 template <typename ValueType>
00064 Any& operator = (const ValueType& rhs)
00065 {
00066 Any(rhs).swap(*this);
00067 return *this;
00068 }
00069
00070 Any& operator = (const Any& rhs)
00071 {
00072 Any(rhs).swap(*this);
00073 return *this;
00074 }
00075
00076 bool empty() const
00077 {
00078 return !_content;
00079 }
00080
00081 const std::type_info& type() const
00082 {
00083 return _content ? _content->type() : typeid(void);
00084 }
00085
00086 private:
00087 class Placeholder
00088 {
00089 public:
00090 virtual ~Placeholder(){}
00091
00092 virtual const std::type_info& type() const = 0;
00093 virtual Placeholder* clone() const = 0;
00094 };
00095
00096 template <typename ValueType>
00097 class Holder: public Placeholder
00098 {
00099 public:
00100 Holder(const ValueType& value):_held(value){}
00101
00102 virtual const std::type_info& type() const
00103 {
00104 return typeid(ValueType);
00105 }
00106
00107 virtual Placeholder* clone() const
00108 {
00109 return new Holder(_held);
00110 }
00111
00112 ValueType _held;
00113 };
00114
00115 private:
00116 template <typename ValueType>
00117 friend ValueType* AnyCast(Any*);
00118
00119 template <typename ValueType>
00120 friend ValueType* UnsafeAnyCast(Any*);
00121
00122 Placeholder* _content;
00123 };
00124
00125
00132 template <typename ValueType>
00133 ValueType* AnyCast(Any* operand)
00134 {
00135 return operand && operand->type() == typeid(ValueType)
00136 ? &static_cast<Any::Holder<ValueType>*>(operand->_content)->_held
00137 : 0;
00138 }
00139
00140
00147 template <typename ValueType>
00148 const ValueType* AnyCast(const Any* operand)
00149 {
00150 return AnyCast<ValueType>(const_cast<Any*>(operand));
00151 }
00152
00153
00162 template <typename ValueType>
00163 ValueType AnyCast(const Any& operand)
00164 {
00165 ValueType* result = AnyCast<ValueType>(const_cast<Any*>(&operand));
00166 if (!result) throw Exception("Failed to convert between const Any types");
00167 return *result;
00168 }
00169
00178 template <typename ValueType>
00179 ValueType AnyCast(Any& operand)
00180 {
00181 ValueType* result = AnyCast<ValueType>(&operand);
00182 if (!result) throw Exception("Failed to convert between Any types");
00183 return *result;
00184 }
00185
00190 template <typename ValueType>
00191 const ValueType& RefAnyCast(const Any & operand)
00192 {
00193 ValueType* result = AnyCast<ValueType>(const_cast<Any*>(&operand));
00194 if (!result) throw Exception("RefAnyCast: Failed to convert between const Any types");
00195 return *result;
00196 }
00197
00198
00203 template <typename ValueType>
00204 ValueType& RefAnyCast(Any& operand)
00205 {
00206 ValueType* result = AnyCast<ValueType>(&operand);
00207 if (!result) throw Exception("RefAnyCast: Failed to convert between Any types");
00208 return *result;
00209 }
00210
00216 template <typename ValueType>
00217 ValueType* UnsafeAnyCast(Any* operand)
00218 {
00219 return &static_cast<Any::Holder<ValueType>*>(operand->_content)->_held;
00220 }
00221
00227 template <typename ValueType>
00228 const ValueType* UnsafeAnyCast(const Any* operand)
00229 {
00230 return AnyCast<ValueType>(const_cast<Any*>(operand));
00231 }
00232
00233 }
00234
00235
00236 #endif //GPSTK_ANY_HPP
00237