function.hpp
Go to the documentation of this file.
00001 /* 00002 Copyright 2005-2007 Adobe Systems Incorporated 00003 Distributed under the MIT License (see accompanying file LICENSE_1_0_0.txt 00004 or a copy at http://stlab.adobe.com/licenses.html) 00005 */ 00006 00007 /**************************************************************************************************/ 00008 00009 #ifndef ADOBE_FUNCTION_HPP 00010 #define ADOBE_FUNCTION_HPP 00011 00012 #include <algorithm> 00013 #include <exception> 00014 00015 #include <tr1/functional> 00016 #include <tr1/type_traits> 00017 00018 #include <boost/bind.hpp> 00019 00020 #include <adobe/cstdint.hpp> 00021 #include <adobe/string.hpp> 00022 00023 /**************************************************************************************************/ 00024 00025 namespace adobe { 00026 00027 /**************************************************************************************************/ 00028 00029 class marshaled_exception : public std::exception { 00030 public: 00031 explicit marshaled_exception(string_t message) : message_m(move(message)) { } 00032 ~marshaled_exception() throw() { } 00033 const char* what() const throw() { return message_m.c_str(); } 00034 private: 00035 string_t message_m; 00036 }; 00037 00038 const char* current_exception_what() { 00039 const char* result = "unknown_exception"; 00040 00041 try { throw; } 00042 catch (const std::exception& error) { 00043 if (error.what()) result = error.what(); 00044 } catch (...) { } 00045 00046 return result; 00047 } 00048 00049 struct void_; 00050 typedef void_* null_ptr_t; 00051 00052 /**************************************************************************************************/ 00053 00054 namespace implementation { 00055 00056 template <typename T> 00057 class function_base { 00058 public: 00059 // [3.7.2.2] function modifiers 00060 void swap(T& x) { std::swap(self()->object_m, x.object_m); } 00061 00062 // [3.7.2.3] function capacity 00063 operator bool() const { return self()->object_m; } 00064 00065 // [3.7.2.5] function target access 00066 /* Not provided: 00067 const std::type_info& target_type() const; 00068 template <typename T> T* target(); 00069 template <typename T> const T* target() const; 00070 */ 00071 00072 friend inline void swap(T& x, T& y) { x.swap(y); } 00073 private: 00074 operator int() const; // for safe bool cast 00075 00076 T* self() { return static_cast<T*>(this); } 00077 const T* self() const { return static_cast<const T*>(this); } 00078 }; 00079 00080 template <typename Concept, typename Apply> 00081 struct vtable { 00082 void (*destroy)(Concept*); 00083 Concept* (*copy)(const Concept*, string_t& message); 00084 Apply apply; 00085 }; 00086 00087 template <typename Concept, typename V> 00088 struct concept_base_t { 00089 explicit concept_base_t(const V* x) : vtable_m(x) { } 00090 00091 Concept* copy() const { 00092 string_t message; 00093 Concept* result = vtable_m->copy(self(), message); 00094 if (message) throw marshaled_exception(move(message)); 00095 return result; 00096 } 00097 00098 void destroy() { vtable_m->destroy(self()); } 00099 00100 Concept* self() { return static_cast<Concept*>(this); } 00101 const Concept* self() const { return static_cast<const Concept*>(this); } 00102 00103 const V* vtable_m; 00104 }; 00105 00106 template <typename Model, 00107 typename Concept> 00108 struct model_base : Concept { 00109 template <typename T> 00110 explicit model_base(T x) : Concept(x) { } 00111 00112 static Model* self(Concept* x) { return static_cast<Model*>(x); } 00113 static const Model* self(const Concept* x) { return static_cast<const Model*>(x); } 00114 00115 static void destroy(Concept* x) { delete self(x); } 00116 00117 static Concept* copy(const Concept* x, string_t& message) { 00118 Concept* result = 0; 00119 00120 try { 00121 result = new Model(*self(x)); 00122 } catch (...) { 00123 message = current_exception_what(); 00124 } 00125 00126 return result; 00127 } 00128 }; 00129 00130 template <typename F, typename T> 00131 typename F::concept_t* make_model(const T& x) { 00132 return new typename F::template model<T>(x); 00133 } 00134 00135 template <typename F, typename T> 00136 typename F::concept_t* create_model(const T& x, std::tr1::true_type) { 00137 return x ? make_model<F>(boost::bind<typename F::result_type>(x)) : 0; 00138 } 00139 00140 template <typename F, typename T> 00141 typename F::concept_t* create_model(const T& x, std::tr1::false_type) { 00142 return make_model<F>(boost::bind<typename F::result_type>(x)); 00143 } 00144 00145 template <typename F, typename T> 00146 typename F::concept_t* create_model(const T& x) { 00147 return create_model<F>(x, std::tr1::is_pointer<T>()); 00148 } 00149 00150 } // namespace implementation 00151 00152 /**************************************************************************************************/ 00153 00154 namespace version_1 { 00155 00156 /**************************************************************************************************/ 00157 00163 template <typename F> class function; 00164 00165 /**************************************************************************************************/ 00166 00167 // [3.7.2.7] null pointer comparisons 00168 template <typename F> bool operator==(const function<F>& x, null_ptr_t) { return !x; } 00169 template <typename F> bool operator==(null_ptr_t, const function<F>& x) { return !x; } 00170 template <typename F> bool operator!=(const function<F>& x, null_ptr_t) { return x; } 00171 template <typename F> bool operator!=(null_ptr_t, const function<F>& x) { return x; } 00172 00173 /**************************************************************************************************/ 00174 00175 template <typename R> 00176 class function<R ()> : public implementation::function_base<function<R ()> > 00177 { 00178 public: 00179 typedef R result_type; 00180 00181 // [3.7.2.1] construction/copy/destroy 00182 function() : object_m(0) { } 00183 function(null_ptr_t) : object_m(0) { } 00184 function(const function& x) : object_m(x.object_m ? x.object_m->copy() : 0) { } 00185 template <typename T> function(T x) : object_m(implementation::create_model<function>(x)) { } 00186 00187 function& operator=(function x) { swap(*this, x); return *this; } 00188 function& operator=(null_ptr_t) { if (object_m) object_m->destroy(); object_m = 0; } 00189 template <typename T> function& operator=(T x) { return *this = function(x); } 00190 // template<class F> function& operator=(reference_wrapper<F>); 00191 00192 ~function() { if (object_m) object_m->destroy(); } 00193 00194 // [3.7.2.4] function invocation 00195 R operator()() const { 00196 if (!object_m) throw std::tr1::bad_function_call(); 00197 return object_m->apply(); 00198 } 00199 00200 struct concept_t; // implementation 00201 00202 private: 00203 friend class implementation::function_base<function<R ()> >; 00204 00205 typedef implementation::vtable<concept_t, R (*)(concept_t*, string_t&)> vtable_type; 00206 00207 /* 00208 REVISIT (sparent) : This section is an implementation detail - made public until I can figure 00209 out how to make template friends. 00210 */ 00211 00212 public: 00213 00214 struct concept_t : implementation::concept_base_t<concept_t, vtable_type> { 00215 typedef implementation::concept_base_t<concept_t, vtable_type> base_type; 00216 00217 explicit concept_t(const vtable_type* x) : base_type(x) { } 00218 R apply() { 00219 return apply(typename std::tr1::is_void<R>()); 00220 } 00221 00222 void apply(std::tr1::true_type) { 00223 string_t message; 00224 this->vtable_m->apply(this, message); 00225 if (message) throw marshaled_exception(move(message)); 00226 } 00227 00228 R apply(std::tr1::false_type) { 00229 string_t message; 00230 R result = this->vtable_m->apply(this, message); 00231 if (message) throw marshaled_exception(move(message)); 00232 return result; 00233 } 00234 }; 00235 00236 template <typename T> 00237 struct model : implementation::model_base<model<T>, concept_t> { 00238 typedef implementation::model_base<model<T>, concept_t> base_type; 00239 00240 explicit model(T x) : base_type(&vtable_s), function_m(x) { } 00241 00242 static R apply(concept_t* x, string_t& message) { 00243 return apply(x, message, typename std::tr1::is_void<R>()); 00244 } 00245 00246 static void apply(concept_t* x, string_t& message, std::tr1::true_type) { 00247 try { 00248 static_cast<model*>(x)->function_m(); 00249 } catch (...) { 00250 message = current_exception_what(); 00251 } 00252 } 00253 00254 static R apply(concept_t* x, string_t& message, std::tr1::false_type) { 00255 R result; 00256 try { 00257 result = static_cast<model*>(x)->function_m(); 00258 } catch (...) { 00259 message = current_exception_what(); 00260 } 00261 return result; 00262 } 00263 00264 static const vtable_type vtable_s; 00265 T function_m; 00266 }; 00267 00268 private: 00269 concept_t* object_m; 00270 }; 00271 00272 template <typename R> 00273 template <typename T> 00274 const typename function<R ()>::vtable_type function<R ()>::model<T>::vtable_s = { 00275 &model::destroy, 00276 &model::copy, 00277 &model::apply 00278 }; 00279 00280 /**************************************************************************************************/ 00281 00282 } // namespace version_1 00283 using namespace version_1; 00284 } // namespace adobe 00285 00286 /**************************************************************************************************/ 00287 00288 #endif 00289 00290 /**************************************************************************************************/ |