stlab.adobe.com Adobe Systems Incorporated

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 /**************************************************************************************************/

Copyright © 2006-2007 Adobe Systems Incorporated.

Use of this website signifies your agreement to the Terms of Use and Online Privacy Policy.

Search powered by Google