From 0ed9602ba965ebba4fe724f8baa41da37debaffa Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Tue, 21 Apr 2015 12:01:29 -0600 Subject: [PATCH] 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. --- include/chaiscript/chaiscript_defines.hpp | 6 ++ include/chaiscript/dispatchkit/bind_first.hpp | 61 +++++++++---------- include/chaiscript/dispatchkit/bootstrap.hpp | 4 +- .../chaiscript/dispatchkit/bootstrap_stl.hpp | 7 ++- .../dispatchkit/register_function.hpp | 61 ++++++++++--------- .../chaiscript/language/chaiscript_engine.hpp | 8 ++- .../chaiscript/language/chaiscript_eval.hpp | 2 +- .../chaiscript/language/chaiscript_parser.hpp | 4 +- samples/example.cpp | 2 +- unittests/multithreaded_test.cpp | 4 +- 10 files changed, 87 insertions(+), 72 deletions(-) diff --git a/include/chaiscript/chaiscript_defines.hpp b/include/chaiscript/chaiscript_defines.hpp index 811b1bd..09930c5 100644 --- a/include/chaiscript/chaiscript_defines.hpp +++ b/include/chaiscript/chaiscript_defines.hpp @@ -15,6 +15,12 @@ #endif #endif +#include + +#if defined( _LIBCPP_VERSION ) +#define CHAISCRIPT_LIBCPP +#endif + #if defined(_WIN32) || defined(__CYGWIN__) #define CHAISCRIPT_WINDOWS #endif diff --git a/include/chaiscript/dispatchkit/bind_first.hpp b/include/chaiscript/dispatchkit/bind_first.hpp index 92675e1..5cd61da 100644 --- a/include/chaiscript/dispatchkit/bind_first.hpp +++ b/include/chaiscript/dispatchkit/bind_first.hpp @@ -14,63 +14,58 @@ namespace chaiscript namespace detail { - struct Placeholder - { - static std::tuple placeholder() { - return std::tuple(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); + template + T* get_pointer(T *t) + { + return t; } - }; - template - struct Bind_First + template + T* get_pointer(const std::reference_wrapper &t) { - template - static std::function bind(F&& f, InnerParams ... innerparams) - { - return Bind_First::bind(std::forward(f), innerparams..., std::get(Placeholder::placeholder())); - } - }; - - template - struct Bind_First<0, maxcount, Sig> - { - template - static std::function bind(F&& f, InnerParams ... innerparams) - { - return std::bind(std::forward(f), innerparams...); - } - }; - + return &t.get(); + } template std::function bind_first(Ret (*f)(P1, Param...), O&& o) { - return Bind_First::bind(f, std::forward(o)); + return std::function( + [f, o](Param...param) -> Ret { + return f(std::forward(o), std::forward(param)...); + } + ); } template std::function bind_first(Ret (Class::*f)(Param...), O&& o) { - return Bind_First::bind(f, std::forward(o)); + return std::function( + [f, o](Param...param) -> Ret { + return (get_pointer(o)->*f)(std::forward(param)...); + } + ); } template std::function bind_first(Ret (Class::*f)(Param...) const, O&& o) { - return Bind_First::bind(f, std::forward(o)); + return std::function( + [f, o](Param...param) -> Ret { + return (get_pointer(o)->*f)(std::forward(param)...); + } + ); + } template std::function bind_first(const std::function &f, O&& o) { - return Bind_First::bind(f, std::forward(o)); + return std::function( + [f, o](Param...param) -> Ret { + return f(o, std::forward(param)...); + }); } - template - std::function bind_first(std::function &&f, O&& o) - { - return Bind_First::bind(std::move(f), std::forward(o)); - } } } diff --git a/include/chaiscript/dispatchkit/bootstrap.hpp b/include/chaiscript/dispatchkit/bootstrap.hpp index 32c11c1..302c7e1 100644 --- a/include/chaiscript/dispatchkit/bootstrap.hpp +++ b/include/chaiscript/dispatchkit/bootstrap.hpp @@ -357,7 +357,9 @@ namespace chaiscript template static std::function (const dispatch::Proxy_Function_Base*)> return_boxed_value_vector(const Function &f) { - return std::bind(&do_return_boxed_value_vector, f, std::placeholders::_1); + return [f](const dispatch::Proxy_Function_Base *b) { + return do_return_boxed_value_vector(f, b); + }; } diff --git a/include/chaiscript/dispatchkit/bootstrap_stl.hpp b/include/chaiscript/dispatchkit/bootstrap_stl.hpp index cc4219c..82e9f7a 100644 --- a/include/chaiscript/dispatchkit/bootstrap_stl.hpp +++ b/include/chaiscript/dispatchkit/bootstrap_stl.hpp @@ -247,7 +247,6 @@ namespace chaiscript { // cppcheck-suppress syntaxError 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, //to throw an exception in an out of bounds condition. @@ -255,8 +254,10 @@ namespace chaiscript fun(std::function (std::mem_fn(static_cast(&ContainerType::at)))), "[]"); m->add( - fun(std::function - (std::mem_fn(static_cast(&ContainerType::at)))), "[]"); + fun( + [](const ContainerType &c, int index) -> typename ContainerType::const_reference { + return c.at(index); + }), "[]"); return m; } diff --git a/include/chaiscript/dispatchkit/register_function.hpp b/include/chaiscript/dispatchkit/register_function.hpp index 7c4f4a8..8dd51f6 100644 --- a/include/chaiscript/dispatchkit/register_function.hpp +++ b/include/chaiscript/dispatchkit/register_function.hpp @@ -52,36 +52,17 @@ namespace chaiscript template std::function 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 /// std::function for member function pointers seems to be broken in MSVC - return std::function(std::mem_fn(func)); + return std::function([func](const Class &o, Args... args)->Ret { + return (o.*func)(std::forward(args)...); + }); #else return std::function(func); #endif } - template - struct Fun_Helper - { - template - static Proxy_Function go(T t) - { - /// \todo is it possible to reduce the number of templates generated here? - return Proxy_Function( - static_cast(new Proxy_Function_Impl::Signature>(to_function(t)))); - } - }; - - template<> - struct Fun_Helper - { - template - static Proxy_Function go(T Class::* m) - { - return Proxy_Function(new Attribute_Access(m)); - } - }; } } @@ -106,9 +87,31 @@ namespace chaiscript /// /// \sa \ref adding_functions template - Proxy_Function fun(T t) + Proxy_Function fun(const T &t) { - return dispatch::detail::Fun_Helper::value>::go(t); + return Proxy_Function( + static_cast(new dispatch::Proxy_Function_Impl::Signature>(dispatch::detail::to_function(t)))); + } + + template + Proxy_Function fun(Ret (Class::*func)(Param...) const) + { + return Proxy_Function( + static_cast(new dispatch::Proxy_Function_Impl::Signature>(dispatch::detail::to_function(func)))); + } + + template + Proxy_Function fun(Ret (Class::*func)(Param...)) + { + return Proxy_Function( + static_cast(new dispatch::Proxy_Function_Impl::Signature>(dispatch::detail::to_function(func)))); + } + + + template::value>::type*/> + Proxy_Function fun(T Class::* m /*, typename std::enable_if::value>::type* = 0*/ ) + { + return Proxy_Function(new dispatch::Attribute_Access(m)); } @@ -149,9 +152,9 @@ namespace chaiscript /// /// \sa \ref adding_functions template - 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), q)); } /// \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 template - 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), std::forward(q)), std::forward(r))); } } diff --git a/include/chaiscript/language/chaiscript_engine.hpp b/include/chaiscript/language/chaiscript_engine.hpp index d65badd..69eac31 100644 --- a/include/chaiscript/language/chaiscript_engine.hpp +++ b/include/chaiscript/language/chaiscript_engine.hpp @@ -367,7 +367,13 @@ namespace chaiscript [this](const std::vector &t_params) { return m_engine.call_exists(t_params); })), "call_exists"); - m_engine.add(fun &)>(std::bind(&chaiscript::dispatch::Proxy_Function_Base::operator(), std::placeholders::_1, std::placeholders::_2, std::ref(m_engine.conversions()))), "call"); + +// m_engine.add(fun &)>(std::bind(&chaiscript::dispatch::Proxy_Function_Base::operator(), std::placeholders::_1, std::placeholders::_2, std::ref(m_engine.conversions()))), "call"); +// + m_engine.add(fun &)>( + [=](const dispatch::Proxy_Function_Base &t_fun, const std::vector &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"); diff --git a/include/chaiscript/language/chaiscript_eval.hpp b/include/chaiscript/language/chaiscript_eval.hpp index 59e09ba..8a0f897 100644 --- a/include/chaiscript/language/chaiscript_eval.hpp +++ b/include/chaiscript/language/chaiscript_eval.hpp @@ -712,7 +712,7 @@ namespace chaiscript 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)) { return this->children[i]->children[0]->text; } diff --git a/include/chaiscript/language/chaiscript_parser.hpp b/include/chaiscript/language/chaiscript_parser.hpp index 73a33e2..66ea3f4 100644 --- a/include/chaiscript/language/chaiscript_parser.hpp +++ b/include/chaiscript/language/chaiscript_parser.hpp @@ -617,7 +617,7 @@ namespace chaiscript } - const size_t size = [&](){ + const size_t size = [&]()->size_t{ if (longlong_) { return sizeof(int64_t) * 8; @@ -800,7 +800,7 @@ namespace chaiscript const auto prev_line = m_line; if (Id_()) { m_match_stack.push_back(std::make_shared( - [&](){ + [&]()->std::string{ if (*start == '`') { //Id Literal return std::string(start+1, m_input_pos-1); diff --git a/samples/example.cpp b/samples/example.cpp index 6d4d4d0..507c5c0 100644 --- a/samples/example.cpp +++ b/samples/example.cpp @@ -76,7 +76,7 @@ int main(int /*argc*/, char * /*argv*/[]) { chai.add(var(&system), "system"); //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. chai.add(fun(&System::add_callback), "add_callback"); diff --git a/unittests/multithreaded_test.cpp b/unittests/multithreaded_test.cpp index 0a6ac39..9b4d6a5 100644 --- a/unittests/multithreaded_test.cpp +++ b/unittests/multithreaded_test.cpp @@ -68,7 +68,9 @@ int main() std::vector > threads; // 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(std::thread::hardware_concurrency()) - 1, 2); + + std::cout << "Num threads: " << num_threads << '\n'; for (int i = 0; i < num_threads; ++i) {