Get libc++ on ubuntu 14.04 working
The std::is_member_function_pointer<> template is broken on this version of the libc++ standard library for const member functions. To get ChaiScript to work with this, we had to work around the use of automatically generated std::function wrappers in many cases. This actually cleaned up the code in a few places and muddied it up in one.
This commit is contained in:
parent
2f531355cd
commit
0ed9602ba9
@ -15,6 +15,12 @@
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#if defined( _LIBCPP_VERSION )
|
||||||
|
#define CHAISCRIPT_LIBCPP
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(_WIN32) || defined(__CYGWIN__)
|
#if defined(_WIN32) || defined(__CYGWIN__)
|
||||||
#define CHAISCRIPT_WINDOWS
|
#define CHAISCRIPT_WINDOWS
|
||||||
#endif
|
#endif
|
||||||
|
@ -14,63 +14,58 @@ namespace chaiscript
|
|||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
|
|
||||||
struct Placeholder
|
template<typename T>
|
||||||
{
|
T* get_pointer(T *t)
|
||||||
static std::tuple<decltype(std::placeholders::_1),decltype(std::placeholders::_2),decltype(std::placeholders::_3),decltype(std::placeholders::_4),decltype(std::placeholders::_5),decltype(std::placeholders::_6),decltype(std::placeholders::_7),decltype(std::placeholders::_8),decltype(std::placeholders::_9),decltype(std::placeholders::_10)> placeholder() {
|
{
|
||||||
return std::tuple<decltype(std::placeholders::_1),decltype(std::placeholders::_2),decltype(std::placeholders::_3),decltype(std::placeholders::_4),decltype(std::placeholders::_5),decltype(std::placeholders::_6),decltype(std::placeholders::_7),decltype(std::placeholders::_8),decltype(std::placeholders::_9),decltype(std::placeholders::_10)>(std::placeholders::_1,std::placeholders::_2,std::placeholders::_3,std::placeholders::_4,std::placeholders::_5,std::placeholders::_6,std::placeholders::_7,std::placeholders::_8,std::placeholders::_9,std::placeholders::_10);
|
return t;
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
template<int count, int maxcount, typename Sig>
|
template<typename T>
|
||||||
struct Bind_First
|
T* get_pointer(const std::reference_wrapper<T> &t)
|
||||||
{
|
{
|
||||||
template<typename F, typename ... InnerParams>
|
return &t.get();
|
||||||
static std::function<Sig> bind(F&& f, InnerParams ... innerparams)
|
}
|
||||||
{
|
|
||||||
return Bind_First<count - 1, maxcount, Sig>::bind(std::forward<F>(f), innerparams..., std::get<maxcount - count>(Placeholder::placeholder()));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<int maxcount, typename Sig>
|
|
||||||
struct Bind_First<0, maxcount, Sig>
|
|
||||||
{
|
|
||||||
template<typename F, typename ... InnerParams>
|
|
||||||
static std::function<Sig> bind(F&& f, InnerParams ... innerparams)
|
|
||||||
{
|
|
||||||
return std::bind(std::forward<F>(f), innerparams...);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
template<typename O, typename Ret, typename P1, typename ... Param>
|
template<typename O, typename Ret, typename P1, typename ... Param>
|
||||||
std::function<Ret (Param...)> bind_first(Ret (*f)(P1, Param...), O&& o)
|
std::function<Ret (Param...)> bind_first(Ret (*f)(P1, Param...), O&& o)
|
||||||
{
|
{
|
||||||
return Bind_First<sizeof...(Param), sizeof...(Param), Ret (Param...)>::bind(f, std::forward<O>(o));
|
return std::function<Ret (Param...)>(
|
||||||
|
[f, o](Param...param) -> Ret {
|
||||||
|
return f(std::forward<O>(o), std::forward<Param>(param)...);
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename O, typename Ret, typename Class, typename ... Param>
|
template<typename O, typename Ret, typename Class, typename ... Param>
|
||||||
std::function<Ret (Param...)> bind_first(Ret (Class::*f)(Param...), O&& o)
|
std::function<Ret (Param...)> bind_first(Ret (Class::*f)(Param...), O&& o)
|
||||||
{
|
{
|
||||||
return Bind_First<sizeof...(Param), sizeof...(Param), Ret (Param...)>::bind(f, std::forward<O>(o));
|
return std::function<Ret (Param...)>(
|
||||||
|
[f, o](Param...param) -> Ret {
|
||||||
|
return (get_pointer(o)->*f)(std::forward<Param>(param)...);
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename O, typename Ret, typename Class, typename ... Param>
|
template<typename O, typename Ret, typename Class, typename ... Param>
|
||||||
std::function<Ret (Param...)> bind_first(Ret (Class::*f)(Param...) const, O&& o)
|
std::function<Ret (Param...)> bind_first(Ret (Class::*f)(Param...) const, O&& o)
|
||||||
{
|
{
|
||||||
return Bind_First<sizeof...(Param), sizeof...(Param), Ret (Param...)>::bind(f, std::forward<O>(o));
|
return std::function<Ret (Param...)>(
|
||||||
|
[f, o](Param...param) -> Ret {
|
||||||
|
return (get_pointer(o)->*f)(std::forward<Param>(param)...);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename O, typename Ret, typename P1, typename ... Param>
|
template<typename O, typename Ret, typename P1, typename ... Param>
|
||||||
std::function<Ret (Param...)> bind_first(const std::function<Ret (P1, Param...)> &f, O&& o)
|
std::function<Ret (Param...)> bind_first(const std::function<Ret (P1, Param...)> &f, O&& o)
|
||||||
{
|
{
|
||||||
return Bind_First<sizeof...(Param), sizeof...(Param), Ret (Param...)>::bind(f, std::forward<O>(o));
|
return std::function<Ret (Param...)>(
|
||||||
|
[f, o](Param...param) -> Ret {
|
||||||
|
return f(o, std::forward<Param>(param)...);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename O, typename Ret, typename P1, typename ... Param>
|
|
||||||
std::function<Ret (Param...)> bind_first(std::function<Ret (P1, Param...)> &&f, O&& o)
|
|
||||||
{
|
|
||||||
return Bind_First<sizeof...(Param), sizeof...(Param), Ret (Param...)>::bind(std::move(f), std::forward<O>(o));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -357,7 +357,9 @@ namespace chaiscript
|
|||||||
template<typename Function>
|
template<typename Function>
|
||||||
static std::function<std::vector<Boxed_Value> (const dispatch::Proxy_Function_Base*)> return_boxed_value_vector(const Function &f)
|
static std::function<std::vector<Boxed_Value> (const dispatch::Proxy_Function_Base*)> return_boxed_value_vector(const Function &f)
|
||||||
{
|
{
|
||||||
return std::bind(&do_return_boxed_value_vector<Function>, f, std::placeholders::_1);
|
return [f](const dispatch::Proxy_Function_Base *b) {
|
||||||
|
return do_return_boxed_value_vector(f, b);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -247,7 +247,6 @@ namespace chaiscript
|
|||||||
{
|
{
|
||||||
// cppcheck-suppress syntaxError
|
// cppcheck-suppress syntaxError
|
||||||
typedef typename ContainerType::reference(ContainerType::*indexoper)(size_t);
|
typedef typename ContainerType::reference(ContainerType::*indexoper)(size_t);
|
||||||
typedef typename ContainerType::const_reference(ContainerType::*constindexoper)(size_t) const;
|
|
||||||
|
|
||||||
//In the interest of runtime safety for the m, we prefer the at() method for [] access,
|
//In the interest of runtime safety for the m, we prefer the at() method for [] access,
|
||||||
//to throw an exception in an out of bounds condition.
|
//to throw an exception in an out of bounds condition.
|
||||||
@ -255,8 +254,10 @@ namespace chaiscript
|
|||||||
fun(std::function<typename ContainerType::reference (ContainerType *, int)>
|
fun(std::function<typename ContainerType::reference (ContainerType *, int)>
|
||||||
(std::mem_fn(static_cast<indexoper>(&ContainerType::at)))), "[]");
|
(std::mem_fn(static_cast<indexoper>(&ContainerType::at)))), "[]");
|
||||||
m->add(
|
m->add(
|
||||||
fun(std::function<typename ContainerType::const_reference (const ContainerType *, int)>
|
fun<typename ContainerType::const_reference (const ContainerType &, int)>(
|
||||||
(std::mem_fn(static_cast<constindexoper>(&ContainerType::at)))), "[]");
|
[](const ContainerType &c, int index) -> typename ContainerType::const_reference {
|
||||||
|
return c.at(index);
|
||||||
|
}), "[]");
|
||||||
|
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
@ -52,36 +52,17 @@ namespace chaiscript
|
|||||||
template<typename Ret, typename Class, typename ... Args>
|
template<typename Ret, typename Class, typename ... Args>
|
||||||
std::function<Ret (const Class &, Args...) > to_function(Ret (Class::*func)(Args...) const)
|
std::function<Ret (const Class &, Args...) > to_function(Ret (Class::*func)(Args...) const)
|
||||||
{
|
{
|
||||||
#ifdef CHAISCRIPT_MSVC
|
#if defined(CHAISCRIPT_MSVC) || defined(CHAISCRIPT_LIBCPP)
|
||||||
/// \todo this std::mem_fn wrap shouldn't be necessary but type conversions for
|
/// \todo this std::mem_fn wrap shouldn't be necessary but type conversions for
|
||||||
/// std::function for member function pointers seems to be broken in MSVC
|
/// std::function for member function pointers seems to be broken in MSVC
|
||||||
return std::function<Ret(const Class &, Args...)>(std::mem_fn(func));
|
return std::function<Ret (const Class &, Args...)>([func](const Class &o, Args... args)->Ret {
|
||||||
|
return (o.*func)(std::forward<Args>(args)...);
|
||||||
|
});
|
||||||
#else
|
#else
|
||||||
return std::function<Ret(const Class &, Args...)>(func);
|
return std::function<Ret(const Class &, Args...)>(func);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
template<bool Object>
|
|
||||||
struct Fun_Helper
|
|
||||||
{
|
|
||||||
template<typename T>
|
|
||||||
static Proxy_Function go(T t)
|
|
||||||
{
|
|
||||||
/// \todo is it possible to reduce the number of templates generated here?
|
|
||||||
return Proxy_Function(
|
|
||||||
static_cast<dispatch::Proxy_Function_Impl_Base *>(new Proxy_Function_Impl<typename FunctionSignature<decltype(to_function(t)) >::Signature>(to_function(t))));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<>
|
|
||||||
struct Fun_Helper<true>
|
|
||||||
{
|
|
||||||
template<typename T, typename Class>
|
|
||||||
static Proxy_Function go(T Class::* m)
|
|
||||||
{
|
|
||||||
return Proxy_Function(new Attribute_Access<T, Class>(m));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -106,9 +87,31 @@ namespace chaiscript
|
|||||||
///
|
///
|
||||||
/// \sa \ref adding_functions
|
/// \sa \ref adding_functions
|
||||||
template<typename T>
|
template<typename T>
|
||||||
Proxy_Function fun(T t)
|
Proxy_Function fun(const T &t)
|
||||||
{
|
{
|
||||||
return dispatch::detail::Fun_Helper<std::is_member_object_pointer<T>::value>::go(t);
|
return Proxy_Function(
|
||||||
|
static_cast<dispatch::Proxy_Function_Impl_Base *>(new dispatch::Proxy_Function_Impl<typename dispatch::detail::FunctionSignature<decltype(dispatch::detail::to_function(t)) >::Signature>(dispatch::detail::to_function(t))));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Ret, typename Class, typename ... Param>
|
||||||
|
Proxy_Function fun(Ret (Class::*func)(Param...) const)
|
||||||
|
{
|
||||||
|
return Proxy_Function(
|
||||||
|
static_cast<dispatch::Proxy_Function_Impl_Base *>(new dispatch::Proxy_Function_Impl<typename dispatch::detail::FunctionSignature<decltype(dispatch::detail::to_function(func)) >::Signature>(dispatch::detail::to_function(func))));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Ret, typename Class, typename ... Param>
|
||||||
|
Proxy_Function fun(Ret (Class::*func)(Param...))
|
||||||
|
{
|
||||||
|
return Proxy_Function(
|
||||||
|
static_cast<dispatch::Proxy_Function_Impl_Base *>(new dispatch::Proxy_Function_Impl<typename dispatch::detail::FunctionSignature<decltype(dispatch::detail::to_function(func)) >::Signature>(dispatch::detail::to_function(func))));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<typename T, typename Class /*, typename = typename std::enable_if<std::is_member_object_pointer<T>::value>::type*/>
|
||||||
|
Proxy_Function fun(T Class::* m /*, typename std::enable_if<std::is_member_object_pointer<T>::value>::type* = 0*/ )
|
||||||
|
{
|
||||||
|
return Proxy_Function(new dispatch::Attribute_Access<T, Class>(m));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -149,9 +152,9 @@ namespace chaiscript
|
|||||||
///
|
///
|
||||||
/// \sa \ref adding_functions
|
/// \sa \ref adding_functions
|
||||||
template<typename T, typename Q>
|
template<typename T, typename Q>
|
||||||
Proxy_Function fun(T t, const Q &q)
|
Proxy_Function fun(T &&t, const Q &q)
|
||||||
{
|
{
|
||||||
return fun(detail::bind_first(t, q));
|
return fun(detail::bind_first(std::forward<T>(t), q));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Creates a new Proxy_Function object from a free function or member function and binds the first and second parameters of it
|
/// \brief Creates a new Proxy_Function object from a free function or member function and binds the first and second parameters of it
|
||||||
@ -175,9 +178,9 @@ namespace chaiscript
|
|||||||
///
|
///
|
||||||
/// \sa \ref adding_functions
|
/// \sa \ref adding_functions
|
||||||
template<typename T, typename Q, typename R>
|
template<typename T, typename Q, typename R>
|
||||||
Proxy_Function fun(T t, const Q &q, const R &r)
|
Proxy_Function fun(T &&t, Q &&q, R &&r)
|
||||||
{
|
{
|
||||||
return fun(detail::bind_first(detail::bind_first(t, q), r));
|
return fun(detail::bind_first(detail::bind_first(std::forward<T>(t), std::forward<Q>(q)), std::forward<R>(r)));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -367,7 +367,13 @@ namespace chaiscript
|
|||||||
[this](const std::vector<Boxed_Value> &t_params) {
|
[this](const std::vector<Boxed_Value> &t_params) {
|
||||||
return m_engine.call_exists(t_params);
|
return m_engine.call_exists(t_params);
|
||||||
})), "call_exists");
|
})), "call_exists");
|
||||||
m_engine.add(fun<Boxed_Value (const dispatch::Proxy_Function_Base *, const std::vector<Boxed_Value> &)>(std::bind(&chaiscript::dispatch::Proxy_Function_Base::operator(), std::placeholders::_1, std::placeholders::_2, std::ref(m_engine.conversions()))), "call");
|
|
||||||
|
// m_engine.add(fun<Boxed_Value (const dispatch::Proxy_Function_Base *, const std::vector<Boxed_Value> &)>(std::bind(&chaiscript::dispatch::Proxy_Function_Base::operator(), std::placeholders::_1, std::placeholders::_2, std::ref(m_engine.conversions()))), "call");
|
||||||
|
//
|
||||||
|
m_engine.add(fun<Boxed_Value (const dispatch::Proxy_Function_Base &, const std::vector<Boxed_Value> &)>(
|
||||||
|
[=](const dispatch::Proxy_Function_Base &t_fun, const std::vector<Boxed_Value> &t_params) {
|
||||||
|
return t_fun(t_params, this->m_engine.conversions());
|
||||||
|
}), "call");
|
||||||
|
|
||||||
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::get_type_name, std::ref(m_engine)), "name");
|
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::get_type_name, std::ref(m_engine)), "name");
|
||||||
|
|
||||||
|
@ -712,7 +712,7 @@ namespace chaiscript
|
|||||||
|
|
||||||
fpp.save_params(params);
|
fpp.save_params(params);
|
||||||
|
|
||||||
std::string fun_name = [&](){
|
std::string fun_name = [&]()->std::string{
|
||||||
if ((this->children[i]->identifier == AST_Node_Type::Fun_Call) || (this->children[i]->identifier == AST_Node_Type::Array_Call)) {
|
if ((this->children[i]->identifier == AST_Node_Type::Fun_Call) || (this->children[i]->identifier == AST_Node_Type::Array_Call)) {
|
||||||
return this->children[i]->children[0]->text;
|
return this->children[i]->children[0]->text;
|
||||||
}
|
}
|
||||||
|
@ -617,7 +617,7 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const size_t size = [&](){
|
const size_t size = [&]()->size_t{
|
||||||
if (longlong_)
|
if (longlong_)
|
||||||
{
|
{
|
||||||
return sizeof(int64_t) * 8;
|
return sizeof(int64_t) * 8;
|
||||||
@ -800,7 +800,7 @@ namespace chaiscript
|
|||||||
const auto prev_line = m_line;
|
const auto prev_line = m_line;
|
||||||
if (Id_()) {
|
if (Id_()) {
|
||||||
m_match_stack.push_back(std::make_shared<eval::Id_AST_Node>(
|
m_match_stack.push_back(std::make_shared<eval::Id_AST_Node>(
|
||||||
[&](){
|
[&]()->std::string{
|
||||||
if (*start == '`') {
|
if (*start == '`') {
|
||||||
//Id Literal
|
//Id Literal
|
||||||
return std::string(start+1, m_input_pos-1);
|
return std::string(start+1, m_input_pos-1);
|
||||||
|
@ -76,7 +76,7 @@ int main(int /*argc*/, char * /*argv*/[]) {
|
|||||||
chai.add(var(&system), "system");
|
chai.add(var(&system), "system");
|
||||||
|
|
||||||
//Add a bound callback method
|
//Add a bound callback method
|
||||||
chai.add(fun(&System::add_callback, system), "add_callback_bound");
|
chai.add(fun(&System::add_callback, std::ref(system)), "add_callback_bound");
|
||||||
|
|
||||||
//Register the two methods of the System structure.
|
//Register the two methods of the System structure.
|
||||||
chai.add(fun(&System::add_callback), "add_callback");
|
chai.add(fun(&System::add_callback), "add_callback");
|
||||||
|
@ -68,7 +68,9 @@ int main()
|
|||||||
std::vector<std::shared_ptr<std::thread> > threads;
|
std::vector<std::shared_ptr<std::thread> > threads;
|
||||||
|
|
||||||
// Ensure at least two, but say only 7 on an 8 core processor
|
// Ensure at least two, but say only 7 on an 8 core processor
|
||||||
int num_threads = std::max(std::thread::hardware_concurrency() - 1, 2u);
|
int num_threads = std::max(static_cast<int>(std::thread::hardware_concurrency()) - 1, 2);
|
||||||
|
|
||||||
|
std::cout << "Num threads: " << num_threads << '\n';
|
||||||
|
|
||||||
for (int i = 0; i < num_threads; ++i)
|
for (int i = 0; i < num_threads; ++i)
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user