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. ;~;
This commit is contained in:
ThePhD 2016-02-02 16:18:44 -05:00
parent b66c7f015a
commit bb29127785
7 changed files with 49 additions and 50 deletions

View File

@ -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 );
}
}

View File

@ -222,11 +222,11 @@ public:
namespace stack {
template<typename... Sigs>
struct pusher<function_sig_t<Sigs...>> {
struct pusher<function_sig<Sigs...>> {
template<typename R, typename... Args, typename Fx, typename = typename std::result_of<Fx(Args...)>::type>
static void set_memfx(types<R(Args...)> t, lua_State* L, Fx&& fx) {
typedef Decay<Unwrap<Fx>> raw_fx_t;
typedef Decay<Unwrap<Unqualified<Fx>>> raw_fx_t;
typedef R(* fx_ptr_t)(Args...);
typedef std::is_convertible<raw_fx_t, fx_ptr_t> is_convertible;
set_isconvertible_fx(is_convertible(), t, L, std::forward<Fx>(fx));
@ -234,7 +234,7 @@ struct pusher<function_sig_t<Sigs...>> {
template<typename Fx>
static void set_memfx(types<>, lua_State* L, Fx&& fx) {
typedef Unqualified<Unwrap<Fx>> fx_t;
typedef Unwrap<Unqualified<Fx>> fx_t;
typedef decltype(&fx_t::operator()) Sig;
set_memfx(types<function_signature_t<Sig>>(), L, std::forward<Fx>(fx));
}
@ -275,7 +275,7 @@ struct pusher<function_sig_t<Sigs...>> {
template<typename Fx, typename R, typename... Args>
static void set_isconvertible_fx(std::false_type, types<R(Args...)>, lua_State* L, Fx&& fx) {
typedef Decay<Unwrap<Fx>> fx_t;
typedef Unwrap<Decay<Fx>> fx_t;
std::unique_ptr<base_function> sptr(new functor_function<fx_t>(std::forward<Fx>(fx)));
set_fx<Fx>(L, std::move(sptr));
}
@ -349,10 +349,23 @@ struct pusher<function_sig_t<Sigs...>> {
}
};
template<typename T, typename... Args>
struct pusher<sol::detail::function_packer<T, Args...>> {
template <std::size_t... I, typename FP>
static int push_func(indices<I...>, lua_State* L, FP&& fp) {
return stack::push<T>(L, std::get<I>(fp)...);
}
template <typename FP>
static int push(lua_State* L, FP&& fp) {
return push_func(build_indices<sizeof...(Args)>(), L, std::forward<FP>(fp));
}
};
template<typename Signature>
struct pusher<std::function<Signature>> {
static int push(lua_State* L, std::function<Signature> fx) {
return pusher<function_t>{}.push(L, std::move(fx));
return pusher<function_sig<>>{}.push(L, std::move(fx));
}
};

View File

@ -34,6 +34,14 @@ struct ref_call_t {
const auto ref_call = ref_call_t{};
template <typename Sig, typename... Args>
struct function_packer : std::tuple<Args...> { using std::tuple<Args...>::tuple; };
template <typename Sig, typename... Args>
function_packer<Sig, Args...> function_pack( Args&&... args ) {
return function_packer<Sig, Args...>(std::forward<Args>(args)...);
}
template<typename T, typename Func, typename = void>
struct functor {
typedef member_traits<Func> traits_type;

View File

@ -26,15 +26,20 @@
namespace sol {
namespace stack {
template <typename T>
template <bool top_level, typename T>
struct push_pop {
T t;
push_pop (T x) : t(x) { t.push(); }
~push_pop() { t.pop(); }
};
template <typename T>
push_pop<T> push_popper(T&& x) {
return push_pop<T>(std::forward<T>(x));
struct push_pop<true, T> {
push_pop (T x) {}
~push_pop() {}
};
template <bool top_level = false, typename T>
push_pop<top_level, T> push_popper(T&& x) {
return push_pop<top_level, T>(std::forward<T>(x));
};
} // stack

View File

@ -46,7 +46,7 @@ class table_core : public reference {
template<typename T, typename Key, EnableIf<Not<Bool<top_level>>, is_c_str<Key>> = 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<T>( lua_state( ) );
}
@ -66,17 +66,19 @@ class table_core : public reference {
template<typename Key, typename Value, EnableIf<Not<Bool<top_level>>, is_c_str<Key>> = 0>
void single_set(Key&& key, Value&& value) {
auto pp = stack::push_popper(*this);
push();
stack::push(lua_state(), std::forward<Value>(value));
lua_setfield(lua_state(), -3, &key[0]);
lua_setfield(lua_state(), -2, &key[0]);
pop();
}
template<typename Key, typename Value, EnableIf<Not<is_c_str<Key>>> = 0>
void single_set(Key&& key, Value&& value) {
auto pp = stack::push_popper(*this);
push();
stack::push(lua_state(), std::forward<Key>(key));
stack::push(lua_state(), std::forward<Value>(value));
lua_settable(lua_state(), -3);
pop();
}
template<typename Keys, typename... Ret, std::size_t... I>
@ -125,27 +127,17 @@ public:
template<typename Key, typename T>
SOL_DEPRECATED table_core& set_userdata( Key&& key, usertype<T>& user ) {
return set_usertype( std::forward<Key>( key ), user );
return set_usertype(std::forward<Key>(key), user);
}
template<typename T>
table_core& set_usertype( usertype<T>& user ) {
return set_usertype( usertype_traits<T>::name, user );
return set_usertype(usertype_traits<T>::name, user);
}
template<typename Key, typename T>
table_core& set_usertype( Key&& key, usertype<T>& 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>( key ) );
stack::push( lua_state( ), user );
lua_settable( lua_state( ), -3 );
}
return *this;
return set(std::forward<Key>(key), user);
}
template<typename Fx>
@ -227,27 +219,9 @@ private:
set_fx( types<function_signature_t<Sig>>( ), std::forward<Key>( key ), std::forward<Fx>( fx ) );
}
template<typename... Sig, typename... Args, typename Key, EnableIf<Bool<top_level>, is_c_str<Key>> = 0>
template<typename... Sig, typename... Args, typename Key>
void set_resolved_function( Key&& key, Args&&... args ) {
stack::push<function_sig_t<Sig...>>( lua_state( ), std::forward<Args>( args )... );
lua_setglobal( lua_state( ), &key[ 0 ] );
}
template<typename... Sig, typename... Args, typename Key, EnableIf<Not<Bool<top_level>>, is_c_str<Key>> = 0>
void set_resolved_function( Key&& key, Args&&... args ) {
auto pp = stack::push_popper( *this );
int tabletarget = lua_gettop( lua_state( ) );
stack::push<function_sig_t<Sig...>>( lua_state( ), std::forward<Args>( args )... );
lua_setfield( lua_state( ), tabletarget, &key[ 0 ] );
}
template<typename... Sig, typename... Args, typename Key, EnableIf<Not<is_c_str<Key>>> = 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>(key));
stack::push<function_sig_t<Sig...>>( lua_state( ), std::forward<Args>( args )... );
lua_settable( lua_state( ), tabletarget );
set(std::forward<Key>(key), detail::function_pack<function_sig<Sig...>>(std::forward<Args>(args)...));
}
};
} // sol

View File

@ -316,7 +316,7 @@ template <typename T>
using is_string_constructible = Or<std::is_same<Unqualified<T>, const char*>, std::is_same<Unqualified<T>, char>, std::is_same<Unqualified<T>, std::string>, std::is_same<Unqualified<T>, std::initializer_list<char>>>;
template <typename T>
using is_c_str = Or<std::is_same<std::decay_t<Unqualified<T>>, const char*>, std::is_same<Unqualified<T>, std::string>>;
using is_c_str = Or<std::is_same<std::decay_t<Unqualified<T>>, char*>, std::is_same<Unqualified<T>, std::string>>;
template<typename T>
auto unwrapper(T&& item) -> decltype(std::forward<T>(item)) {

View File

@ -36,9 +36,8 @@ inline bool operator!=(nil_t, nil_t) { return false; }
struct void_type : types<void> {}; // This is important because it allows myobject.call( Void, ... ) to work
const void_type Void {};
template<typename... T>
struct function_sig_t {};
using function_t = function_sig_t<>;
template<typename... Args>
struct function_sig {};
struct upvalue {
void* value;