object_methods.h

Go to the documentation of this file.
00001 #ifndef OBJECT_METHODS_H
00002 #define OBJECT_METHODS_H
00003 
00004 #include "calling_convention.h"
00005 #include "global_function.h"
00006 #include <boost/utility/enable_if.hpp>
00007 
00008 void AS_StdcallFunctionsCannotBeObjectMethods(Undefined &);
00009 
00010 template <typename T, typename Fn, typename D = void>
00011 struct ObjectMethod {
00012   ObjectMethod() {
00013     CallingConvention<Fn>();
00014   }
00015   
00016   static std::string signature(const std::string & name);
00017   static asSFuncPtr convert(Fn);
00018   static const asDWORD calling_convention;
00019 };
00020 
00021 template <typename T, typename Fn>
00022 struct ObjectMethod<T, Fn,
00023                      typename boost::enable_if<
00024                        boost::integral_constant<bool,
00025                          (CallingConvention<Fn>::value == asCALL_THISCALL)
00026                        >
00027                      >::type>
00028   : boost::integral_constant<bool,
00029       boost::is_base_of<typename CallingConvention<Fn>::ObjectType, T>::value &&
00030       CallingConvention<Fn>::valid_object_method> {
00031   static std::string signature(const std::string & name) {
00032     return CallingConvention<Fn>::object_method_signature(name);
00033   }
00034 
00035   static const asDWORD calling_convention = asCALL_THISCALL;
00036   
00037   static asSFuncPtr convert(Fn fn) {
00038     return asSMethodPtr<sizeof(void (T::*)())>::Convert((void (T::*)())(fn));
00039   }
00040 };
00041 
00042 template <typename ClassType, typename T>
00043 struct IsValidClassArgType : boost::false_type {};
00044 
00045 template <typename ClassType, typename T>
00046 struct IsValidClassArgType<ClassType, T *> : boost::is_base_of<T, ClassType> {};
00047 template <typename ClassType, typename T>
00048 struct IsValidClassArgType<ClassType, const T *> : boost::is_base_of<T, ClassType> {};
00049 template <typename ClassType, typename T>
00050 struct IsValidClassArgType<ClassType, T &> : boost::is_base_of<T, ClassType> {};
00051 template <typename ClassType, typename T>
00052 struct IsValidClassArgType<ClassType, const T &> : boost::is_base_of<T, ClassType> {};
00053 
00054 template <typename ClassType, typename T>
00055 struct IsValidClassArgType<ClassType, ObjectProxy<T> *> : boost::is_base_of<T, ClassType> {};
00056 template <typename ClassType, typename T>
00057 struct IsValidClassArgType<ClassType, const ObjectProxy<T> *> : boost::is_base_of<T, ClassType> {};
00058 template <typename ClassType, typename T>
00059 struct IsValidClassArgType<ClassType, ObjectProxy<T> &> : boost::is_base_of<T, ClassType> {};
00060 template <typename ClassType, typename T>
00061 struct IsValidClassArgType<ClassType, const ObjectProxy<T> &> : boost::is_base_of<T, ClassType> {};
00062 
00063 template <typename T, typename Fn>
00064 struct ObjectMethod<T, Fn,
00065                      typename boost::enable_if<
00066                        boost::integral_constant<bool,
00067                          (CallingConvention<Fn>::value == asCALL_CDECL)
00068                        >
00069                      >::type>
00070   : boost::integral_constant<bool,
00071     (IsValidClassArgType<T, typename CallingConvention<Fn>::FirstType>::value &&
00072      CallingConvention<Fn>::is_valid_firstcall_method) || 
00073     (IsValidClassArgType<T, typename CallingConvention<Fn>::LastType>::value &&
00074      CallingConvention<Fn>::is_valid_lastcall_method)>
00075 {
00076   static std::string signature(const std::string & name) {
00077     return do_signature(name, boost::integral_constant<asDWORD, calling_convention>());
00078   }
00079   
00080   static std::string do_signature(const std::string & name,
00081                                   boost::integral_constant<asDWORD, asCALL_CDECL_OBJFIRST>) {
00082     return CallingConvention<Fn>::firstcall_signature(name);
00083   }
00084   static std::string do_signature(const std::string & name,
00085                                   boost::integral_constant<asDWORD, asCALL_CDECL_OBJLAST>) {
00086     return CallingConvention<Fn>::lastcall_signature(name);
00087   }
00088 
00089   static const asDWORD calling_convention
00090     = (IsValidClassArgType<T, typename CallingConvention<Fn>::FirstType>::value &&
00091        CallingConvention<Fn>::is_valid_firstcall_method) ? asCALL_CDECL_OBJFIRST 
00092                                                          : asCALL_CDECL_OBJLAST;
00093 
00094   static asSFuncPtr convert(Fn fn) {
00095     return asFUNCTION(fn);
00096   }
00097 };
00098 
00099 template <typename T, typename Fn>
00100 struct ObjectMethod<T, Fn,
00101                      typename boost::enable_if<
00102                        boost::integral_constant<bool,
00103                          (CallingConvention<Fn>::value == asCALL_STDCALL)
00104                        >
00105                      >::type> {
00106   ObjectMethod() {
00107     AS_StdcallFunctionsCannotBeObjectMethods(Fn());
00108   }
00109   
00110   static std::string signature(const std::string & name);
00111   static asSFuncPtr convert(Fn);
00112   static const asDWORD calling_convention;
00113 };
00114 
00115 
00116 template <typename T, typename Fn>
00117 std::string do_object_method_signature(Fn, const std::string & name, ObjectMethod<T, Fn> om) {
00118   AS_FunctionHasInvalidParameters(om);
00119   return ObjectMethod<T, Fn>::signature(name);
00120 }
00121 
00122 template <typename T, typename Fn>
00123 std::string object_method_signature(Fn fn, const std::string & name) {
00124   return do_object_method_signature<T>(fn, name, ObjectMethod<T, Fn>());
00125 }
00126 
00127 template <typename T, typename Fn>
00128 asSFuncPtr convert_object_method(Fn fn) {
00129   return ObjectMethod<T, Fn>::convert(fn);
00130 }
00131 
00132 template <typename T, typename Fn>
00133 asDWORD object_method_calling_conv(Fn) {
00134   return ObjectMethod<T, Fn>::calling_convention;
00135 }
00136 
00137 
00138 #define REGISTER_OBJECT_METHOD(type, name, fn)                             \
00139   RegisterObjectMethod( ASTraits<type>::get_name().c_str(),                \
00140                         object_method_signature<type>(fn, name).c_str(),   \
00141                         convert_object_method<type>(fn),                   \
00142                         object_method_calling_conv<type>(fn) )
00143 
00144 #define REGISTER_OBJECT_BEHAVIOUR(type, behaviour, fn)                       \
00145   RegisterObjectBehaviour( ASTraits<type>::get_name().c_str(),               \
00146                            behaviour,                                        \
00147                            object_method_signature<type>(fn, "f").c_str(),   \
00148                            convert_object_method<type>(fn),                  \
00149                            object_method_calling_conv<type>(fn) )
00150 
00151 #endif

Generated on Mon Jan 11 12:03:41 2010 for Werewolf by  doxygen 1.6.1