diff --git a/sol.hpp b/sol.hpp index ad511394..ce093f66 100644 --- a/sol.hpp +++ b/sol.hpp @@ -25,6 +25,5 @@ #include "sol/state.hpp" #include "sol/object.hpp" #include "sol/function.hpp" -#include "sol/container.hpp" #endif // SOL_HPP diff --git a/sol/container.hpp b/sol/container.hpp deleted file mode 100644 index b1432ea3..00000000 --- a/sol/container.hpp +++ /dev/null @@ -1,106 +0,0 @@ -#ifndef SOL_CONTAINER_HPP -#define SOL_CONTAINER_HPP - -#include "userdata.hpp" - -namespace sol { - -template -struct container { - typedef typename std::conditional::value, Tc, Unqualified>::type T; - typedef Unqualified().begin()))> value_type; - T cont; - - template - container (Args&&... args) : cont(std::forward(args)...){ - - } - - operator T& () const { - return cont; - } - - void set(std::ptrdiff_t i, const value_type& value) { - cont[ i ] = value; - } - - value_type& get(std::ptrdiff_t i) { - return cont[ i ]; - } - - std::size_t size() const { - return cont.size(); - } - -}; - -template -struct container>::value>::type> { - typedef typename std::conditional::value, Tc, Decay>::type T; - typedef Unqualified().begin())).first)> key_type; - typedef Unqualified().begin())).second)> value_type; - T cont; - - template - container (Args&&... args) : cont(std::forward(args)...){ - - } - - operator T& () const { - return cont; - } - - void set(key_type i, const value_type& value) { - cont[ i ] = value; - } - - value_type& get(key_type i) { - return cont.at(i); - } - - std::size_t size() const { - return cont.size(); - } -}; - -namespace stack { -template -struct pusher::value>::type> { - static void push(lua_State* L, const T& cont) { - typedef container container_t; - // todo: NEED to find a different way of handling this... - static std::vector> classes{}; - userdata classdata(default_constructor, - "__index", &container_t::get, - "__newindex", &container_t::set, - "__len", &container_t::size); - classes.emplace_back(std::make_shared>(std::move(classdata))); - auto&& ptr = classes.back(); - auto udata = std::static_pointer_cast>(ptr); - stack::push(L, *udata); - - container_t* c = static_cast(lua_newuserdata(L, sizeof(container_t))); - std::allocator alloc{}; - alloc.construct(c, cont); - - auto&& meta = userdata_traits::metatable; - if (luaL_newmetatable(L, std::addressof(meta[0])) == 1) { - std::string err("metatable not defined for "); - err += meta; - throw error(err); - } - lua_setmetatable(L, -2); - } -}; - -template -struct getter::value>::type> { - static Unqualified& get(lua_State* L, int index = -1) { - typedef container> container_t; - container_t& data = stack::get(L, index); - return data.cont; - } -}; -} // stack -} // sol -#endif // SOL_CONTAINER_HPP diff --git a/sol/function_types.hpp b/sol/function_types.hpp index 2f6ae30e..fe255fe8 100644 --- a/sol/function_types.hpp +++ b/sol/function_types.hpp @@ -83,7 +83,7 @@ struct static_function { return_type r = stack::get_call(L, fx, t); std::ptrdiff_t nargs = sizeof...(Args); lua_pop(L, nargs); - stack::push(L, std::move(r)); + stack::push(L, std::forward(r)); return sizeof...(Ret); } diff --git a/sol/stack.hpp b/sol/stack.hpp index 875836ca..ddebb722 100644 --- a/sol/stack.hpp +++ b/sol/stack.hpp @@ -184,38 +184,8 @@ struct pusher { lua_pushunsigned(L, value); } - template> = 0> - static void push(lua_State*, T& ref) { - ref.push(); - } - - template>, Not>, Not>> = 0> - static void push(lua_State* L, T& t) { - pusher{}.push(L, std::addressof(t)); - } - - template, EnableIf>, Not>, Not>> = 0> - static void push(lua_State* L, T&& t) { - detail::push_userdata(L, userdata_traits::metatable, std::move(t)); - } -}; - -template -struct pusher { - static void push(lua_State* L, T* obj) { - detail::push_userdata(L, userdata_traits::metatable, obj); - } -}; - -template <> -struct pusher { - template, EnableIf> = 0> - static void push_as(lua_State *L, T&& ref) { - ref.push(); - } - - template, EnableIf, Not>> = 0> - static void push_as(lua_State* L, const T& cont) { + template, Not>> = 0> + static void push(lua_State* L, const T& cont) { lua_createtable(L, cont.size(), 0); unsigned index = 1; for(auto&& i : cont) { @@ -228,8 +198,8 @@ struct pusher
{ } } - template, EnableIf, has_key_value_pair> = 0> - static void push_as(lua_State* L, const T& cont) { + template, has_key_value_pair> = 0> + static void push(lua_State* L, const T& cont) { lua_createtable(L, cont.size(), 0); for(auto&& pair : cont) { pusher>{}.push(L, pair.first); @@ -238,9 +208,26 @@ struct pusher
{ } } - template - static void push(lua_State *L, T&& table) { - push_as(L, std::forward(table)); + template> = 0> + static void push(lua_State*, T& ref) { + ref.push(); + } + + template, EnableIf>, Not>, Not>, Not>> = 0> + static void push(lua_State* L, T& t) { + pusher{}.push(L, std::addressof(t)); + } + + template, EnableIf>, Not>, Not>, Not>> = 0> + static void push(lua_State* L, T&& t) { + detail::push_userdata(L, userdata_traits::metatable, std::move(t)); + } +}; + +template +struct pusher { + static void push(lua_State* L, T* obj) { + detail::push_userdata(L, userdata_traits::metatable, obj); } }; @@ -375,7 +362,7 @@ inline std::pair get_as_upvalues(lua_State* L, int index = 1) { typedef std::array data_t; data_t voiddata{ {} }; for (std::size_t i = 0, d = 0; d < sizeof(T); ++i, d += sizeof(void*)) { - voiddata[ i ] = get(L, index++); + voiddata[i] = get(L, index++); } return std::pair(*reinterpret_cast(static_cast(voiddata.data())), index); } diff --git a/sol/userdata.hpp b/sol/userdata.hpp index 5ecfff15..aff9551c 100644 --- a/sol/userdata.hpp +++ b/sol/userdata.hpp @@ -85,8 +85,15 @@ private: T* obj = static_cast(udata); match_constructor(L, obj, syntax, argcount - static_cast(syntax), typename std::common_type::type()...); - luaL_getmetatable(L, std::addressof(meta[0])); - lua_setmetatable(L, -1); + + if (luaL_newmetatable(L, std::addressof(meta[0])) == 1) { + lua_pop(L, 1); + std::string err = "Unable to get userdata metatable for "; + err += meta; + throw error(err); + } + + lua_setmetatable(L, -2); return 1; } @@ -103,10 +110,10 @@ private: } }; - template + template void build_function_tables() {} - template + template void build_function_tables(std::string funcname, Ret TBase::* func, Args&&... args) { static_assert(std::is_base_of::value, "Any registered function must be part of the class"); typedef typename std::decay::type function_type; @@ -118,14 +125,15 @@ private: ptrmetafuncs.emplace_back(detail::make_unique::type>>(std::move(func))); metafunctiontable.push_back({ name.c_str(), &base_function::userdata::call }); ptrmetafunctiontable.push_back({ name.c_str(), &base_function::userdata::call }); + build_function_tables(std::forward(args)...); } else { funcs.emplace_back(detail::make_unique>(std::move(func))); ptrfuncs.emplace_back(detail::make_unique::type>>(std::move(func))); - functiontable.push_back({ name.c_str(), &base_function::userdata::call }); - ptrfunctiontable.push_back({ name.c_str(), &base_function::userdata::call }); + functiontable.push_back({ name.c_str(), &base_function::userdata::call }); + ptrfunctiontable.push_back({ name.c_str(), &base_function::userdata::call }); + build_function_tables(std::forward(args)...); } - build_function_tables(std::forward(args)...); } public: @@ -146,7 +154,7 @@ public: ptrfuncs.reserve(sizeof...(args) + 2); metafuncs.reserve(sizeof...(args) + 2); ptrmetafuncs.reserve(sizeof...(args) + 2); - build_function_tables<0>(std::forward(args)...); + build_function_tables<0, 0>(std::forward(args)...); functionnames.push_back("new"); functiontable.push_back({ functionnames.back().c_str(), &constructor::construct }); @@ -238,22 +246,24 @@ struct pusher> { static void push_metatable(lua_State* L, Meta&& meta, Funcs&& funcs, FuncTable&& functable, MetaFuncs&& metafuncs, MetaFuncTable&& metafunctable) { luaL_newmetatable(L, std::addressof(meta[0])); // regular functions accessed through __index semantics - lua_pushvalue(L, -1); - lua_setfield(L, -1, "__index"); for (std::size_t u = 0; u < funcs.size(); ++u) { - stack::push(L, funcs[ u ].get()); + stack::push(L, funcs[u].get()); } luaL_setfuncs(L, functable.data(), static_cast(funcs.size())); // meta functions for (std::size_t u = 0; u < metafuncs.size(); ++u) { - stack::push(L, metafuncs[ u ].get()); + stack::push(L, metafuncs[u].get()); } luaL_setfuncs(L, metafunctable.data(), static_cast(metafuncs.size())); + lua_pushvalue(L, -1); + lua_setfield(L, -1, "__index"); } static void push (lua_State* L, userdata& user) { - push_metatable(L, userdata_traits::metatable, user.functions(), user.function_table(), user.meta_functions(), user.meta_function_table()); + // push pointer tables first, + // but leave the regular T table on last so it can be linked to a type for usage with `.new(...)` push_metatable(L, userdata_traits::metatable, user.reference_functions(), user.reference_function_table(), user.meta_reference_functions(), user.meta_reference_function_table()); + push_metatable(L, userdata_traits::metatable, user.functions(), user.function_table(), user.meta_functions(), user.meta_function_table()); } }; } // stack diff --git a/sol/userdata_traits.hpp b/sol/userdata_traits.hpp index 77dabcd5..27e044f8 100644 --- a/sol/userdata_traits.hpp +++ b/sol/userdata_traits.hpp @@ -36,7 +36,7 @@ template const std::string userdata_traits::name = detail::demangle(typeid(T)); template -const std::string userdata_traits::metatable = std::string("sol.stateful.").append(detail::demangle(typeid(T))); +const std::string userdata_traits::metatable = std::string("sol.").append(detail::demangle(typeid(T))); }