From bb2912778592325c8bede8ecead7379da9297bd2 Mon Sep 17 00:00:00 2001 From: ThePhD Date: Tue, 2 Feb 2016 16:18:44 -0500 Subject: [PATCH] Proper semantics for `set`/`get` `set_function`/`set_usertype` now properly use `set` For the time being, we are going to avoid implementing `traverse`; aside from performance of nested table access (e.g. `int x = lua["a"]["b"]["c"]`), it's a pain. ;~; --- bench.cpp | 2 +- sol/function.hpp | 23 +++++++++++++++----- sol/function_types.hpp | 8 +++++++ sol/reference.hpp | 11 +++++++--- sol/table_core.hpp | 48 ++++++++++-------------------------------- sol/traits.hpp | 2 +- sol/types.hpp | 5 ++--- 7 files changed, 49 insertions(+), 50 deletions(-) diff --git a/bench.cpp b/bench.cpp index 20a1c7b2..4a778547 100644 --- a/bench.cpp +++ b/bench.cpp @@ -14,4 +14,4 @@ int main( int argc, char* argv[] ) { bench_get( "bench/", configurationname, platformname ); bench_set( "bench/", configurationname, platformname ); bench_usertype( "bench/", configurationname, platformname ); -} \ No newline at end of file +} diff --git a/sol/function.hpp b/sol/function.hpp index 57831171..0e18830a 100644 --- a/sol/function.hpp +++ b/sol/function.hpp @@ -222,11 +222,11 @@ public: namespace stack { template -struct pusher> { +struct pusher> { template::type> static void set_memfx(types t, lua_State* L, Fx&& fx) { - typedef Decay> raw_fx_t; + typedef Decay>> raw_fx_t; typedef R(* fx_ptr_t)(Args...); typedef std::is_convertible is_convertible; set_isconvertible_fx(is_convertible(), t, L, std::forward(fx)); @@ -234,7 +234,7 @@ struct pusher> { template static void set_memfx(types<>, lua_State* L, Fx&& fx) { - typedef Unqualified> fx_t; + typedef Unwrap> fx_t; typedef decltype(&fx_t::operator()) Sig; set_memfx(types>(), L, std::forward(fx)); } @@ -275,7 +275,7 @@ struct pusher> { template static void set_isconvertible_fx(std::false_type, types, lua_State* L, Fx&& fx) { - typedef Decay> fx_t; + typedef Unwrap> fx_t; std::unique_ptr sptr(new functor_function(std::forward(fx))); set_fx(L, std::move(sptr)); } @@ -349,10 +349,23 @@ struct pusher> { } }; +template +struct pusher> { + template + static int push_func(indices, lua_State* L, FP&& fp) { + return stack::push(L, std::get(fp)...); + } + + template + static int push(lua_State* L, FP&& fp) { + return push_func(build_indices(), L, std::forward(fp)); + } +}; + template struct pusher> { static int push(lua_State* L, std::function fx) { - return pusher{}.push(L, std::move(fx)); + return pusher>{}.push(L, std::move(fx)); } }; diff --git a/sol/function_types.hpp b/sol/function_types.hpp index 1490a60e..5fa9c280 100644 --- a/sol/function_types.hpp +++ b/sol/function_types.hpp @@ -34,6 +34,14 @@ struct ref_call_t { const auto ref_call = ref_call_t{}; +template +struct function_packer : std::tuple { using std::tuple::tuple; }; + +template +function_packer function_pack( Args&&... args ) { + return function_packer(std::forward(args)...); +} + template struct functor { typedef member_traits traits_type; diff --git a/sol/reference.hpp b/sol/reference.hpp index bd311aaa..e9e77ea8 100644 --- a/sol/reference.hpp +++ b/sol/reference.hpp @@ -26,15 +26,20 @@ namespace sol { namespace stack { -template +template struct push_pop { T t; push_pop (T x) : t(x) { t.push(); } ~push_pop() { t.pop(); } }; template -push_pop push_popper(T&& x) { - return push_pop(std::forward(x)); +struct push_pop { + push_pop (T x) {} + ~push_pop() {} +}; +template +push_pop push_popper(T&& x) { + return push_pop(std::forward(x)); }; } // stack diff --git a/sol/table_core.hpp b/sol/table_core.hpp index a79e65e1..a8f5cd10 100644 --- a/sol/table_core.hpp +++ b/sol/table_core.hpp @@ -46,7 +46,7 @@ class table_core : public reference { template>, is_c_str> = 0> decltype(auto) single_get( Key&& key ) const { auto pp = stack::push_popper(*this); - lua_getfield( lua_state( ), -2, &key[0] ); + lua_getfield( lua_state( ), -1, &key[0] ); return stack::pop( lua_state( ) ); } @@ -66,17 +66,19 @@ class table_core : public reference { template>, is_c_str> = 0> void single_set(Key&& key, Value&& value) { - auto pp = stack::push_popper(*this); + push(); stack::push(lua_state(), std::forward(value)); - lua_setfield(lua_state(), -3, &key[0]); + lua_setfield(lua_state(), -2, &key[0]); + pop(); } template>> = 0> void single_set(Key&& key, Value&& value) { - auto pp = stack::push_popper(*this); + push(); stack::push(lua_state(), std::forward(key)); stack::push(lua_state(), std::forward(value)); lua_settable(lua_state(), -3); + pop(); } template @@ -125,27 +127,17 @@ public: template SOL_DEPRECATED table_core& set_userdata( Key&& key, usertype& user ) { - return set_usertype( std::forward( key ), user ); + return set_usertype(std::forward(key), user); } template table_core& set_usertype( usertype& user ) { - return set_usertype( usertype_traits::name, user ); + return set_usertype(usertype_traits::name, user); } template table_core& set_usertype( Key&& key, usertype& user ) { - if ( top_level ) { - stack::push( lua_state( ), user ); - lua_setglobal( lua_state( ), &key[ 0 ] ); - } - else { - auto pp = stack::push_popper( *this ); - stack::push( lua_state( ), std::forward( key ) ); - stack::push( lua_state( ), user ); - lua_settable( lua_state( ), -3 ); - } - return *this; + return set(std::forward(key), user); } template @@ -227,27 +219,9 @@ private: set_fx( types>( ), std::forward( key ), std::forward( fx ) ); } - template, is_c_str> = 0> + template void set_resolved_function( Key&& key, Args&&... args ) { - stack::push>( lua_state( ), std::forward( args )... ); - lua_setglobal( lua_state( ), &key[ 0 ] ); - } - - template>, is_c_str> = 0> - void set_resolved_function( Key&& key, Args&&... args ) { - auto pp = stack::push_popper( *this ); - int tabletarget = lua_gettop( lua_state( ) ); - stack::push>( lua_state( ), std::forward( args )... ); - lua_setfield( lua_state( ), tabletarget, &key[ 0 ] ); - } - - template>> = 0> - void set_resolved_function( Key&& key, Args&&... args ) { - auto pp = stack::push_popper( *this ); - int tabletarget = lua_gettop( lua_state( ) ); - stack::push(lua_state(), std::forward(key)); - stack::push>( lua_state( ), std::forward( args )... ); - lua_settable( lua_state( ), tabletarget ); + set(std::forward(key), detail::function_pack>(std::forward(args)...)); } }; } // sol diff --git a/sol/traits.hpp b/sol/traits.hpp index 5ee5a118..5d74e4bd 100644 --- a/sol/traits.hpp +++ b/sol/traits.hpp @@ -316,7 +316,7 @@ template using is_string_constructible = Or, const char*>, std::is_same, char>, std::is_same, std::string>, std::is_same, std::initializer_list>>; template -using is_c_str = Or>, const char*>, std::is_same, std::string>>; +using is_c_str = Or>, char*>, std::is_same, std::string>>; template auto unwrapper(T&& item) -> decltype(std::forward(item)) { diff --git a/sol/types.hpp b/sol/types.hpp index a4a6139d..a02def33 100644 --- a/sol/types.hpp +++ b/sol/types.hpp @@ -36,9 +36,8 @@ inline bool operator!=(nil_t, nil_t) { return false; } struct void_type : types {}; // This is important because it allows myobject.call( Void, ... ) to work const void_type Void {}; -template -struct function_sig_t {}; -using function_t = function_sig_t<>; +template +struct function_sig {}; struct upvalue { void* value;