diff --git a/include/chaiscript/dispatchkit/proxy_functions.hpp b/include/chaiscript/dispatchkit/proxy_functions.hpp index 227ec454..eb378227 100644 --- a/include/chaiscript/dispatchkit/proxy_functions.hpp +++ b/include/chaiscript/dispatchkit/proxy_functions.hpp @@ -92,6 +92,7 @@ namespace chaiscript const Type_Info &ti = types[1]; + if (ti.is_undef() || vals[0].get_type_info().is_undef() || ti.bare_equal(user_type()) || ti.bare_equal(user_type()) @@ -407,6 +408,81 @@ namespace chaiscript Func *m_dummy_func; }; + /** + * Attribute getter Proxy_Function implementation + */ + template + class Attribute_Access : public Proxy_Function_Base + { + public: + Attribute_Access(T Class::* t_attr) + : Proxy_Function_Base(param_types()), + m_attr(t_attr) + { + } + + virtual ~Attribute_Access() {} + + virtual bool operator==(const Proxy_Function_Base &t_func) const + { + try { + const Attribute_Access &aa + = dynamic_cast &>(t_func); + return m_attr == aa.m_attr; + } catch (const std::bad_cast &) { + return false; + } + } + + virtual Boxed_Value operator()(const std::vector ¶ms) const + { + if (params.size() == 1) + { + const Boxed_Value &bv = params[0]; + if (bv.is_const()) + { + const Class *o = boxed_cast(bv); + return Boxed_Value( boost::ref(o->*m_attr) ); + } else { + Class *o = boxed_cast(bv); + return Boxed_Value( boost::ref(o->*m_attr) ); + } + } else { + throw arity_error(params.size(), 1); + } + } + + virtual int get_arity() const + { + return 1; + } + + virtual bool call_match(const std::vector &vals) const + { + if (vals.size() != 1) + { + return false; + } + + return vals[0].get_type_info().bare_equal(user_type()); + } + + virtual std::string annotation() const + { + return ""; + } + + private: + static std::vector param_types() + { + std::vector v; + v.push_back(user_type()); + v.push_back(user_type()); + return v; + } + T Class::* m_attr; + }; + /** * Exception thrown in the case that a multi method dispatch fails * because no matching function was found diff --git a/include/chaiscript/dispatchkit/register_function.hpp b/include/chaiscript/dispatchkit/register_function.hpp index bd9da435..5daea436 100644 --- a/include/chaiscript/dispatchkit/register_function.hpp +++ b/include/chaiscript/dispatchkit/register_function.hpp @@ -13,74 +13,61 @@ #include #include #include +#include namespace chaiscript { namespace detail { - /** - * Helper function for register_member function - */ - template - T &get_member(T Class::* m, Class *obj) + template + struct Fun_Helper { - return (obj->*m); - } + template + static Proxy_Function go(T t) + { + return Proxy_Function( + new Proxy_Function_Impl< + typename boost::function_types::function_type >::type> ( + boost::function< + typename boost::function_types::function_type >::type + >(t))); + } + }; - template - boost::function mk_boost_fun(const boost::function &f) - { - return f; - } - - template - boost::function< - typename boost::function_types::function_type >::type - > mk_boost_fun(T t) - { - return - boost::function< - typename boost::function_types::function_type >::type - >(t); - } - - template - Proxy_Function fun_helper(T Class::* m) + template<> + struct Fun_Helper { - return fun_helper(boost::function(boost::bind(&detail::get_member, m, _1))); - } + template + static Proxy_Function go(T Class::* m) + { + return Proxy_Function(new Attribute_Access(m)); + } + }; - - template - Proxy_Function fun_helper(const boost::function &f) - { - return Proxy_Function(new Proxy_Function_Impl(f)); - } } template Proxy_Function fun(const boost::function &f) { - return detail::fun_helper(f); + return Proxy_Function(new Proxy_Function_Impl(f)); } template Proxy_Function fun(T t) { - return detail::fun_helper(detail::mk_boost_fun(t)); + return detail::Fun_Helper::value>::go(t); } - template Proxy_Function fun(T t, const Q &q) { - return detail::fun_helper(bind_first(t, q)); + return fun(bind_first(t, q)); } template Proxy_Function fun(T t, const Q &q, const R &r) { - return detail::fun_helper(bind_first(bind_first(t, q), r)); + return fun(bind_first(bind_first(t, q), r)); } }