Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifndef PROGRAM_OPTIONS_VALUE_STORE_H_INCLUDED
00023 #define PROGRAM_OPTIONS_VALUE_STORE_H_INCLUDED
00024 #include <typeinfo>
00025 #include <new>
00026 namespace ProgramOptions {
00027 namespace detail {
00028 typedef void (*vcall_type)(const void* in, void** out);
00029 typedef vcall_type vtable_type[4];
00030 typedef vtable_type* vptr_type;
00031
00032
00033 template <class T>
00034 inline vptr_type vtable(const T* = 0);
00035 template <class T>
00036 inline vptr_type base_vtable(const T* = 0);
00037 }
00038
00040 class ValueStore {
00041 public:
00043 ValueStore();
00045 ValueStore(const ValueStore& other);
00047 template <class T>
00048 ValueStore(const T& obj)
00049 : vptr_(detail::vtable(static_cast<const T*>(0)))
00050 , value_(0) {
00051 clone(&obj, &value_);
00052 }
00054 ~ValueStore();
00056 ValueStore& operator=(ValueStore other);
00058 template <class T>
00059 ValueStore& operator=(const T& obj) {
00060 ValueStore(obj).swap(*this);
00061 return *this;
00062 }
00064
00067 template <class T>
00068 ValueStore& assimilate(T* obj) {
00069 clear();
00070 vptr_ = detail::base_vtable(static_cast<const T*>(0));
00071 value_= obj;
00072 return *this;
00073 }
00075 void swap(ValueStore& other);
00077 bool empty() const { return vptr_ == 0; }
00079 const std::type_info&
00080 type() const;
00082 void clear();
00084 void surrender();
00085
00086 void* extract_raw() const {
00087 return !empty()
00088 ? extract(const_cast<void**>(&value_))
00089 : 0;
00090 }
00091 private:
00092 enum { call_extract = 0, vcall_clone = 1, vcall_destroy = 2, vcall_typeid = 3 };
00093 typedef detail::vptr_type vptr_type;
00094 void clone(const void* obj, void** out) const;
00095 void* extract(void** o) const;
00096 vptr_type vptr_;
00097 void* value_;
00098 };
00099
00100 struct bad_value_cast : std::bad_cast {
00101 const char * what() const throw() {
00102 return "value_cast: invalid conversion on ValueStore";
00103 }
00104 };
00105
00107
00110 template <class T>
00111 const T& value_cast(const ValueStore& v, const T* = 0) {
00112 if (v.type() == typeid(T)) {
00113 return *static_cast<const T*>(const_cast<const void*>(v.extract_raw()));
00114 }
00115 throw bad_value_cast();
00116 }
00118 template <class T>
00119 const T* value_cast(const ValueStore* v, const T* = 0) {
00120 if (v->type() == typeid(T)) {
00121 return static_cast<const T*>(const_cast<const void*>(v->extract_raw()));
00122 }
00123 return 0;
00124 }
00128 template <class T>
00129 T& value_cast(ValueStore& v, const T* p = 0) {
00130 return const_cast<T&>(value_cast(const_cast<const ValueStore&>(v), p));
00131 }
00132 template <class T>
00133 T* value_cast(ValueStore* v, const T* p = 0) {
00134 return const_cast<T*>(value_cast(const_cast<const ValueStore*>(v), p));
00135 }
00136
00138 template <class T>
00139 const T* unsafe_value_cast(const ValueStore* v, const T* = 0) {
00140 return static_cast<const T*>(const_cast<const void*>(v->extract_raw()));
00141 }
00145 template <class T>
00146 T* unsafe_value_cast(ValueStore* v, const T* p = 0) {
00147 return const_cast<T*>(unsafe_value_cast(const_cast<const ValueStore*>(v), p));
00148 }
00149
00150 #include "detail/value_store.h"
00151
00152 }
00153 #endif