Added support for const attribute access

This commit is contained in:
Jason Turner
2009-11-14 19:02:00 +00:00
parent cca477dae6
commit 9dddb49850
2 changed files with 102 additions and 39 deletions

View File

@@ -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<Boxed_Value>())
|| ti.bare_equal(user_type<Boxed_POD_Value>())
@@ -407,6 +408,81 @@ namespace chaiscript
Func *m_dummy_func;
};
/**
* Attribute getter Proxy_Function implementation
*/
template<typename T, typename Class>
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<T, Class> &aa
= dynamic_cast<const Attribute_Access<T, Class> &>(t_func);
return m_attr == aa.m_attr;
} catch (const std::bad_cast &) {
return false;
}
}
virtual Boxed_Value operator()(const std::vector<Boxed_Value> &params) const
{
if (params.size() == 1)
{
const Boxed_Value &bv = params[0];
if (bv.is_const())
{
const Class *o = boxed_cast<const Class *>(bv);
return Boxed_Value( boost::ref(o->*m_attr) );
} else {
Class *o = boxed_cast<Class *>(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<Boxed_Value> &vals) const
{
if (vals.size() != 1)
{
return false;
}
return vals[0].get_type_info().bare_equal(user_type<Class>());
}
virtual std::string annotation() const
{
return "";
}
private:
static std::vector<Type_Info> param_types()
{
std::vector<Type_Info> v;
v.push_back(user_type<T>());
v.push_back(user_type<Class>());
return v;
}
T Class::* m_attr;
};
/**
* Exception thrown in the case that a multi method dispatch fails
* because no matching function was found

View File

@@ -13,74 +13,61 @@
#include <boost/bind.hpp>
#include <boost/function_types/components.hpp>
#include <boost/function_types/function_type.hpp>
#include <boost/function_types/is_member_object_pointer.hpp>
namespace chaiscript
{
namespace detail
{
/**
* Helper function for register_member function
*/
template<typename T, typename Class>
T &get_member(T Class::* m, Class *obj)
template<bool Object>
struct Fun_Helper
{
return (obj->*m);
}
template<typename T>
static Proxy_Function go(T t)
{
return Proxy_Function(
new Proxy_Function_Impl<
typename boost::function_types::function_type<boost::function_types::components<T> >::type> (
boost::function<
typename boost::function_types::function_type<boost::function_types::components<T> >::type
>(t)));
}
};
template<typename T>
boost::function<T> mk_boost_fun(const boost::function<T> &f)
{
return f;
}
template<typename T>
boost::function<
typename boost::function_types::function_type<boost::function_types::components<T> >::type
> mk_boost_fun(T t)
{
return
boost::function<
typename boost::function_types::function_type<boost::function_types::components<T> >::type
>(t);
}
template<typename T, typename Class>
Proxy_Function fun_helper(T Class::* m)
template<>
struct Fun_Helper<true>
{
return fun_helper(boost::function<T& (Class *)>(boost::bind(&detail::get_member<T, Class>, m, _1)));
}
template<typename T, typename Class>
static Proxy_Function go(T Class::* m)
{
return Proxy_Function(new Attribute_Access<T, Class>(m));
}
};
template<typename T>
Proxy_Function fun_helper(const boost::function<T> &f)
{
return Proxy_Function(new Proxy_Function_Impl<T>(f));
}
}
template<typename T>
Proxy_Function fun(const boost::function<T> &f)
{
return detail::fun_helper(f);
return Proxy_Function(new Proxy_Function_Impl<T>(f));
}
template<typename T>
Proxy_Function fun(T t)
{
return detail::fun_helper(detail::mk_boost_fun(t));
return detail::Fun_Helper<boost::function_types::is_member_object_pointer<T>::value>::go(t);
}
template<typename T, typename Q>
Proxy_Function fun(T t, const Q &q)
{
return detail::fun_helper(bind_first(t, q));
return fun(bind_first(t, q));
}
template<typename T, typename Q, typename R>
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));
}
}