mirror of
https://github.com/ThePhD/sol2.git
synced 2024-03-22 13:10:44 +08:00
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:
parent
b66c7f015a
commit
bb29127785
@ -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 );
|
||||
}
|
||||
}
|
||||
|
@ -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));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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)) {
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user