Added support for const attribute access
This commit is contained in:
@@ -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> ¶ms) 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
|
||||
|
@@ -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));
|
||||
}
|
||||
|
||||
}
|
||||
|
Reference in New Issue
Block a user