mirror of
https://github.com/ThePhD/sol2.git
synced 2024-03-22 13:10:44 +08:00
Implement better insert-with-no-iterator support
- reorder constructor values to match class order - Fix up compilation related to GCC - Add new shim tests to confirm insertion works properly - regenerate single
This commit is contained in:
parent
a9ff1d4187
commit
d363ccd759
|
@ -65,9 +65,9 @@ namespace sol {
|
|||
: m_L(nullptr)
|
||||
, m_next_function_ref(lua_nil)
|
||||
, m_table_ref(lua_nil)
|
||||
, m_cached_key_value_pair({ lua_nil, lua_nil })
|
||||
, m_key_index(empty_key_index)
|
||||
, m_iteration_index(0)
|
||||
, m_cached_key_value_pair({ lua_nil, lua_nil }) {
|
||||
, m_iteration_index(0) {
|
||||
}
|
||||
|
||||
pairs_iterator(const pairs_iterator&) = delete;
|
||||
|
@ -77,9 +77,9 @@ namespace sol {
|
|||
: m_L(right.m_L)
|
||||
, m_next_function_ref(std::move(right.m_next_function_ref))
|
||||
, m_table_ref(std::move(right.m_table_ref))
|
||||
, m_cached_key_value_pair(std::move(right.m_cached_key_value_pair))
|
||||
, m_key_index(right.m_key_index)
|
||||
, m_iteration_index(right.m_iteration_index)
|
||||
, m_cached_key_value_pair(std::move(right.m_cached_key_value_pair)) {
|
||||
, m_iteration_index(right.m_iteration_index) {
|
||||
right.m_key_index = empty_key_index;
|
||||
}
|
||||
|
||||
|
@ -87,10 +87,11 @@ namespace sol {
|
|||
m_L = right.m_L;
|
||||
m_next_function_ref = std::move(right.m_next_function_ref);
|
||||
m_table_ref = std::move(right.m_table_ref);
|
||||
m_cached_key_value_pair = std::move(right.m_cached_key_value_pair);
|
||||
m_key_index = right.m_key_index;
|
||||
m_iteration_index = right.m_iteration_index;
|
||||
m_cached_key_value_pair = std::move(right.m_cached_key_value_pair);
|
||||
right.m_key_index = empty_key_index;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename Source>
|
||||
|
@ -105,8 +106,9 @@ namespace sol {
|
|||
lua_remove(m_L, abs_source_index);
|
||||
if (metatable_exists == 1) {
|
||||
// just has a metatable, but does it have __pairs ?
|
||||
stack_lua_table metatable(m_L, abs_source_index);
|
||||
optional<protected_function> maybe_pairs_function = metatable.raw_get<optional<function>>(meta_function::pairs);
|
||||
stack_reference metatable(m_L, raw_index(abs_source_index));
|
||||
stack::get_field<is_global_table_v<Source>, true>(m_L, meta_function::pairs, metatable.stack_index());
|
||||
optional<protected_function> maybe_pairs_function = stack::pop<optional<function>>(m_L);
|
||||
if (maybe_pairs_function.has_value()) {
|
||||
function& pairs_function = *maybe_pairs_function;
|
||||
protected_function_result next_fn_and_table_and_first_key = pairs_function(source_);
|
||||
|
|
|
@ -401,16 +401,28 @@ namespace sol { namespace meta {
|
|||
};
|
||||
|
||||
template <typename T>
|
||||
struct has_insert_test {
|
||||
struct has_insert_with_iterator_test {
|
||||
private:
|
||||
template <typename C>
|
||||
static sfinae_yes_t test(decltype(std::declval<C>().insert(std::declval<std::add_rvalue_reference_t<typename C::const_iterator>>(),
|
||||
std::declval<std::add_rvalue_reference_t<typename C::value_type>>()))*);
|
||||
static sfinae_yes_t test(decltype(std::declval<C>().insert(
|
||||
std::declval<std::add_rvalue_reference_t<typename C::iterator>>(), std::declval<std::add_rvalue_reference_t<typename C::value_type>>()))*);
|
||||
template <typename C>
|
||||
static sfinae_no_t test(...);
|
||||
|
||||
public:
|
||||
static constexpr bool value = std::is_same_v<decltype(test<T>(0)), sfinae_yes_t>;
|
||||
static constexpr bool value = !std::is_same_v<decltype(test<T>(0)), sfinae_no_t>;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct has_insert_test {
|
||||
private:
|
||||
template <typename C>
|
||||
static sfinae_yes_t test(decltype(std::declval<C>().insert(std::declval<std::add_rvalue_reference_t<typename C::value_type>>()))*);
|
||||
template <typename C>
|
||||
static sfinae_no_t test(...);
|
||||
|
||||
public:
|
||||
static constexpr bool value = !std::is_same_v<decltype(test<T>(0)), sfinae_no_t>;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
|
@ -562,6 +574,9 @@ namespace sol { namespace meta {
|
|||
template <typename T>
|
||||
using has_insert = meta::boolean<meta_detail::has_insert_test<T>::value>;
|
||||
|
||||
template <typename T>
|
||||
using has_insert_with_iterator = meta::boolean<meta_detail::has_insert_with_iterator_test<T>::value>;
|
||||
|
||||
template <typename T>
|
||||
using has_insert_after = meta::boolean<meta_detail::has_insert_after_test<T>::value>;
|
||||
|
||||
|
|
|
@ -719,10 +719,14 @@ namespace sol {
|
|||
|
||||
template <typename Iter>
|
||||
static detail::error_result set_associative_insert(std::true_type, lua_State*, T& self, Iter& it, K& key, stack_object value) {
|
||||
if constexpr (meta::has_insert<T>::value) {
|
||||
if constexpr (meta::has_insert_with_iterator<T>::value) {
|
||||
self.insert(it, value_type(key, value.as<V>()));
|
||||
return {};
|
||||
}
|
||||
else if constexpr (meta::has_insert<T>::value) {
|
||||
self.insert(value_type(key, value.as<V>()));
|
||||
return {};
|
||||
}
|
||||
else {
|
||||
(void)self;
|
||||
(void)it;
|
||||
|
@ -734,10 +738,14 @@ namespace sol {
|
|||
|
||||
template <typename Iter>
|
||||
static detail::error_result set_associative_insert(std::false_type, lua_State*, T& self, Iter& it, K& key, stack_object) {
|
||||
if constexpr (meta::has_insert<T>::value) {
|
||||
if constexpr (meta::has_insert_with_iterator<T>::value) {
|
||||
self.insert(it, key);
|
||||
return {};
|
||||
}
|
||||
else if constexpr (meta::has_insert<T>::value) {
|
||||
self.insert(key);
|
||||
return {};
|
||||
}
|
||||
else {
|
||||
(void)self;
|
||||
(void)it;
|
||||
|
@ -917,19 +925,25 @@ namespace sol {
|
|||
|
||||
template <typename Iter>
|
||||
static detail::error_result add_push_back(std::false_type, lua_State* L, T& self, stack_object value, Iter& pos) {
|
||||
return add_insert(meta::has_insert<T>(), L, self, value, pos);
|
||||
return add_insert(
|
||||
std::integral_constant < bool, meta::has_insert<T>::value || meta::has_insert_with_iterator<T>::value > (), L, self, value, pos);
|
||||
}
|
||||
|
||||
static detail::error_result add_push_back(std::false_type, lua_State* L, T& self, stack_object value) {
|
||||
return add_insert(meta::has_insert<T>(), L, self, value);
|
||||
return add_insert(
|
||||
std::integral_constant < bool, meta::has_insert<T>::value || meta::has_insert_with_iterator<T>::value > (), L, self, value);
|
||||
}
|
||||
|
||||
template <typename Iter>
|
||||
static detail::error_result add_associative(std::true_type, lua_State* L, T& self, stack_object key, Iter& pos) {
|
||||
if constexpr (meta::has_insert<T>::value) {
|
||||
if constexpr (meta::has_insert_with_iterator<T>::value) {
|
||||
self.insert(pos, value_type(key.as<K>(), stack::unqualified_get<V>(L, 3)));
|
||||
return {};
|
||||
}
|
||||
else if constexpr (meta::has_insert<T>::value) {
|
||||
self.insert(value_type(key.as<K>(), stack::unqualified_get<V>(L, 3)));
|
||||
return {};
|
||||
}
|
||||
else {
|
||||
(void)L;
|
||||
(void)self;
|
||||
|
@ -1016,7 +1030,12 @@ namespace sol {
|
|||
}
|
||||
|
||||
static detail::error_result insert_copyable(std::true_type, lua_State* L, T& self, stack_object key, stack_object value) {
|
||||
return insert_has(meta::has_insert<T>(), L, self, std::move(key), std::move(value));
|
||||
return insert_has(std::integral_constant < bool,
|
||||
meta::has_insert<T>::value || meta::has_insert_with_iterator<T>::value > (),
|
||||
L,
|
||||
self,
|
||||
std::move(key),
|
||||
std::move(value));
|
||||
}
|
||||
|
||||
static detail::error_result insert_copyable(std::false_type, lua_State*, T&, stack_object, stack_object) {
|
||||
|
|
|
@ -657,12 +657,6 @@ namespace sol { namespace u_detail {
|
|||
inline void set(lua_State* L, Key&& key, Value&& value);
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
inline int destroy_usertype_storage(lua_State* L) noexcept {
|
||||
clear_usertype_registry_names<T>(L);
|
||||
return detail::user_alloc_destroy<usertype_storage<T>>(L);
|
||||
}
|
||||
|
||||
template <typename T, typename Key, typename Value>
|
||||
void usertype_storage_base::set(lua_State* L, Key&& key, Value&& value) {
|
||||
using ValueU = meta::unwrap_unqualified_t<Value>;
|
||||
|
@ -804,6 +798,34 @@ namespace sol { namespace u_detail {
|
|||
static_cast<usertype_storage_base&>(*this).set<T>(L, std::forward<Key>(key), std::forward<Value>(value));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void clear_usertype_registry_names(lua_State* L) {
|
||||
using u_traits = usertype_traits<T>;
|
||||
using u_const_traits = usertype_traits<const T>;
|
||||
using u_unique_traits = usertype_traits<d::u<T>>;
|
||||
using u_ref_traits = usertype_traits<T*>;
|
||||
using u_const_ref_traits = usertype_traits<T const*>;
|
||||
|
||||
stack_reference registry(L, raw_index(LUA_REGISTRYINDEX));
|
||||
registry.push();
|
||||
// eliminate all named entries for this usertype
|
||||
// in the registry (luaL_newmetatable does
|
||||
// [name] = new table
|
||||
// in registry upon creation
|
||||
stack::set_field(L, &u_traits::metatable()[0], lua_nil, registry.stack_index());
|
||||
stack::set_field(L, &u_const_traits::metatable()[0], lua_nil, registry.stack_index());
|
||||
stack::set_field(L, &u_const_ref_traits::metatable()[0], lua_nil, registry.stack_index());
|
||||
stack::set_field(L, &u_ref_traits::metatable()[0], lua_nil, registry.stack_index());
|
||||
stack::set_field(L, &u_unique_traits::metatable()[0], lua_nil, registry.stack_index());
|
||||
registry.pop();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline int destroy_usertype_storage(lua_State* L) noexcept {
|
||||
clear_usertype_registry_names<T>(L);
|
||||
return detail::user_alloc_destroy<usertype_storage<T>>(L);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline usertype_storage<T>& create_usertype_storage(lua_State* L) {
|
||||
const char* gcmetakey = &usertype_traits<T>::gc_table()[0];
|
||||
|
@ -900,28 +922,6 @@ namespace sol { namespace u_detail {
|
|||
return target_umt;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void clear_usertype_registry_names(lua_State* L) {
|
||||
using u_traits = usertype_traits<T>;
|
||||
using u_const_traits = usertype_traits<const T>;
|
||||
using u_unique_traits = usertype_traits<d::u<T>>;
|
||||
using u_ref_traits = usertype_traits<T*>;
|
||||
using u_const_ref_traits = usertype_traits<T const*>;
|
||||
|
||||
stack_reference registry(L, raw_index(LUA_REGISTRYINDEX));
|
||||
registry.push();
|
||||
// eliminate all named entries for this usertype
|
||||
// in the registry (luaL_newmetatable does
|
||||
// [name] = new table
|
||||
// in registry upon creation
|
||||
stack::set_field(L, &u_traits::metatable()[0], lua_nil, registry.stack_index());
|
||||
stack::set_field(L, &u_const_traits::metatable()[0], lua_nil, registry.stack_index());
|
||||
stack::set_field(L, &u_const_ref_traits::metatable()[0], lua_nil, registry.stack_index());
|
||||
stack::set_field(L, &u_ref_traits::metatable()[0], lua_nil, registry.stack_index());
|
||||
stack::set_field(L, &u_unique_traits::metatable()[0], lua_nil, registry.stack_index());
|
||||
registry.pop();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void clear_usertype_storage(lua_State* L) {
|
||||
using u_traits = usertype_traits<T>;
|
||||
|
|
|
@ -20,8 +20,8 @@
|
|||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
// This file was generated with a script.
|
||||
// Generated 2021-01-21 20:56:50.106258 UTC
|
||||
// This header was generated with sol v3.2.3 (revision c032cda5)
|
||||
// Generated 2021-01-22 06:17:28.820224 UTC
|
||||
// This header was generated with sol v3.2.3 (revision a9ff1d41)
|
||||
// https://github.com/ThePhD/sol2
|
||||
|
||||
#ifndef SOL_SINGLE_CONFIG_HPP
|
||||
|
|
|
@ -20,8 +20,8 @@
|
|||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
// This file was generated with a script.
|
||||
// Generated 2021-01-21 20:56:50.090246 UTC
|
||||
// This header was generated with sol v3.2.3 (revision c032cda5)
|
||||
// Generated 2021-01-22 06:17:28.815225 UTC
|
||||
// This header was generated with sol v3.2.3 (revision a9ff1d41)
|
||||
// https://github.com/ThePhD/sol2
|
||||
|
||||
#ifndef SOL_SINGLE_INCLUDE_FORWARD_HPP
|
||||
|
|
|
@ -20,8 +20,8 @@
|
|||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
// This file was generated with a script.
|
||||
// Generated 2021-01-21 20:56:49.214244 UTC
|
||||
// This header was generated with sol v3.2.3 (revision c032cda5)
|
||||
// Generated 2021-01-22 06:17:28.072111 UTC
|
||||
// This header was generated with sol v3.2.3 (revision a9ff1d41)
|
||||
// https://github.com/ThePhD/sol2
|
||||
|
||||
#ifndef SOL_SINGLE_INCLUDE_HPP
|
||||
|
@ -2118,16 +2118,28 @@ namespace sol { namespace meta {
|
|||
};
|
||||
|
||||
template <typename T>
|
||||
struct has_insert_test {
|
||||
struct has_insert_with_iterator_test {
|
||||
private:
|
||||
template <typename C>
|
||||
static sfinae_yes_t test(decltype(std::declval<C>().insert(std::declval<std::add_rvalue_reference_t<typename C::const_iterator>>(),
|
||||
std::declval<std::add_rvalue_reference_t<typename C::value_type>>()))*);
|
||||
static sfinae_yes_t test(decltype(std::declval<C>().insert(
|
||||
std::declval<std::add_rvalue_reference_t<typename C::iterator>>(), std::declval<std::add_rvalue_reference_t<typename C::value_type>>()))*);
|
||||
template <typename C>
|
||||
static sfinae_no_t test(...);
|
||||
|
||||
public:
|
||||
static constexpr bool value = std::is_same_v<decltype(test<T>(0)), sfinae_yes_t>;
|
||||
static constexpr bool value = !std::is_same_v<decltype(test<T>(0)), sfinae_no_t>;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct has_insert_test {
|
||||
private:
|
||||
template <typename C>
|
||||
static sfinae_yes_t test(decltype(std::declval<C>().insert(std::declval<std::add_rvalue_reference_t<typename C::value_type>>()))*);
|
||||
template <typename C>
|
||||
static sfinae_no_t test(...);
|
||||
|
||||
public:
|
||||
static constexpr bool value = !std::is_same_v<decltype(test<T>(0)), sfinae_no_t>;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
|
@ -2279,6 +2291,9 @@ namespace sol { namespace meta {
|
|||
template <typename T>
|
||||
using has_insert = meta::boolean<meta_detail::has_insert_test<T>::value>;
|
||||
|
||||
template <typename T>
|
||||
using has_insert_with_iterator = meta::boolean<meta_detail::has_insert_with_iterator_test<T>::value>;
|
||||
|
||||
template <typename T>
|
||||
using has_insert_after = meta::boolean<meta_detail::has_insert_after_test<T>::value>;
|
||||
|
||||
|
@ -21366,10 +21381,14 @@ namespace sol {
|
|||
|
||||
template <typename Iter>
|
||||
static detail::error_result set_associative_insert(std::true_type, lua_State*, T& self, Iter& it, K& key, stack_object value) {
|
||||
if constexpr (meta::has_insert<T>::value) {
|
||||
if constexpr (meta::has_insert_with_iterator<T>::value) {
|
||||
self.insert(it, value_type(key, value.as<V>()));
|
||||
return {};
|
||||
}
|
||||
else if constexpr (meta::has_insert<T>::value) {
|
||||
self.insert(value_type(key, value.as<V>()));
|
||||
return {};
|
||||
}
|
||||
else {
|
||||
(void)self;
|
||||
(void)it;
|
||||
|
@ -21381,10 +21400,14 @@ namespace sol {
|
|||
|
||||
template <typename Iter>
|
||||
static detail::error_result set_associative_insert(std::false_type, lua_State*, T& self, Iter& it, K& key, stack_object) {
|
||||
if constexpr (meta::has_insert<T>::value) {
|
||||
if constexpr (meta::has_insert_with_iterator<T>::value) {
|
||||
self.insert(it, key);
|
||||
return {};
|
||||
}
|
||||
else if constexpr (meta::has_insert<T>::value) {
|
||||
self.insert(key);
|
||||
return {};
|
||||
}
|
||||
else {
|
||||
(void)self;
|
||||
(void)it;
|
||||
|
@ -21564,19 +21587,25 @@ namespace sol {
|
|||
|
||||
template <typename Iter>
|
||||
static detail::error_result add_push_back(std::false_type, lua_State* L, T& self, stack_object value, Iter& pos) {
|
||||
return add_insert(meta::has_insert<T>(), L, self, value, pos);
|
||||
return add_insert(
|
||||
std::integral_constant < bool, meta::has_insert<T>::value || meta::has_insert_with_iterator<T>::value > (), L, self, value, pos);
|
||||
}
|
||||
|
||||
static detail::error_result add_push_back(std::false_type, lua_State* L, T& self, stack_object value) {
|
||||
return add_insert(meta::has_insert<T>(), L, self, value);
|
||||
return add_insert(
|
||||
std::integral_constant < bool, meta::has_insert<T>::value || meta::has_insert_with_iterator<T>::value > (), L, self, value);
|
||||
}
|
||||
|
||||
template <typename Iter>
|
||||
static detail::error_result add_associative(std::true_type, lua_State* L, T& self, stack_object key, Iter& pos) {
|
||||
if constexpr (meta::has_insert<T>::value) {
|
||||
if constexpr (meta::has_insert_with_iterator<T>::value) {
|
||||
self.insert(pos, value_type(key.as<K>(), stack::unqualified_get<V>(L, 3)));
|
||||
return {};
|
||||
}
|
||||
else if constexpr (meta::has_insert<T>::value) {
|
||||
self.insert(value_type(key.as<K>(), stack::unqualified_get<V>(L, 3)));
|
||||
return {};
|
||||
}
|
||||
else {
|
||||
(void)L;
|
||||
(void)self;
|
||||
|
@ -21663,7 +21692,12 @@ namespace sol {
|
|||
}
|
||||
|
||||
static detail::error_result insert_copyable(std::true_type, lua_State* L, T& self, stack_object key, stack_object value) {
|
||||
return insert_has(meta::has_insert<T>(), L, self, std::move(key), std::move(value));
|
||||
return insert_has(std::integral_constant < bool,
|
||||
meta::has_insert<T>::value || meta::has_insert_with_iterator<T>::value > (),
|
||||
L,
|
||||
self,
|
||||
std::move(key),
|
||||
std::move(value));
|
||||
}
|
||||
|
||||
static detail::error_result insert_copyable(std::false_type, lua_State*, T&, stack_object, stack_object) {
|
||||
|
@ -23392,12 +23426,6 @@ namespace sol { namespace u_detail {
|
|||
inline void set(lua_State* L, Key&& key, Value&& value);
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
inline int destroy_usertype_storage(lua_State* L) noexcept {
|
||||
clear_usertype_registry_names<T>(L);
|
||||
return detail::user_alloc_destroy<usertype_storage<T>>(L);
|
||||
}
|
||||
|
||||
template <typename T, typename Key, typename Value>
|
||||
void usertype_storage_base::set(lua_State* L, Key&& key, Value&& value) {
|
||||
using ValueU = meta::unwrap_unqualified_t<Value>;
|
||||
|
@ -23539,6 +23567,34 @@ namespace sol { namespace u_detail {
|
|||
static_cast<usertype_storage_base&>(*this).set<T>(L, std::forward<Key>(key), std::forward<Value>(value));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void clear_usertype_registry_names(lua_State* L) {
|
||||
using u_traits = usertype_traits<T>;
|
||||
using u_const_traits = usertype_traits<const T>;
|
||||
using u_unique_traits = usertype_traits<d::u<T>>;
|
||||
using u_ref_traits = usertype_traits<T*>;
|
||||
using u_const_ref_traits = usertype_traits<T const*>;
|
||||
|
||||
stack_reference registry(L, raw_index(LUA_REGISTRYINDEX));
|
||||
registry.push();
|
||||
// eliminate all named entries for this usertype
|
||||
// in the registry (luaL_newmetatable does
|
||||
// [name] = new table
|
||||
// in registry upon creation
|
||||
stack::set_field(L, &u_traits::metatable()[0], lua_nil, registry.stack_index());
|
||||
stack::set_field(L, &u_const_traits::metatable()[0], lua_nil, registry.stack_index());
|
||||
stack::set_field(L, &u_const_ref_traits::metatable()[0], lua_nil, registry.stack_index());
|
||||
stack::set_field(L, &u_ref_traits::metatable()[0], lua_nil, registry.stack_index());
|
||||
stack::set_field(L, &u_unique_traits::metatable()[0], lua_nil, registry.stack_index());
|
||||
registry.pop();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline int destroy_usertype_storage(lua_State* L) noexcept {
|
||||
clear_usertype_registry_names<T>(L);
|
||||
return detail::user_alloc_destroy<usertype_storage<T>>(L);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline usertype_storage<T>& create_usertype_storage(lua_State* L) {
|
||||
const char* gcmetakey = &usertype_traits<T>::gc_table()[0];
|
||||
|
@ -23634,28 +23690,6 @@ namespace sol { namespace u_detail {
|
|||
return target_umt;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void clear_usertype_registry_names(lua_State* L) {
|
||||
using u_traits = usertype_traits<T>;
|
||||
using u_const_traits = usertype_traits<const T>;
|
||||
using u_unique_traits = usertype_traits<d::u<T>>;
|
||||
using u_ref_traits = usertype_traits<T*>;
|
||||
using u_const_ref_traits = usertype_traits<T const*>;
|
||||
|
||||
stack_reference registry(L, raw_index(LUA_REGISTRYINDEX));
|
||||
registry.push();
|
||||
// eliminate all named entries for this usertype
|
||||
// in the registry (luaL_newmetatable does
|
||||
// [name] = new table
|
||||
// in registry upon creation
|
||||
stack::set_field(L, &u_traits::metatable()[0], lua_nil, registry.stack_index());
|
||||
stack::set_field(L, &u_const_traits::metatable()[0], lua_nil, registry.stack_index());
|
||||
stack::set_field(L, &u_const_ref_traits::metatable()[0], lua_nil, registry.stack_index());
|
||||
stack::set_field(L, &u_ref_traits::metatable()[0], lua_nil, registry.stack_index());
|
||||
stack::set_field(L, &u_unique_traits::metatable()[0], lua_nil, registry.stack_index());
|
||||
registry.pop();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void clear_usertype_storage(lua_State* L) {
|
||||
using u_traits = usertype_traits<T>;
|
||||
|
@ -24493,9 +24527,9 @@ namespace sol {
|
|||
: m_L(nullptr)
|
||||
, m_next_function_ref(lua_nil)
|
||||
, m_table_ref(lua_nil)
|
||||
, m_cached_key_value_pair({ lua_nil, lua_nil })
|
||||
, m_key_index(empty_key_index)
|
||||
, m_iteration_index(0)
|
||||
, m_cached_key_value_pair({ lua_nil, lua_nil }) {
|
||||
, m_iteration_index(0) {
|
||||
}
|
||||
|
||||
pairs_iterator(const pairs_iterator&) = delete;
|
||||
|
@ -24505,9 +24539,9 @@ namespace sol {
|
|||
: m_L(right.m_L)
|
||||
, m_next_function_ref(std::move(right.m_next_function_ref))
|
||||
, m_table_ref(std::move(right.m_table_ref))
|
||||
, m_cached_key_value_pair(std::move(right.m_cached_key_value_pair))
|
||||
, m_key_index(right.m_key_index)
|
||||
, m_iteration_index(right.m_iteration_index)
|
||||
, m_cached_key_value_pair(std::move(right.m_cached_key_value_pair)) {
|
||||
, m_iteration_index(right.m_iteration_index) {
|
||||
right.m_key_index = empty_key_index;
|
||||
}
|
||||
|
||||
|
@ -24515,10 +24549,11 @@ namespace sol {
|
|||
m_L = right.m_L;
|
||||
m_next_function_ref = std::move(right.m_next_function_ref);
|
||||
m_table_ref = std::move(right.m_table_ref);
|
||||
m_cached_key_value_pair = std::move(right.m_cached_key_value_pair);
|
||||
m_key_index = right.m_key_index;
|
||||
m_iteration_index = right.m_iteration_index;
|
||||
m_cached_key_value_pair = std::move(right.m_cached_key_value_pair);
|
||||
right.m_key_index = empty_key_index;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename Source>
|
||||
|
@ -24533,8 +24568,9 @@ namespace sol {
|
|||
lua_remove(m_L, abs_source_index);
|
||||
if (metatable_exists == 1) {
|
||||
// just has a metatable, but does it have __pairs ?
|
||||
stack_lua_table metatable(m_L, abs_source_index);
|
||||
optional<protected_function> maybe_pairs_function = metatable.raw_get<optional<function>>(meta_function::pairs);
|
||||
stack_reference metatable(m_L, raw_index(abs_source_index));
|
||||
stack::get_field<is_global_table_v<Source>, true>(m_L, meta_function::pairs, metatable.stack_index());
|
||||
optional<protected_function> maybe_pairs_function = stack::pop<optional<function>>(m_L);
|
||||
if (maybe_pairs_function.has_value()) {
|
||||
function& pairs_function = *maybe_pairs_function;
|
||||
protected_function_result next_fn_and_table_and_first_key = pairs_function(source_);
|
||||
|
|
|
@ -36,111 +36,193 @@
|
|||
#include <set>
|
||||
#include <unordered_set>
|
||||
|
||||
class int_shim {
|
||||
public:
|
||||
int_shim() = default;
|
||||
|
||||
int_shim(int x) : x_(x) {
|
||||
}
|
||||
inline namespace sol2_test_container_shims {
|
||||
|
||||
int val() const {
|
||||
return x_;
|
||||
}
|
||||
class int_shim {
|
||||
public:
|
||||
int_shim() = default;
|
||||
|
||||
private:
|
||||
int x_ = -1;
|
||||
};
|
||||
|
||||
class input_it {
|
||||
public:
|
||||
typedef std::input_iterator_tag iterator_category;
|
||||
typedef int_shim value_type;
|
||||
typedef value_type& reference;
|
||||
typedef const value_type& const_reference;
|
||||
typedef value_type* pointer;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
|
||||
input_it() = default;
|
||||
|
||||
input_it(int n, int m) : n_(n), m_(m), value_(n_) {
|
||||
assert(n_ >= 0);
|
||||
assert(m_ >= 0);
|
||||
assert(n_ <= m_);
|
||||
|
||||
if (!n_ && !m_) {
|
||||
n_ = -1;
|
||||
m_ = -1;
|
||||
value_ = -1;
|
||||
int_shim(int x) : x_(x) {
|
||||
}
|
||||
}
|
||||
|
||||
const int_shim& operator*() const {
|
||||
return value_;
|
||||
}
|
||||
|
||||
const int_shim* operator->() const {
|
||||
return &value_;
|
||||
}
|
||||
|
||||
input_it& operator++() {
|
||||
assert(n_ >= 0);
|
||||
assert(m_ >= 0);
|
||||
if (n_ == m_ - 1) {
|
||||
n_ = m_ = -1;
|
||||
int val() const {
|
||||
return x_;
|
||||
}
|
||||
else {
|
||||
++n_;
|
||||
|
||||
private:
|
||||
int x_ = -1;
|
||||
};
|
||||
|
||||
class input_it {
|
||||
public:
|
||||
typedef std::input_iterator_tag iterator_category;
|
||||
typedef int_shim value_type;
|
||||
typedef value_type& reference;
|
||||
typedef const value_type& const_reference;
|
||||
typedef value_type* pointer;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
|
||||
input_it() = default;
|
||||
|
||||
input_it(int n, int m) : n_(n), m_(m), value_(n_) {
|
||||
assert(n_ >= 0);
|
||||
assert(m_ >= 0);
|
||||
assert(n_ <= m_);
|
||||
|
||||
if (!n_ && !m_) {
|
||||
n_ = -1;
|
||||
m_ = -1;
|
||||
value_ = -1;
|
||||
}
|
||||
}
|
||||
value_ = n_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator==(const input_it& i) const {
|
||||
return n_ == i.n_ && m_ == i.m_;
|
||||
}
|
||||
const int_shim& operator*() const {
|
||||
return value_;
|
||||
}
|
||||
|
||||
bool operator!=(const input_it& i) const {
|
||||
return !(*this == i);
|
||||
}
|
||||
const int_shim* operator->() const {
|
||||
return &value_;
|
||||
}
|
||||
|
||||
private:
|
||||
int n_ = -1;
|
||||
int m_ = -1;
|
||||
int_shim value_;
|
||||
};
|
||||
input_it& operator++() {
|
||||
assert(n_ >= 0);
|
||||
assert(m_ >= 0);
|
||||
if (n_ == m_ - 1) {
|
||||
n_ = m_ = -1;
|
||||
}
|
||||
else {
|
||||
++n_;
|
||||
}
|
||||
value_ = n_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
class not_really_a_container {
|
||||
public:
|
||||
using value_type = int_shim;
|
||||
using iterator = input_it;
|
||||
using const_iterator = input_it;
|
||||
bool operator==(const input_it& i) const {
|
||||
return n_ == i.n_ && m_ == i.m_;
|
||||
}
|
||||
|
||||
const_iterator begin() const {
|
||||
return iterator(0, 100);
|
||||
}
|
||||
bool operator!=(const input_it& i) const {
|
||||
return !(*this == i);
|
||||
}
|
||||
|
||||
const_iterator end() const {
|
||||
return iterator();
|
||||
}
|
||||
private:
|
||||
int n_ = -1;
|
||||
int m_ = -1;
|
||||
int_shim value_;
|
||||
};
|
||||
|
||||
value_type gcc_warning_block() {
|
||||
return int_shim();
|
||||
}
|
||||
class not_really_a_container {
|
||||
public:
|
||||
using value_type = int_shim;
|
||||
using iterator = input_it;
|
||||
using const_iterator = input_it;
|
||||
|
||||
std::size_t size() const {
|
||||
return 100;
|
||||
}
|
||||
};
|
||||
const_iterator begin() const {
|
||||
return iterator(0, 100);
|
||||
}
|
||||
|
||||
struct my_vec : public std::vector<int> {
|
||||
typedef std::vector<int> base_t;
|
||||
using base_t::base_t;
|
||||
};
|
||||
const_iterator end() const {
|
||||
return iterator();
|
||||
}
|
||||
|
||||
value_type gcc_warning_block() {
|
||||
return int_shim();
|
||||
}
|
||||
|
||||
std::size_t size() const {
|
||||
return 100;
|
||||
}
|
||||
};
|
||||
|
||||
struct my_vec : public std::vector<int> {
|
||||
typedef std::vector<int> base_t;
|
||||
using base_t::base_t;
|
||||
};
|
||||
|
||||
struct order_suit {
|
||||
std::vector<std::pair<int, int64_t>> objs;
|
||||
std::vector<std::pair<int64_t, int>> objs2;
|
||||
|
||||
order_suit(int pairs) {
|
||||
objs.reserve(static_cast<std::size_t>(pairs));
|
||||
objs2.reserve(static_cast<std::size_t>(pairs * 2));
|
||||
for (int i = 0; i < pairs; ++i) {
|
||||
objs.push_back({ i, i * 10 });
|
||||
objs2.push_back({ (i + pairs) * 2, (i * 2) * 50 });
|
||||
objs2.push_back({ ((i + pairs) * 2) + 1, (i * 2 + 1) * 50 });
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class map_number_storage {
|
||||
|
||||
private:
|
||||
std::unordered_map<std::string, int> data; // changed to map
|
||||
|
||||
public:
|
||||
map_number_storage(int i) {
|
||||
data[std::to_string(i)] = i;
|
||||
}
|
||||
|
||||
int accumulate() const // changed for map
|
||||
{
|
||||
std::size_t sum = 0;
|
||||
for (const auto& [k, v] : data) {
|
||||
sum += v;
|
||||
}
|
||||
return static_cast<int>(sum);
|
||||
}
|
||||
|
||||
public:
|
||||
typedef std::string key_type;
|
||||
typedef int mapped_type;
|
||||
using value_type = decltype(data)::value_type;
|
||||
using iterator = decltype(data)::iterator;
|
||||
using const_iterator = decltype(data)::const_iterator;
|
||||
using size_type = decltype(data)::size_type;
|
||||
|
||||
// ADDED
|
||||
iterator find(const key_type& key) {
|
||||
return data.find(key);
|
||||
}
|
||||
auto insert(value_type kv) {
|
||||
return data.insert(kv);
|
||||
}
|
||||
auto insert(const key_type k, mapped_type v) {
|
||||
return data.insert({ k, v });
|
||||
}
|
||||
mapped_type& set(key_type k, mapped_type v) {
|
||||
return data[k] = v;
|
||||
}
|
||||
|
||||
iterator begin() {
|
||||
return iterator(data.begin());
|
||||
}
|
||||
iterator end() {
|
||||
return iterator(data.end());
|
||||
}
|
||||
size_type size() const noexcept {
|
||||
return data.size();
|
||||
}
|
||||
size_type max_size() const noexcept {
|
||||
return data.max_size();
|
||||
}
|
||||
// void push_back(int value) { data.push_back(value); } NOT APPLICABLE TO MAP
|
||||
bool empty() const noexcept {
|
||||
return data.empty();
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace sol2_test_container_shims
|
||||
|
||||
namespace sol {
|
||||
template <>
|
||||
struct is_container<my_vec> : std::true_type { };
|
||||
|
||||
template <>
|
||||
struct is_container<map_number_storage> : std::false_type { };
|
||||
|
||||
template <>
|
||||
struct usertype_container<my_vec> {
|
||||
// Hooks Lua's syntax for #c
|
||||
|
@ -164,20 +246,6 @@ namespace sol {
|
|||
|
||||
} // namespace sol
|
||||
|
||||
struct order_suit {
|
||||
std::vector<std::pair<int, int64_t>> objs;
|
||||
std::vector<std::pair<int64_t, int>> objs2;
|
||||
|
||||
order_suit(int pairs) {
|
||||
objs.reserve(static_cast<std::size_t>(pairs));
|
||||
objs2.reserve(static_cast<std::size_t>(pairs * 2));
|
||||
for (int i = 0; i < pairs; ++i) {
|
||||
objs.push_back({ i, i * 10 });
|
||||
objs2.push_back({ (i + pairs) * 2, (i * 2) * 50 });
|
||||
objs2.push_back({ ((i + pairs) * 2) + 1, (i * 2 + 1) * 50 });
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
TEST_CASE("containers/input iterators", "test shitty input iterators that are all kinds of B L E H") {
|
||||
sol::state lua;
|
||||
|
@ -319,3 +387,48 @@ TEST_CASE("containers/pair container in usertypes", "make sure containers that u
|
|||
REQUIRE(pvec2[3].first == 13);
|
||||
REQUIRE(pvec2[3].second == 150);
|
||||
}
|
||||
|
||||
TEST_CASE("containers/as_container usertype", "A usertype should be able to mark itself as a container explicitly and work with BOTH kinds of insert types") {
|
||||
sol::state lua;
|
||||
lua.open_libraries(sol::lib::base);
|
||||
|
||||
lua.new_usertype<map_number_storage>("map_number_storage",
|
||||
sol::constructors<map_number_storage(int)>(),
|
||||
"accumulate",
|
||||
&map_number_storage::accumulate,
|
||||
"iterable",
|
||||
[](map_number_storage& ns) {
|
||||
return sol::as_container(ns); // treat like a container, despite is_container specialization
|
||||
});
|
||||
|
||||
sol::optional<sol::error> maybe_error0 = lua.safe_script(R"(
|
||||
ns = map_number_storage.new(23)
|
||||
assert(ns:accumulate() == 23)
|
||||
|
||||
-- reference original usertype like a container
|
||||
ns_container = ns:iterable()
|
||||
ns_container["24"]=24
|
||||
|
||||
-- now print to show effect
|
||||
assert(ns:accumulate() == 47)
|
||||
assert(#ns == 2)
|
||||
)",
|
||||
&sol::script_pass_on_error);
|
||||
REQUIRE_FALSE(maybe_error0.has_value());
|
||||
|
||||
map_number_storage& ns = lua["ns"];
|
||||
map_number_storage& ns_container = lua["ns_container"];
|
||||
|
||||
ns.insert({ "33", 33 });
|
||||
|
||||
sol::optional<sol::error> maybe_error1 = lua.safe_script(R"(
|
||||
assert(ns:accumulate() == 80)
|
||||
assert(#ns == 3)
|
||||
assert(ns_container['33'] == 33)
|
||||
)",
|
||||
&sol::script_pass_on_error);
|
||||
REQUIRE_FALSE(maybe_error1.has_value());
|
||||
|
||||
REQUIRE(&ns == &ns_container);
|
||||
REQUIRE(ns.size() == 3);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user