00001
00002
00003
00004
00005
00006
00013
00014
00015 #ifndef BOOST_PP_IS_ITERATING
00016
00017 # ifndef EVAL_FWRAP_H
00018 # define EVAL_FWRAP_H
00019
00020
00021 # include <vector>
00022 # include <stdexcept>
00023 # include <typeinfo>
00024
00025 # include <boost/static_assert.hpp>
00026 # include <boost/type_traits/is_reference.hpp>
00027 # include <boost/type_traits/is_pointer.hpp>
00028 # include <boost/type_traits/is_const.hpp>
00029 # include <boost/type_traits/is_integral.hpp>
00030 # include <boost/type_traits/is_floating_point.hpp>
00031 # include <boost/preprocessor/repetition.hpp>
00032 # include <boost/preprocessor/punctuation/comma_if.hpp>
00033 # include <boost/preprocessor/iteration/iterate.hpp>
00034
00035 # include "val.hpp"
00036
00037 # ifndef EVAL_FWRAP_MAX_NUM_OF_ARGS
00038 # define EVAL_FWRAP_MAX_NUM_OF_ARGS 10
00039 # endif
00040
00041
00042 namespace eval
00043 {
00047 typedef std::vector<val> fwrap_args;
00048
00049 class null_ptr_exception : public std::logic_error
00050 {
00051 public:
00052 explicit null_ptr_exception(const std::string& err)
00053 : std::logic_error("eval::null_ptr_exception: " + err)
00054 {
00055 }
00056 };
00057
00059 class arity_mismatch_exception : public std::logic_error
00060 {
00061 public:
00062 arity_mismatch_exception(int num_args_required, int num_args_supplied)
00063 : std::logic_error(std::string("eval::arity_mismatch_exception: Expected ")
00064 + detail::stringify(&num_args_required) + " arguments (got "
00065 + detail::stringify(&num_args_supplied) + ")")
00066 {
00067 }
00068 };
00069
00070 enum fwrap_fn_type {
00071 FWRAP_CONST_METHOD = 1,
00072 FWRAP_METHOD,
00073 FWRAP_CONSTRUCTOR,
00074 FWRAP_FUNCTION
00075
00076 };
00077
00078
00079 class arg_info
00080 {
00081 public:
00084 arg_info(const std::type_info *type, bool is_const, bool is_pointer, bool is_reference)
00085 : _type(type), _is_const(is_const), _is_pointer(is_pointer), _is_reference(is_reference)
00086 {
00087 }
00088
00089
00090 const std::type_info& type() const
00091 {
00092 return *_type;
00093 }
00094
00096 bool is_const() const
00097 {
00098 return _is_const;
00099 }
00100
00101 bool is_pointer() const
00102 {
00103 return _is_pointer;
00104 }
00105
00106 bool is_reference() const
00107 {
00108 return _is_reference;
00109 }
00110
00111 bool is_void() const
00112 {
00113 return *_type == typeid(void) && !is_pointer();
00114 }
00115 private:
00116 const std::type_info *_type;
00117 bool _is_const;
00118 bool _is_pointer;
00119 bool _is_reference;
00120 };
00121
00122
00123 namespace detail
00124 {
00125 template<typename T>
00126 class val_cast_ptr_or_ref
00127 {
00128 public:
00129 static T cast(val& v)
00130 {
00131 return *val_cast_ptr<const T>(v);
00132 }
00133 };
00134
00135 template<typename T>
00136 class val_cast_ptr_or_ref<T *>
00137 {
00138 public:
00139 static T *cast(val& v)
00140 {
00141 if(v.empty())
00142 {
00143 return 0;
00144 }
00145 else
00146 {
00147 return val_cast_ptr<T>(v);
00148 }
00149 }
00150 };
00151
00152 template<typename T>
00153 class val_cast_ptr_or_ref<T&>
00154 {
00155 public:
00156 static T& cast(val& v)
00157 {
00158 return *val_cast_ptr<T>(v);
00159 }
00160 };
00161
00162
00163
00165 template<typename T>
00166 inline val create_val(T& x, const boost::true_type&)
00167 {
00168 return val(&x, UNMANAGED_PTR);
00169 }
00170
00172 template<typename T>
00173 inline val create_val(T& x, const boost::false_type&)
00174 {
00175 T *new_x = new T(x);
00176 return val(new_x, TRANSFER_OWNERSHIP);
00177 }
00178
00179 template<typename T>
00180 inline val create_val(T *x, const boost::false_type&)
00181 {
00182 return val(x, UNMANAGED_PTR);
00183 }
00184
00185 template<typename T>
00186 class arg_info_generator
00187 {
00188 public:
00189 static arg_info make_arg_info()
00190 {
00191 return arg_info(&typeid(T), true, false, false);
00192 }
00193 };
00194
00195 template<typename T>
00196 class arg_info_generator<T *>
00197 {
00198 public:
00199 static arg_info make_arg_info()
00200 {
00201 return arg_info(&typeid(T), boost::is_const<T>::value, true, false);
00202 }
00203 };
00204
00205 template<typename T>
00206 class arg_info_generator<T&>
00207 {
00208 public:
00209 static arg_info make_arg_info()
00210 {
00211 return arg_info(&typeid(T), boost::is_const<T>::value, false, true);
00212 }
00213 };
00214
00215
00216
00217
00218
00219
00220
00221 # define BOOST_PP_ITERATION_LIMITS (0, EVAL_FWRAP_MAX_NUM_OF_ARGS)
00222 # define BOOST_PP_FILENAME_1 "fwrap.hpp" // this file
00223 # include BOOST_PP_ITERATE()
00224
00225 # endif // EVAL_FWRAP_H
00226
00227 #else // BOOST_PP_IS_ITERATING
00228
00229 # define n BOOST_PP_ITERATION()
00230
00231
00232 # if n == 0 // Define the abstract base classes and primary specializations
00233
00236 class fwrap_store_base
00237 {
00238 public:
00239 virtual val call(fwrap_args &args) const = 0;
00240 virtual const fwrap_store_base *clone() const = 0;
00241 virtual unsigned int arity() const = 0;
00242 virtual fwrap_fn_type fn_type() const = 0;
00243 virtual arg_info get_rv_info() const = 0;
00244 virtual void get_arg_info(std::vector<arg_info> &vec) const = 0;
00245
00246 virtual ~fwrap_store_base()
00247 {
00248 }
00249 };
00250
00251
00253 template<typename T>
00254 class func_store : public fwrap_store_base
00255 {
00256 BOOST_STATIC_ASSERT(sizeof(T) == 0);
00257 };
00258
00260 template<typename ObjT, typename T>
00261 class ctor_store : public fwrap_store_base
00262 {
00263 BOOST_STATIC_ASSERT(sizeof(ObjT) == 0);
00264 };
00265
00266
00267 # endif
00268
00269
00270
00271
00272 # define ARG_INFO_PUSH_BACK(z, n, vec_name) \
00273 vec_name.push_back(detail::arg_info_generator<T ## n>::make_arg_info());
00274
00275
00276
00277 # define ARGS_PRINT(z, n, vec_name) detail::val_cast_ptr_or_ref<T ## n>::cast(vec_name[n])
00278
00279 template<typename RvT
00280 BOOST_PP_COMMA_IF(n)
00281 BOOST_PP_ENUM_PARAMS(n, typename T)>
00282 class func_store<RvT (*)(BOOST_PP_ENUM_PARAMS(n, T))> : public fwrap_store_base
00283 {
00284 public:
00285 explicit func_store(RvT (*f)(BOOST_PP_ENUM_PARAMS(n, T)))
00286 : _f(f)
00287 {
00288 }
00289
00290 virtual val call(fwrap_args& args) const
00291 {
00292 if(args.size() != n)
00293 {
00294 throw arity_mismatch_exception(n, args.size());
00295 }
00296 RvT rv(_f(BOOST_PP_ENUM(n, ARGS_PRINT, args)));
00297 return detail::create_val(rv, boost::is_reference<RvT>());
00298 }
00299
00300 virtual const fwrap_store_base *clone() const
00301 {
00302 return new func_store<RvT (*)(BOOST_PP_ENUM_PARAMS(n, T))>(_f);
00303 }
00304
00305 virtual unsigned int arity() const
00306 {
00307 return n;
00308 }
00309
00310 virtual fwrap_fn_type fn_type() const
00311 {
00312 return FWRAP_FUNCTION;
00313 }
00314
00315 virtual arg_info get_rv_info() const
00316 {
00317 return detail::arg_info_generator<RvT>::make_arg_info();
00318 }
00319
00320 virtual void get_arg_info(std::vector<arg_info>& vec) const
00321 {
00322 vec.clear();
00323 BOOST_PP_REPEAT(n, ARG_INFO_PUSH_BACK, vec)
00324 }
00325 private:
00326 RvT (*_f)(BOOST_PP_ENUM_PARAMS(n, T));
00327 };
00328
00329
00330
00331
00332
00333 template<BOOST_PP_ENUM_PARAMS(n, typename T)>
00334 class func_store<void (*)(BOOST_PP_ENUM_PARAMS(n, T))> : public fwrap_store_base
00335 {
00336 public:
00337 explicit func_store(void (*f)(BOOST_PP_ENUM_PARAMS(n, T)))
00338 : _f(f)
00339 {
00340 }
00341
00342 virtual val call(fwrap_args& args) const
00343 {
00344 if(args.size() != n)
00345 {
00346 throw arity_mismatch_exception(n, args.size());
00347 }
00348 _f(BOOST_PP_ENUM(n, ARGS_PRINT, args));
00349 return val();
00350 }
00351
00352 virtual const fwrap_store_base *clone() const
00353 {
00354 return new func_store<void (*)(BOOST_PP_ENUM_PARAMS(n, T))>(_f);
00355 }
00356
00357 virtual unsigned int arity() const
00358 {
00359 return n;
00360 }
00361
00362 virtual fwrap_fn_type fn_type() const
00363 {
00364 return FWRAP_FUNCTION;
00365 }
00366
00367 virtual arg_info get_rv_info() const
00368 {
00369 return detail::arg_info_generator<void>::make_arg_info();
00370 }
00371
00372 virtual void get_arg_info(std::vector<arg_info>& vec) const
00373 {
00374 vec.clear();
00375 BOOST_PP_REPEAT(n, ARG_INFO_PUSH_BACK, vec)
00376 }
00377 private:
00378 void (*_f)(BOOST_PP_ENUM_PARAMS(n, T));
00379 };
00380
00381
00382
00383 # define ARGS_PRINT_METHOD(z, n, vec_name) \
00384 detail::val_cast_ptr_or_ref<T ## n>::cast(vec_name[n + 1])
00385
00386
00387 template<typename ObjT,
00388 typename RvT
00389 BOOST_PP_COMMA_IF(n)
00390 BOOST_PP_ENUM_PARAMS(n, typename T)>
00391 class func_store<RvT (ObjT::*)(BOOST_PP_ENUM_PARAMS(n, T))> : public fwrap_store_base
00392 {
00393 public:
00394 explicit func_store(RvT (ObjT::*m)(BOOST_PP_ENUM_PARAMS(n, T)))
00395 : _m(m)
00396 {
00397 }
00398
00399 virtual val call(fwrap_args& args) const
00400 {
00401 if(args.size() != n + 1)
00402 {
00403 throw arity_mismatch_exception(n + 1, args.size());
00404 }
00405 ObjT *o = eval::val_cast_ptr<ObjT>(args[0]);
00406 RvT rv((o->*_m)(BOOST_PP_ENUM(n, ARGS_PRINT_METHOD, args)));
00407 return detail::create_val(rv, boost::is_reference<RvT>());
00408 }
00409
00410 virtual const fwrap_store_base *clone() const
00411 {
00412 return new func_store<RvT (ObjT::*)(BOOST_PP_ENUM_PARAMS(n, T))>(_m);
00413 }
00414
00415 virtual unsigned int arity() const
00416 {
00417 return n + 1;
00418 }
00419
00420 virtual fwrap_fn_type fn_type() const
00421 {
00422 return FWRAP_METHOD;
00423 }
00424
00425 virtual arg_info get_rv_info() const
00426 {
00427 return detail::arg_info_generator<RvT>::make_arg_info();
00428 }
00429
00430 virtual void get_arg_info(std::vector<arg_info>& vec) const
00431 {
00432 vec.clear();
00433 vec.push_back(detail::arg_info_generator<ObjT *>::make_arg_info());
00434 BOOST_PP_REPEAT(n, ARG_INFO_PUSH_BACK, vec)
00435 }
00436
00437 private:
00438 RvT (ObjT::*_m)(BOOST_PP_ENUM_PARAMS(n, T));
00439 };
00440
00441
00442
00443
00444 template<typename ObjT,
00445 typename RvT
00446 BOOST_PP_COMMA_IF(n)
00447 BOOST_PP_ENUM_PARAMS(n, typename T)>
00448 class func_store<RvT (ObjT::*)(BOOST_PP_ENUM_PARAMS(n, T)) const> : public fwrap_store_base
00449 {
00450 public:
00451 explicit func_store(RvT (ObjT::*m)(BOOST_PP_ENUM_PARAMS(n, T)) const)
00452 : _m(m)
00453 {
00454 }
00455
00456 virtual val call(fwrap_args& args) const
00457 {
00458 if(args.size() != n + 1)
00459 {
00460 throw arity_mismatch_exception(n + 1, args.size());
00461 }
00462 const ObjT *o = eval::val_cast_ptr<const ObjT>(args[0]);
00463 RvT rv((o->*_m)(BOOST_PP_ENUM(n, ARGS_PRINT_METHOD, args)));
00464 return detail::create_val(rv, boost::is_reference<RvT>());
00465 }
00466
00467 virtual const fwrap_store_base *clone() const
00468 {
00469 return new func_store<RvT (ObjT::*)(BOOST_PP_ENUM_PARAMS(n, T)) const>(_m);
00470 }
00471
00472 virtual unsigned int arity() const
00473 {
00474 return n + 1;
00475 }
00476
00477 virtual fwrap_fn_type fn_type() const
00478 {
00479 return FWRAP_CONST_METHOD;
00480 }
00481
00482 virtual arg_info get_rv_info() const
00483 {
00484 return detail::arg_info_generator<RvT>::make_arg_info();
00485 }
00486
00487 virtual void get_arg_info(std::vector<arg_info>& vec) const
00488 {
00489 vec.clear();
00490 vec.push_back(detail::arg_info_generator<const ObjT *>::make_arg_info());
00491 BOOST_PP_REPEAT(n, ARG_INFO_PUSH_BACK, vec)
00492 }
00493
00494 private:
00495 RvT (ObjT::*_m)(BOOST_PP_ENUM_PARAMS(n, T)) const;
00496 };
00497
00498
00499
00500
00501 template<typename ObjT
00502 BOOST_PP_COMMA_IF(n)
00503 BOOST_PP_ENUM_PARAMS(n, typename T)>
00504 class func_store<void (ObjT::*)(BOOST_PP_ENUM_PARAMS(n, T))> : public fwrap_store_base
00505 {
00506 public:
00507 explicit func_store(void (ObjT::*m)(BOOST_PP_ENUM_PARAMS(n, T)))
00508 : _m(m)
00509 {
00510 }
00511
00512 virtual val call(fwrap_args& args) const
00513 {
00514 if(args.size() != n + 1)
00515 {
00516 throw arity_mismatch_exception(n + 1, args.size());
00517 }
00518 ObjT *o = eval::val_cast_ptr<ObjT>(args[0]);
00519 (o->*_m)(BOOST_PP_ENUM(n, ARGS_PRINT_METHOD, args));
00520 return val();
00521 }
00522
00523 virtual const fwrap_store_base *clone() const
00524 {
00525 return new func_store<void (ObjT::*)(BOOST_PP_ENUM_PARAMS(n, T))>(_m);
00526 }
00527
00528 virtual unsigned int arity() const
00529 {
00530 return n + 1;
00531 }
00532
00533 virtual fwrap_fn_type fn_type() const
00534 {
00535 return FWRAP_METHOD;
00536 }
00537
00538 virtual arg_info get_rv_info() const
00539 {
00540 return detail::arg_info_generator<void>::make_arg_info();
00541 }
00542
00543 virtual void get_arg_info(std::vector<arg_info>& vec) const
00544 {
00545 vec.clear();
00546 vec.push_back(detail::arg_info_generator<ObjT *>::make_arg_info());
00547 BOOST_PP_REPEAT(n, ARG_INFO_PUSH_BACK, vec)
00548 }
00549
00550 private:
00551 void (ObjT::*_m)(BOOST_PP_ENUM_PARAMS(n, T));
00552 };
00553
00554
00555
00556
00557
00558 template<typename ObjT
00559 BOOST_PP_COMMA_IF(n)
00560 BOOST_PP_ENUM_PARAMS(n, typename T)>
00561 class func_store<void (ObjT::*)(BOOST_PP_ENUM_PARAMS(n, T)) const>
00562 : public fwrap_store_base
00563 {
00564 public:
00565 explicit func_store(void (ObjT::*m)(BOOST_PP_ENUM_PARAMS(n, T)) const)
00566 : _m(m)
00567 {
00568 }
00569
00570 virtual val call(fwrap_args& args) const
00571 {
00572 if(args.size() != n + 1)
00573 {
00574 throw arity_mismatch_exception(n + 1, args.size());
00575 }
00576 const ObjT *o = eval::val_cast_ptr<const ObjT>(args[0]);
00577 (o->*_m)(BOOST_PP_ENUM(n, ARGS_PRINT_METHOD, args));
00578 return val();
00579 }
00580
00581 virtual const fwrap_store_base *clone() const
00582 {
00583 return new func_store<void (ObjT::*)(BOOST_PP_ENUM_PARAMS(n, T)) const>(_m);
00584 }
00585
00586 virtual unsigned int arity() const
00587 {
00588 return n + 1;
00589 }
00590
00591 virtual fwrap_fn_type fn_type() const
00592 {
00593 return FWRAP_CONST_METHOD;
00594 }
00595
00596 virtual arg_info get_rv_info() const
00597 {
00598 return detail::arg_info_generator<void>::make_arg_info();
00599 }
00600
00601 virtual void get_arg_info(std::vector<arg_info>& vec) const
00602 {
00603 vec.clear();
00604 vec.push_back(detail::arg_info_generator<const ObjT *>::make_arg_info());
00605 BOOST_PP_REPEAT(n, ARG_INFO_PUSH_BACK, vec)
00606 }
00607
00608 private:
00609 void (ObjT::*_m)(BOOST_PP_ENUM_PARAMS(n, T)) const;
00610 };
00611
00612
00613
00614
00615 # define ARGS_PRINT_CTOR(z, n, vec_name) detail::val_cast_ptr_or_ref<T ## n>::cast(vec_name[n])
00616
00617 template<typename ObjT
00618 BOOST_PP_COMMA_IF(n)
00619 BOOST_PP_ENUM_PARAMS(n, typename T)>
00620 class ctor_store<ObjT, void (*)(BOOST_PP_ENUM_PARAMS(n, T))> : public fwrap_store_base
00621 {
00622 public:
00623 ctor_store()
00624 {
00625 }
00626
00627 virtual val call(fwrap_args& args) const
00628 {
00629 if(args.size() != n)
00630 {
00631 throw arity_mismatch_exception(n, args.size());
00632 }
00633 ObjT *o = new ObjT(BOOST_PP_ENUM(n, ARGS_PRINT_CTOR, args));
00634 return val(o, TRANSFER_OWNERSHIP);
00635 }
00636
00637 virtual const fwrap_store_base *clone() const
00638 {
00639 return new ctor_store<ObjT, void (*)(BOOST_PP_ENUM_PARAMS(n, T))>();
00640 }
00641
00642 virtual unsigned int arity() const
00643 {
00644 return n;
00645 }
00646
00647 virtual fwrap_fn_type fn_type() const
00648 {
00649 return FWRAP_CONSTRUCTOR;
00650 }
00651
00652 virtual arg_info get_rv_info() const
00653 {
00654 return detail::arg_info_generator<ObjT *>::make_arg_info();
00655 }
00656
00657 virtual void get_arg_info(std::vector<arg_info>& vec) const
00658 {
00659 vec.clear();
00660 BOOST_PP_REPEAT(n, ARG_INFO_PUSH_BACK, vec)
00661 }
00662 };
00663
00664
00665
00666
00667
00668
00669 # if n == EVAL_FWRAP_MAX_NUM_OF_ARGS // all partial specializations completed
00670
00671 }
00672
00679 class fwrap
00680 {
00681 public:
00691 template<typename ObjT, typename T>
00692 static fwrap wrap_ctor()
00693 {
00694 return fwrap(new detail::ctor_store<ObjT, T>(), USE_PRIVATE_CONSTRUCTOR);
00695 }
00696
00697
00703 template<typename T>
00704 explicit fwrap(T fp)
00705 : _store(fp ? new detail::func_store<T>(fp) : 0)
00706 {
00707 }
00708
00709 fwrap()
00710 : _store(0)
00711 {
00712 }
00713
00714 fwrap(const fwrap& other)
00715 : _store(other._store ? other._store->clone() : 0)
00716 {
00717 }
00718
00719 void swap(fwrap& other)
00720 {
00721 std::swap(_store, other._store);
00722 }
00723
00724 fwrap& operator=(fwrap rhs)
00725 {
00726 rhs.swap(*this);
00727 return *this;
00728 }
00729
00733 bool is_null() const
00734 {
00735 return !_store;
00736 }
00737
00758 val operator()(fwrap_args& args) const
00759 {
00760 if(is_null())
00761 {
00762 throw null_ptr_exception("operator() on null fwrap");
00763 }
00764 return _store->call(args);
00765 }
00766
00768 unsigned int arity() const
00769 {
00770 if(is_null())
00771 {
00772 throw null_ptr_exception("arity of null fwrap");
00773 }
00774 return _store->arity();
00775 }
00776
00777 fwrap_fn_type fn_type() const
00778 {
00779 if(is_null())
00780 {
00781 throw null_ptr_exception("fn_type of null fwrap");
00782 }
00783 return _store->fn_type();
00784 }
00785
00786 arg_info get_rv_info() const
00787 {
00788 if(is_null())
00789 {
00790 throw null_ptr_exception("get_rv_info of null fwrap");
00791 }
00792 return _store->get_rv_info();
00793 }
00794
00796 void get_arg_info(std::vector<arg_info>& vec) const
00797 {
00798 if(is_null())
00799 {
00800 throw null_ptr_exception("get_arg_info of null fwrap");
00801 }
00802 _store->get_arg_info(vec);
00803 }
00804
00805 ~fwrap()
00806 {
00807 delete _store;
00808 }
00809 private:
00810 enum ctor_overload_resolution
00811 {
00812 USE_PRIVATE_CONSTRUCTOR
00813 };
00814
00815 explicit fwrap(const detail::fwrap_store_base *store, const ctor_overload_resolution&)
00816 : _store(store)
00817 {
00818 }
00819
00820 const detail::fwrap_store_base *_store;
00821 };
00822
00823 }
00824 # endif
00825
00826
00827 # undef ARGS_PRINT
00828 # undef ARGS_PRINT_METHOD
00829 # undef ARGS_PRINT_CTOR
00830 # undef ARG_INFO_PUSH_PACK
00831 # undef ObjT_ARG_INFO_PUSH_BACK
00832 # undef n
00833
00834 #endif // BOOST_PP_IS_ITERATING
00835
00836