mirror of
https://github.com/ThePhD/sol2.git
synced 2024-03-22 13:10:44 +08:00
update tests (which compile, but now all fail)
This commit is contained in:
parent
e74ce68163
commit
9b47849110
|
@ -50,16 +50,6 @@ namespace sol {
|
|||
struct undefined_metatable;
|
||||
}
|
||||
} // namespace stack::stack_detail
|
||||
|
||||
namespace u_detail {
|
||||
template <typename T, typename Regs, typename Fx>
|
||||
void insert_default_registrations(Regs& l, int& index, Fx&& fx);
|
||||
|
||||
template <typename T, typename Regs, meta::enable<meta::neg<std::is_pointer<T>>, std::is_destructible<T>> = meta::enabler>
|
||||
void make_destructor(Regs& l, int& index);
|
||||
template <typename T, typename Regs, meta::disable<meta::neg<std::is_pointer<T>>, std::is_destructible<T>> = meta::enabler>
|
||||
void make_destructor(Regs& l, int& index);
|
||||
} // namespace u_detail
|
||||
} // namespace sol
|
||||
|
||||
#endif // SOL_FORWARD_DETAIL_HPP
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// sol3
|
||||
// sol3
|
||||
|
||||
// The MIT License (MIT)
|
||||
|
||||
|
@ -37,6 +37,7 @@
|
|||
#include "forward_detail.hpp"
|
||||
|
||||
#include <vector>
|
||||
#include <bitset>
|
||||
#include <forward_list>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
|
@ -51,6 +52,8 @@ namespace sol {
|
|||
template <typename T>
|
||||
struct as_table_tag {};
|
||||
|
||||
using lua_reg_table = luaL_Reg[64];
|
||||
|
||||
using unique_destructor = void (*)(void*);
|
||||
using unique_tag = detail::inheritance_unique_cast_function;
|
||||
|
||||
|
@ -340,7 +343,7 @@ namespace sol {
|
|||
return false;
|
||||
}
|
||||
allocated_size -= sizeof(T*);
|
||||
|
||||
|
||||
adjusted = static_cast<void*>(static_cast<char*>(pointer_adjusted) + sizeof(T*));
|
||||
dx_adjusted = align(std::alignment_of<unique_destructor>::value, sizeof(unique_destructor), adjusted, allocated_size);
|
||||
if (dx_adjusted == nullptr) {
|
||||
|
@ -348,7 +351,7 @@ namespace sol {
|
|||
return false;
|
||||
}
|
||||
allocated_size -= sizeof(unique_destructor);
|
||||
|
||||
|
||||
adjusted = static_cast<void*>(static_cast<char*>(dx_adjusted) + sizeof(unique_destructor));
|
||||
|
||||
id_adjusted = align(std::alignment_of<unique_tag>::value, sizeof(unique_tag), adjusted, allocated_size);
|
||||
|
@ -357,7 +360,7 @@ namespace sol {
|
|||
return false;
|
||||
}
|
||||
allocated_size -= sizeof(unique_tag);
|
||||
|
||||
|
||||
adjusted = static_cast<void*>(static_cast<char*>(id_adjusted) + sizeof(unique_tag));
|
||||
data_adjusted = align(std::alignment_of<Real>::value, sizeof(Real), adjusted, allocated_size);
|
||||
if (data_adjusted == nullptr) {
|
||||
|
@ -488,6 +491,200 @@ namespace sol {
|
|||
void reserve(std::basic_string<T, Tr, Al>& arr, std::size_t hint) {
|
||||
arr.reserve(hint);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline lua_CFunction make_destructor() {
|
||||
if constexpr (std::is_destructible_v<T>) {
|
||||
if constexpr (is_unique_usertype_v<T>) {
|
||||
return &unique_destruct<T>;
|
||||
}
|
||||
else if constexpr (!std::is_pointer_v<T>) {
|
||||
return &usertype_alloc_destruct<T>;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return &cannot_destruct<T>;
|
||||
}
|
||||
}
|
||||
|
||||
struct no_comp {
|
||||
template <typename A, typename B>
|
||||
bool operator()(A&&, B&&) const {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
inline int is_check(lua_State* L) {
|
||||
return stack::push(L, stack::check<T>(L, 1, &no_panic));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline int member_default_to_string(std::true_type, lua_State* L) {
|
||||
decltype(auto) ts = stack::get<T>(L, 1).to_string();
|
||||
return stack::push(L, std::forward<decltype(ts)>(ts));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline int member_default_to_string(std::false_type, lua_State* L) {
|
||||
return luaL_error(L, "cannot perform to_string on '%s': no 'to_string' overload in namespace, 'to_string' member function, or operator<<(ostream&, ...) present", detail::demangle<T>().data());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline int adl_default_to_string(std::true_type, lua_State* L) {
|
||||
using namespace std;
|
||||
decltype(auto) ts = to_string(stack::get<T>(L, 1));
|
||||
return stack::push(L, std::forward<decltype(ts)>(ts));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline int adl_default_to_string(std::false_type, lua_State* L) {
|
||||
return member_default_to_string<T>(meta::supports_to_string_member<T>(), L);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline int oss_default_to_string(std::true_type, lua_State* L) {
|
||||
std::ostringstream oss;
|
||||
oss << stack::unqualified_get<T>(L, 1);
|
||||
return stack::push(L, oss.str());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline int oss_default_to_string(std::false_type, lua_State* L) {
|
||||
return adl_default_to_string<T>(meta::supports_adl_to_string<T>(), L);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline int default_to_string(lua_State* L) {
|
||||
return oss_default_to_string<T>(meta::supports_ostream_op<T>(), L);
|
||||
}
|
||||
|
||||
template <typename T, typename Op>
|
||||
int comparsion_operator_wrap(lua_State* L) {
|
||||
auto maybel = stack::unqualified_check_get<T&>(L, 1);
|
||||
if (maybel) {
|
||||
auto mayber = stack::unqualified_check_get<T&>(L, 2);
|
||||
if (mayber) {
|
||||
auto& l = *maybel;
|
||||
auto& r = *mayber;
|
||||
if (std::is_same<no_comp, Op>::value) {
|
||||
return stack::push(L, detail::ptr(l) == detail::ptr(r));
|
||||
}
|
||||
else {
|
||||
Op op;
|
||||
return stack::push(L, (detail::ptr(l) == detail::ptr(r)) || op(detail::deref(l), detail::deref(r)));
|
||||
}
|
||||
}
|
||||
}
|
||||
return stack::push(L, false);
|
||||
}
|
||||
|
||||
template <typename T, typename IFx, typename Fx>
|
||||
inline void insert_default_registrations(IFx&& ifx, Fx&& fx) {
|
||||
if constexpr (is_automagical<T>::value) {
|
||||
if (fx(meta_function::less_than)) {
|
||||
if constexpr (meta::supports_op_less<T>::value) {
|
||||
lua_CFunction f = &comparsion_operator_wrap<T, std::less<>>;
|
||||
ifx(meta_function::less_than, f);
|
||||
}
|
||||
}
|
||||
if (fx(meta_function::less_than_or_equal_to)) {
|
||||
if constexpr (meta::supports_op_less_equal<T>::value) {
|
||||
lua_CFunction f = &comparsion_operator_wrap<T, std::less_equal<>>;
|
||||
ifx(meta_function::less_than_or_equal_to, f);
|
||||
}
|
||||
}
|
||||
if (fx(meta_function::equal_to)) {
|
||||
if constexpr (meta::supports_op_equal<T>::value) {
|
||||
lua_CFunction f = &comparsion_operator_wrap<T, std::equal_to<>>;
|
||||
ifx(meta_function::equal_to, f);
|
||||
}
|
||||
}
|
||||
if (fx(meta_function::pairs)) {
|
||||
ifx(meta_function::pairs, &usertype_container<as_container_t<T>>::pairs_call);
|
||||
}
|
||||
if (fx(meta_function::length)) {
|
||||
if constexpr (meta::has_size<const T>::value) {
|
||||
#if defined(__clang__)
|
||||
ifx(meta_function::length, &c_call<decltype(&T::size), &T::size>);
|
||||
#else
|
||||
typedef decltype(std::declval<T const>().size()) R;
|
||||
using sz_func = R (T::*)() const;
|
||||
lua_CFunction f = &c_call<decltype(static_cast<sz_func>(&T::size)), static_cast<sz_func>(&T::size)>;
|
||||
ifx(meta_function::length, f);
|
||||
#endif
|
||||
}
|
||||
else if constexpr (meta::has_size<T>::value) {
|
||||
#if defined(__clang__)
|
||||
ifx(meta_function::length, &c_call<decltype(&T::size), &T::size>);
|
||||
#else
|
||||
typedef decltype(std::declval<T>().size()) R;
|
||||
using sz_func = R (T::*)();
|
||||
ifx(meta_function::length, &c_call<decltype(static_cast<sz_func>(&T::size)), static_cast<sz_func>(&T::size)>);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
if (fx(meta_function::to_string)) {
|
||||
if constexpr (is_to_stringable<T>::value) {
|
||||
lua_CFunction f = &detail::static_trampoline<&default_to_string<T>>;
|
||||
ifx(meta_function::to_string, f);
|
||||
}
|
||||
}
|
||||
if (fx(meta_function::call_function)) {
|
||||
if constexpr (meta::has_deducible_signature<T>::value) {
|
||||
lua_CFunction f = &c_call<decltype(&T::operator()), &T::operator()>;
|
||||
ifx(meta_function::call_function, f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline bool property_always_true(meta_function) {
|
||||
return true;
|
||||
}
|
||||
|
||||
struct properties_enrollment_allowed {
|
||||
std::bitset<64>& properties;
|
||||
automagic_enrollments& enrollments;
|
||||
|
||||
properties_enrollment_allowed(std::bitset<64>& props, automagic_enrollments& enroll)
|
||||
: properties(props), enrollments(enroll) {
|
||||
}
|
||||
|
||||
bool operator()(meta_function mf) const {
|
||||
bool p = properties[static_cast<int>(mf)];
|
||||
switch (mf) {
|
||||
case meta_function::length:
|
||||
return enrollments.length_operator && !p;
|
||||
case meta_function::pairs:
|
||||
return enrollments.pairs_operator && !p;
|
||||
case meta_function::call:
|
||||
return enrollments.call_operator && !p;
|
||||
case meta_function::less_than:
|
||||
return enrollments.less_than_operator && !p;
|
||||
case meta_function::less_than_or_equal_to:
|
||||
return enrollments.less_than_or_equal_to_operator && !p;
|
||||
case meta_function::equal_to:
|
||||
return enrollments.equal_to_operator && !p;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return !p;
|
||||
}
|
||||
};
|
||||
|
||||
struct indexed_insert {
|
||||
lua_reg_table& l;
|
||||
int& index;
|
||||
|
||||
indexed_insert(lua_reg_table& cont, int& idx)
|
||||
: l(cont), index(idx) {
|
||||
}
|
||||
void operator()(meta_function mf, lua_CFunction f) {
|
||||
l[index] = luaL_Reg{ to_string(mf).c_str(), f };
|
||||
++index;
|
||||
}
|
||||
};
|
||||
} // namespace detail
|
||||
|
||||
namespace stack {
|
||||
|
|
|
@ -75,7 +75,7 @@ namespace stack {
|
|||
// do the actual object. Things that are std::ref or plain T* are stored as
|
||||
// just the sizeof(T*), and nothing else.
|
||||
T* obj = detail::usertype_allocate<T>(L);
|
||||
std::allocator<T> alloc {};
|
||||
std::allocator<T> alloc{};
|
||||
std::allocator_traits<std::allocator<T>>::construct(alloc, obj, std::forward<Args>(args)...);
|
||||
f();
|
||||
return 1;
|
||||
|
@ -130,7 +130,7 @@ namespace stack {
|
|||
struct pusher {
|
||||
template <typename... Args>
|
||||
static int push(lua_State* L, Args&&... args) {
|
||||
return pusher<detail::as_value_tag<T>> {}.push(L, std::forward<Args>(args)...);
|
||||
return pusher<detail::as_value_tag<T>>{}.push(L, std::forward<Args>(args)...);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -138,7 +138,7 @@ namespace stack {
|
|||
struct pusher<T*, meta::disable_if_t<meta::any<is_container<meta::unqualified_t<T>>, std::is_function<meta::unqualified_t<T>>, is_lua_reference<meta::unqualified_t<T>>>::value>> {
|
||||
template <typename... Args>
|
||||
static int push(lua_State* L, Args&&... args) {
|
||||
return pusher<detail::as_pointer_tag<T>> {}.push(L, std::forward<Args>(args)...);
|
||||
return pusher<detail::as_pointer_tag<T>>{}.push(L, std::forward<Args>(args)...);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -173,11 +173,11 @@ namespace stack {
|
|||
detail::default_construct::construct(mem, std::forward<Args>(args)...);
|
||||
*pref = unique_usertype_traits<T>::get(*mem);
|
||||
if (luaL_newmetatable(L, &usertype_traits<detail::unique_usertype<std::remove_cv_t<P>>>::metatable()[0]) == 1) {
|
||||
luaL_Reg l[32] {};
|
||||
detail::lua_reg_table l{};
|
||||
int index = 0;
|
||||
auto prop_fx = [](meta_function) { return true; };
|
||||
u_detail::insert_default_registrations<P>(l, index, prop_fx);
|
||||
u_detail::make_destructor<T>(l, index);
|
||||
detail::indexed_insert insert_fx(l, index);
|
||||
detail::insert_default_registrations<P>(insert_fx, detail::property_always_true);
|
||||
l[index] = { to_string(meta_function::garbage_collect).c_str(), detail::make_destructor<T>() };
|
||||
luaL_setfuncs(L, l, 0);
|
||||
}
|
||||
lua_setmetatable(L, -2);
|
||||
|
@ -334,7 +334,7 @@ namespace stack {
|
|||
template <typename T>
|
||||
struct pusher<nested<T>, std::enable_if_t<is_container<std::remove_pointer_t<meta::unwrap_unqualified_t<T>>>::value>> {
|
||||
static int push(lua_State* L, const T& tablecont) {
|
||||
pusher<detail::as_table_tag<T>> p {};
|
||||
pusher<detail::as_table_tag<T>> p{};
|
||||
// silence annoying VC++ warning
|
||||
(void)p;
|
||||
return p.push(std::true_type(), L, tablecont);
|
||||
|
@ -344,7 +344,7 @@ namespace stack {
|
|||
template <typename T>
|
||||
struct pusher<nested<T>, std::enable_if_t<!is_container<std::remove_pointer_t<meta::unwrap_unqualified_t<T>>>::value>> {
|
||||
static int push(lua_State* L, const T& tablecont) {
|
||||
pusher<meta::unqualified_t<T>> p {};
|
||||
pusher<meta::unqualified_t<T>> p{};
|
||||
// silence annoying VC++ warning
|
||||
(void)p;
|
||||
return p.push(L, tablecont);
|
||||
|
@ -354,7 +354,7 @@ namespace stack {
|
|||
template <typename T>
|
||||
struct pusher<std::initializer_list<T>> {
|
||||
static int push(lua_State* L, const std::initializer_list<T>& il) {
|
||||
pusher<detail::as_table_tag<std::initializer_list<T>>> p {};
|
||||
pusher<detail::as_table_tag<std::initializer_list<T>>> p{};
|
||||
// silence annoying VC++ warning
|
||||
(void)p;
|
||||
return p.push(L, il);
|
||||
|
@ -497,7 +497,7 @@ namespace stack {
|
|||
static int push_with(lua_State* L, Key&& name, Args&&... args) {
|
||||
// A dumb pusher
|
||||
T* data = detail::user_allocate<T>(L);
|
||||
std::allocator<T> alloc {};
|
||||
std::allocator<T> alloc{};
|
||||
std::allocator_traits<std::allocator<T>>::construct(alloc, data, std::forward<Args>(args)...);
|
||||
if (with_meta) {
|
||||
// Make sure we have a plain GC set for this data
|
||||
|
@ -584,25 +584,25 @@ namespace stack {
|
|||
template <>
|
||||
struct pusher<char*> {
|
||||
static int push_sized(lua_State* L, const char* str, std::size_t len) {
|
||||
pusher<const char*> p {};
|
||||
pusher<const char*> p{};
|
||||
(void)p;
|
||||
return p.push_sized(L, str, len);
|
||||
}
|
||||
|
||||
static int push(lua_State* L, const char* str) {
|
||||
pusher<const char*> p {};
|
||||
pusher<const char*> p{};
|
||||
(void)p;
|
||||
return p.push(L, str);
|
||||
}
|
||||
|
||||
static int push(lua_State* L, const char* strb, const char* stre) {
|
||||
pusher<const char*> p {};
|
||||
pusher<const char*> p{};
|
||||
(void)p;
|
||||
return p.push(L, strb, stre);
|
||||
}
|
||||
|
||||
static int push(lua_State* L, const char* str, std::size_t len) {
|
||||
pusher<const char*> p {};
|
||||
pusher<const char*> p{};
|
||||
(void)p;
|
||||
return p.push(L, str, len);
|
||||
}
|
||||
|
@ -711,19 +711,19 @@ namespace stack {
|
|||
template <>
|
||||
struct pusher<wchar_t*> {
|
||||
static int push(lua_State* L, const wchar_t* str) {
|
||||
pusher<const wchar_t*> p {};
|
||||
pusher<const wchar_t*> p{};
|
||||
(void)p;
|
||||
return p.push(L, str);
|
||||
}
|
||||
|
||||
static int push(lua_State* L, const wchar_t* strb, const wchar_t* stre) {
|
||||
pusher<const wchar_t*> p {};
|
||||
pusher<const wchar_t*> p{};
|
||||
(void)p;
|
||||
return p.push(L, strb, stre);
|
||||
}
|
||||
|
||||
static int push(lua_State* L, const wchar_t* str, std::size_t len) {
|
||||
pusher<const wchar_t*> p {};
|
||||
pusher<const wchar_t*> p{};
|
||||
(void)p;
|
||||
return p.push(L, str, len);
|
||||
}
|
||||
|
@ -791,19 +791,19 @@ namespace stack {
|
|||
template <>
|
||||
struct pusher<char16_t*> {
|
||||
static int push(lua_State* L, const char16_t* str) {
|
||||
pusher<const char16_t*> p {};
|
||||
pusher<const char16_t*> p{};
|
||||
(void)p;
|
||||
return p.push(L, str);
|
||||
}
|
||||
|
||||
static int push(lua_State* L, const char16_t* strb, const char16_t* stre) {
|
||||
pusher<const char16_t*> p {};
|
||||
pusher<const char16_t*> p{};
|
||||
(void)p;
|
||||
return p.push(L, strb, stre);
|
||||
}
|
||||
|
||||
static int push(lua_State* L, const char16_t* str, std::size_t len) {
|
||||
pusher<const char16_t*> p {};
|
||||
pusher<const char16_t*> p{};
|
||||
(void)p;
|
||||
return p.push(L, str, len);
|
||||
}
|
||||
|
@ -869,19 +869,19 @@ namespace stack {
|
|||
template <>
|
||||
struct pusher<char32_t*> {
|
||||
static int push(lua_State* L, const char32_t* str) {
|
||||
pusher<const char32_t*> p {};
|
||||
pusher<const char32_t*> p{};
|
||||
(void)p;
|
||||
return p.push(L, str);
|
||||
}
|
||||
|
||||
static int push(lua_State* L, const char32_t* strb, const char32_t* stre) {
|
||||
pusher<const char32_t*> p {};
|
||||
pusher<const char32_t*> p{};
|
||||
(void)p;
|
||||
return p.push(L, strb, stre);
|
||||
}
|
||||
|
||||
static int push(lua_State* L, const char32_t* str, std::size_t len) {
|
||||
pusher<const char32_t*> p {};
|
||||
pusher<const char32_t*> p{};
|
||||
(void)p;
|
||||
return p.push(L, str, len);
|
||||
}
|
||||
|
@ -960,7 +960,7 @@ namespace stack {
|
|||
template <std::size_t... I, typename T>
|
||||
static int push(std::index_sequence<I...>, lua_State* L, T&& t) {
|
||||
int pushcount = 0;
|
||||
(void)detail::swallow { 0, (pushcount += stack::push(L, detail::forward_get<I>(t)), 0)... };
|
||||
(void)detail::swallow{ 0, (pushcount += stack::push(L, detail::forward_get<I>(t)), 0)... };
|
||||
return pushcount;
|
||||
}
|
||||
|
||||
|
|
|
@ -30,16 +30,41 @@
|
|||
namespace sol {
|
||||
typedef table_core<false> table;
|
||||
|
||||
template <bool top_level, typename base_type>
|
||||
template <typename Class, typename Key, typename... Args>
|
||||
usertype<Class> basic_table_core<top_level, base_type>::new_usertype(Key&& key, Args&&... args) {
|
||||
int mt_index = u_detail::register_usertype<Class>(this->lua_state(), detail::any_is_constructor_v<Args...> ? optional<no_construction>() : optional<no_construction>(no_constructor));
|
||||
template <bool is_global, typename base_type>
|
||||
template <typename Class, typename Key>
|
||||
usertype<Class> basic_table_core<is_global, base_type>::new_usertype(Key&& key) {
|
||||
automagic_enrollments enrollments;
|
||||
return this->new_usertype<Class>(std::forward<Key>(key), std::move(enrollments));
|
||||
}
|
||||
|
||||
template <bool is_global, typename base_type>
|
||||
template <typename Class, typename Key>
|
||||
usertype<Class> basic_table_core<is_global, base_type>::new_usertype(Key&& key, automagic_enrollments enrollments) {
|
||||
int mt_index = u_detail::register_usertype<Class>(this->lua_state(), std::move(enrollments));
|
||||
usertype<Class> mt(this->lua_state(), -mt_index);
|
||||
mt.
|
||||
set(std::forward<Key>(key), mt);
|
||||
return mt;
|
||||
}
|
||||
|
||||
template <bool is_global, typename base_type>
|
||||
template <typename Class, typename Key, typename Arg, typename... Args, typename>
|
||||
usertype<Class> basic_table_core<is_global, base_type>::new_usertype(Key&& key, Arg&& arg, Args&&... args) {
|
||||
automagic_enrollments enrollments;
|
||||
enrollments.default_constructor = !detail::any_is_constructor_v<Arg, Args...>;
|
||||
enrollments.destructor = !detail::any_is_destructor_v<Arg, Args...>;
|
||||
usertype<Class> ut = this->new_usertype<Class>(std::forward<Key>(key), std::move(enrollments));
|
||||
static_assert(sizeof...(Args) % 2 == static_cast<std::size_t>(!detail::any_is_constructor_v<Arg>),
|
||||
"you must pass an even number of arguments to new_usertype after first passing a constructor");
|
||||
if constexpr (detail::any_is_constructor_v<Arg>) {
|
||||
ut.set(meta_function::construct, std::forward<Arg>(arg));
|
||||
ut.tuple_set(std::make_index_sequence<(sizeof...(Args)) / 2>(), std::forward_as_tuple(std::forward<Args>(args)...));
|
||||
}
|
||||
else {
|
||||
ut.tuple_set(std::make_index_sequence<(sizeof...(Args) + 1) / 2>(), std::forward_as_tuple(std::forward<Arg>(arg), std::forward<Args>(args)...));
|
||||
}
|
||||
return ut;
|
||||
}
|
||||
|
||||
template <typename base_type>
|
||||
template <typename Key, typename Value>
|
||||
void basic_metatable<base_type>::set(Key&& key, Value&& value) {
|
||||
|
@ -48,6 +73,9 @@ namespace sol {
|
|||
u_detail::usertype_storage_base& uts = *maybe_uts;
|
||||
uts.set(std::forward<Key>(key), std::forward<Value>(value));
|
||||
}
|
||||
else {
|
||||
base_t::set(std::forward<Key>(key), std::forward<Value>(value));
|
||||
}
|
||||
}
|
||||
|
||||
namespace stack {
|
||||
|
|
|
@ -366,7 +366,13 @@ namespace sol {
|
|||
}
|
||||
|
||||
template <typename Class, typename Key>
|
||||
usertype<Class> new_usertype(Key&& key, optional<no_construction> no_constructor = nullopt);
|
||||
usertype<Class> new_usertype(Key&& key);
|
||||
|
||||
template <typename Class, typename Key>
|
||||
usertype<Class> new_usertype(Key&& key, automagic_enrollments enrollment);
|
||||
|
||||
template <typename Class, typename Key, typename Arg, typename... Args, typename = std::enable_if_t<!std::is_same_v<meta::unqualified_t<Arg>, automagic_enrollments>>>
|
||||
usertype<Class> new_usertype(Key&& key, Arg&& arg, Args&&... args);
|
||||
|
||||
template <bool read_only = true, typename... Args>
|
||||
table new_enum(const string_view& name, Args&&... args) {
|
||||
|
|
|
@ -550,13 +550,13 @@ namespace sol {
|
|||
using has_insert_after = meta::boolean<meta_detail::has_insert_after_test<T>::value>;
|
||||
|
||||
template <typename T>
|
||||
using has_size = meta::boolean<meta_detail::has_size_test<T>::value || meta_detail::has_size_test<const T>::value>;
|
||||
using has_size = meta::boolean<meta_detail::has_size_test<T>::value>;
|
||||
|
||||
template <typename T>
|
||||
struct is_associative : meta::all<has_key_type<T>, has_key_value_pair<T>, has_mapped_type<T>> {};
|
||||
using is_associative = meta::all<has_key_type<T>, has_key_value_pair<T>, has_mapped_type<T>>;
|
||||
|
||||
template <typename T>
|
||||
struct is_lookup : meta::all<has_key_type<T>, has_value_type<T>> {};
|
||||
using is_lookup = meta::all<has_key_type<T>, has_value_type<T>>;
|
||||
|
||||
template <typename T>
|
||||
struct is_matched_lookup : meta_detail::is_matched_lookup_impl<T, is_lookup<T>::value> {};
|
||||
|
|
|
@ -1043,11 +1043,17 @@ namespace sol {
|
|||
template <typename T>
|
||||
struct is_unique_usertype : std::integral_constant<bool, unique_usertype_traits<T>::value> {};
|
||||
|
||||
template <typename T>
|
||||
inline constexpr bool is_unique_usertype_v = is_unique_usertype<T>::value;
|
||||
|
||||
template <typename T>
|
||||
struct lua_type_of : detail::lua_type_of<T> {
|
||||
typedef int SOL_INTERNAL_UNSPECIALIZED_MARKER_;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
inline constexpr type lua_type_of_v = lua_type_of<T>::value;
|
||||
|
||||
template <typename T>
|
||||
struct lua_size : std::integral_constant<int, 1> {
|
||||
typedef int SOL_INTERNAL_UNSPECIALIZED_MARKER_;
|
||||
|
@ -1059,6 +1065,9 @@ namespace sol {
|
|||
template <typename... Args>
|
||||
struct lua_size<std::tuple<Args...>> : std::integral_constant<int, detail::accumulate<int, 0, lua_size, Args...>::value> {};
|
||||
|
||||
template <typename T>
|
||||
inline constexpr int lua_size_v = lua_size<T>::value;
|
||||
|
||||
namespace detail {
|
||||
template <typename...>
|
||||
struct void_ { typedef void type; };
|
||||
|
@ -1211,7 +1220,7 @@ namespace sol {
|
|||
using any_is_constructor = meta::any<is_constructor<meta::unqualified_t<Args>>...>;
|
||||
|
||||
template <typename... Args>
|
||||
using any_is_constructor_v = any_is_constructor<Args...>::value;
|
||||
inline constexpr bool any_is_constructor_v = any_is_constructor<Args...>::value;
|
||||
|
||||
template <typename T>
|
||||
struct is_destructor : std::false_type {};
|
||||
|
@ -1220,13 +1229,30 @@ namespace sol {
|
|||
struct is_destructor<destructor_wrapper<Fx>> : std::true_type {};
|
||||
|
||||
template <typename... Args>
|
||||
using has_destructor = meta::any<is_destructor<meta::unqualified_t<Args>>...>;
|
||||
using any_is_destructor = meta::any<is_destructor<meta::unqualified_t<Args>>...>;
|
||||
|
||||
template <typename... Args>
|
||||
inline constexpr bool any_is_destructor_v = any_is_destructor<Args...>::value;
|
||||
|
||||
struct add_destructor_tag {};
|
||||
struct check_destructor_tag {};
|
||||
struct verified_tag {
|
||||
} const verified {};
|
||||
} // namespace detail
|
||||
|
||||
struct automagic_enrollments {
|
||||
bool default_constructor = true;
|
||||
bool destructor = true;
|
||||
bool pairs_operator = true;
|
||||
bool to_string_operator = true;
|
||||
bool call_operator = true;
|
||||
bool less_than_operator = true;
|
||||
bool less_than_or_equal_to_operator = true;
|
||||
bool length_operator = true;
|
||||
bool equal_to_operator = true;
|
||||
};
|
||||
|
||||
|
||||
} // namespace sol
|
||||
|
||||
#endif // SOL_TYPES_HPP
|
||||
|
|
|
@ -42,6 +42,16 @@ namespace sol {
|
|||
using base_t::pop;
|
||||
using base_t::push;
|
||||
|
||||
template <std::size_t... I, typename... Args>
|
||||
void tuple_set(std::index_sequence<I...>, std::tuple<Args...>&& args) {
|
||||
using args_tuple = std::tuple<Args...>&&;
|
||||
optional<u_detail::usertype_storage<T>&> maybe_uts = u_detail::maybe_get_usertype_storage<T>(this->lua_state());
|
||||
if (maybe_uts) {
|
||||
u_detail::usertype_storage<T>& uts = *maybe_uts;
|
||||
detail::swallow{ 0, (uts.set(this->lua_state(), std::get<I * 2>(std::forward<args_tuple>(args)), std::get<I * 2 + 1>(std::forward<args_tuple>(args))), 0)... };
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Key, typename Value>
|
||||
void set(Key&& key, Value&& value) {
|
||||
optional<u_detail::usertype_storage<T>&> maybe_uts = u_detail::maybe_get_usertype_storage<T>(this->lua_state());
|
||||
|
|
|
@ -45,7 +45,7 @@ namespace sol {
|
|||
}
|
||||
|
||||
static int real_index_call(lua_State* L) {
|
||||
typedef detail::map_t<std::string, lua_CFunction> call_map;
|
||||
typedef detail::unordered_map<std::string, lua_CFunction> call_map;
|
||||
static const call_map calls{
|
||||
{ "at", &at_call },
|
||||
{ "get", &real_get_call },
|
||||
|
|
|
@ -66,78 +66,6 @@ namespace sol {
|
|||
named
|
||||
};
|
||||
|
||||
struct no_comp {
|
||||
template <typename A, typename B>
|
||||
bool operator()(A&&, B&&) const {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
inline int is_check(lua_State* L) {
|
||||
return stack::push(L, stack::check<T>(L, 1, &no_panic));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline int member_default_to_string(std::true_type, lua_State* L) {
|
||||
decltype(auto) ts = stack::get<T>(L, 1).to_string();
|
||||
return stack::push(L, std::forward<decltype(ts)>(ts));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline int member_default_to_string(std::false_type, lua_State* L) {
|
||||
return luaL_error(L, "cannot perform to_string on '%s': no 'to_string' overload in namespace, 'to_string' member function, or operator<<(ostream&, ...) present", detail::demangle<T>().data());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline int adl_default_to_string(std::true_type, lua_State* L) {
|
||||
using namespace std;
|
||||
decltype(auto) ts = to_string(stack::get<T>(L, 1));
|
||||
return stack::push(L, std::forward<decltype(ts)>(ts));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline int adl_default_to_string(std::false_type, lua_State* L) {
|
||||
return member_default_to_string<T>(meta::supports_to_string_member<T>(), L);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline int oss_default_to_string(std::true_type, lua_State* L) {
|
||||
std::ostringstream oss;
|
||||
oss << stack::unqualified_get<T>(L, 1);
|
||||
return stack::push(L, oss.str());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline int oss_default_to_string(std::false_type, lua_State* L) {
|
||||
return adl_default_to_string<T>(meta::supports_adl_to_string<T>(), L);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline int default_to_string(lua_State* L) {
|
||||
return oss_default_to_string<T>(meta::supports_ostream_op<T>(), L);
|
||||
}
|
||||
|
||||
template <typename T, typename Op>
|
||||
int comparsion_operator_wrap(lua_State* L) {
|
||||
auto maybel = stack::unqualified_check_get<T&>(L, 1);
|
||||
if (maybel) {
|
||||
auto mayber = stack::unqualified_check_get<T&>(L, 2);
|
||||
if (mayber) {
|
||||
auto& l = *maybel;
|
||||
auto& r = *mayber;
|
||||
if (std::is_same<no_comp, Op>::value) {
|
||||
return stack::push(L, detail::ptr(l) == detail::ptr(r));
|
||||
}
|
||||
else {
|
||||
Op op;
|
||||
return stack::push(L, (detail::ptr(l) == detail::ptr(r)) || op(detail::deref(l), detail::deref(r)));
|
||||
}
|
||||
}
|
||||
}
|
||||
return stack::push(L, false);
|
||||
}
|
||||
|
||||
inline auto make_string_view(string_view s) {
|
||||
return s;
|
||||
}
|
||||
|
@ -183,81 +111,6 @@ namespace sol {
|
|||
inline int is_indexer(call_construction) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
lua_CFunction make_destructor() {
|
||||
if constexpr (std::is_destructible_v<T>) {
|
||||
if constexpr (is_unique_usertype<T>::value) {
|
||||
return &detail::unique_destruct<T>;
|
||||
}
|
||||
else if constexpr (!std::is_pointer_v<T>) {
|
||||
return &detail::usertype_alloc_destruct<T>;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return &detail::cannot_destruct<T>;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T, typename IFx, typename Fx>
|
||||
void insert_default_registrations(IFx&& ifx, Fx&& fx) {
|
||||
if constexpr (is_automagical<T>::value) {
|
||||
if (fx(meta_function::less_than)) {
|
||||
if constexpr (meta::supports_op_less<T>::value) {
|
||||
lua_CFunction f = &comparsion_operator_wrap<T, std::less<>>;
|
||||
ifx(meta_function::less_than, f);
|
||||
}
|
||||
}
|
||||
if (fx(meta_function::less_than_or_equal_to)) {
|
||||
if constexpr (meta::supports_op_less_equal<T>::value) {
|
||||
lua_CFunction f = &comparsion_operator_wrap<T, std::less_equal<>>;
|
||||
ifx(meta_function::less_than_or_equal_to, f);
|
||||
}
|
||||
}
|
||||
if (fx(meta_function::equal_to)) {
|
||||
if constexpr (meta::supports_op_equal<T>::value) {
|
||||
lua_CFunction f = &comparsion_operator_wrap<T, std::equal_to<>>;
|
||||
ifx(meta_function::equal_to, f);
|
||||
}
|
||||
}
|
||||
if (fx(meta_function::pairs)) {
|
||||
ifx(meta_function::pairs, &usertype_container<as_container_t<T>>::pairs_call);
|
||||
}
|
||||
if (fx(meta_function::length)) {
|
||||
if constexpr (meta::has_size<T>::value) {
|
||||
#if defined(__clang__)
|
||||
ifx(meta_function::length, &c_call<decltype(&T::size), &T::size>);
|
||||
#else
|
||||
typedef decltype(std::declval<T>().size()) R;
|
||||
using sz_func = R (T::*)();
|
||||
ifx(meta_function::length, &c_call<decltype(static_cast<sz_func>(&T::size)), static_cast<sz_func>(&T::size)>);
|
||||
#endif
|
||||
}
|
||||
else if constexpr (meta::has_size<const T>::value) {
|
||||
#if defined(__clang__)
|
||||
ifx(meta_function::length, &c_call<decltype(&T::size), &T::size>);
|
||||
#else
|
||||
typedef decltype(std::declval<T>().size()) R;
|
||||
using sz_func = R (T::*)() const;
|
||||
lua_CFunction f = &c_call<decltype(static_cast<sz_func>(&T::size)), static_cast<sz_func>(&T::size)>;
|
||||
ifx(meta_function::length, f);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
if (fx(meta_function::to_string)) {
|
||||
if constexpr (is_to_stringable<T>::value) {
|
||||
lua_CFunction f = &detail::static_trampoline<&default_to_string<T>>;
|
||||
ifx(meta_function::to_string, f);
|
||||
}
|
||||
}
|
||||
if (fx(meta_function::call_function)) {
|
||||
if constexpr (meta::has_deducible_signature<T>::value) {
|
||||
lua_CFunction f = &c_call<decltype(&T::operator()), &T::operator()>;
|
||||
ifx(meta_function::call_function, f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace u_detail
|
||||
|
||||
namespace stack { namespace stack_detail {
|
||||
|
@ -274,15 +127,11 @@ namespace sol {
|
|||
|
||||
void operator()() const {
|
||||
if (luaL_newmetatable(L, key) == 1) {
|
||||
luaL_Reg l[64] {};
|
||||
detail::lua_reg_table l{};
|
||||
int index = 0;
|
||||
auto prop_fx = [](meta_function) { return true; };
|
||||
auto insert_fx = [&l, &index](meta_function mf, lua_CFunction f) {
|
||||
l[index] = luaL_Reg { to_string(mf).c_str(), f };
|
||||
++index;
|
||||
};
|
||||
u_detail::insert_default_registrations<P>(insert_fx, prop_fx);
|
||||
l[index] = luaL_Reg { to_string(meta_function::garbage_collect).c_str(), u_detail::make_destructor<P>() };
|
||||
detail::indexed_insert insert_fx(l, index);
|
||||
detail::insert_default_registrations<P>(insert_fx, detail::property_always_true);
|
||||
l[index] = luaL_Reg{ to_string(meta_function::garbage_collect).c_str(), detail::make_destructor<P>() };
|
||||
luaL_setfuncs(L, l, 0);
|
||||
|
||||
// __type table
|
||||
|
@ -290,7 +139,7 @@ namespace sol {
|
|||
const std::string& name = detail::demangle<T>();
|
||||
lua_pushlstring(L, name.c_str(), name.size());
|
||||
lua_setfield(L, -2, "name");
|
||||
lua_CFunction is_func = &u_detail::is_check<T>;
|
||||
lua_CFunction is_func = &detail::is_check<T>;
|
||||
lua_pushcclosure(L, is_func, 0);
|
||||
lua_setfield(L, -2, "is");
|
||||
lua_setfield(L, -2, to_string(meta_function::type).c_str());
|
||||
|
|
|
@ -158,7 +158,7 @@ namespace u_detail {
|
|||
reference named_index_table;
|
||||
reference type_table;
|
||||
reference gc_names_table;
|
||||
reference metametatable;
|
||||
reference named_metatable;
|
||||
std::bitset<64> properties;
|
||||
index_call_storage base_index;
|
||||
index_call_storage base_new_index;
|
||||
|
@ -166,7 +166,7 @@ namespace u_detail {
|
|||
bool is_using_new_index;
|
||||
|
||||
usertype_storage_base(lua_State* L)
|
||||
: storage(), string_keys(), auxiliary_keys(), value_index_table(), reference_index_table(), unique_index_table(), const_reference_index_table(), type_table(make_reference(L, create)), gc_names_table(make_reference(L, create)), metametatable(make_reference(L, create)), properties(), base_index(), base_new_index(), is_using_index(false), is_using_new_index(false) {
|
||||
: storage(), string_keys(), auxiliary_keys(), value_index_table(), reference_index_table(), unique_index_table(), const_reference_index_table(), type_table(make_reference(L, create)), gc_names_table(make_reference(L, create)), named_metatable(make_reference(L, create)), properties(), base_index(), base_new_index(), is_using_index(false), is_using_new_index(false) {
|
||||
base_index.binding_data = nullptr;
|
||||
base_index.index = index_target_fail;
|
||||
base_index.new_index = index_target_fail;
|
||||
|
@ -339,8 +339,8 @@ namespace u_detail {
|
|||
}
|
||||
else {
|
||||
if (submetatable_type == submetatable::named) {
|
||||
stack::set_field(L, metatable_key, metametatable, t.stack_index());
|
||||
stack_reference stack_metametatable(L, -metametatable.push());
|
||||
stack::set_field(L, metatable_key, named_metatable, t.stack_index());
|
||||
stack_reference stack_metametatable(L, -named_metatable.push());
|
||||
stack::set_field<false, true>(L, meta_function::index, make_closure(uts::meta_index_call, nullptr, make_light(*this), make_light(this_base), nullptr, toplevel_magic), stack_metametatable.stack_index());
|
||||
stack::set_field<false, true>(L, meta_function::new_index, make_closure(uts::meta_new_index_call, nullptr, make_light(*this), make_light(this_base), nullptr, toplevel_magic), stack_metametatable.stack_index());
|
||||
stack_metametatable.pop();
|
||||
|
@ -433,19 +433,19 @@ namespace u_detail {
|
|||
using KeyU = meta::unwrap_unqualified_t<Key>;
|
||||
using Binding = binding<KeyU, ValueU, T>;
|
||||
using is_var_bind = is_variable_binding<ValueU>;
|
||||
if constexpr (std::is_same_v<Key, call_construction>) {
|
||||
if constexpr (std::is_same_v<KeyU, call_construction>) {
|
||||
std::unique_ptr<Binding> p_binding = std::make_unique<Binding>(std::forward<Value>(value));
|
||||
Binding& b = *p_binding;
|
||||
this->storage.push_back(std::move(p_binding));
|
||||
|
||||
this->named_index_table.push();
|
||||
this->named_metatable.push();
|
||||
absolute_index metametatable_index(L, -1);
|
||||
stack::push(L, nullptr);
|
||||
stack::push(L, b.data());
|
||||
lua_CFunction target_func = &b.call<false, false>;
|
||||
lua_pushcclosure(L, target_func, 2);
|
||||
lua_setfield(L, metametatable_index, to_string(meta_function::call).c_str());
|
||||
this->named_index_table.pop();
|
||||
this->named_metatable.pop();
|
||||
}
|
||||
else if constexpr ((meta::is_string_constructible<KeyU>::value || std::is_same_v<KeyU, meta_function>)&&(!is_lua_reference_or_proxy<ValueU>::value && !is_lua_reference_or_proxy<KeyU>::value)) {
|
||||
std::unique_ptr<Binding> p_binding = std::make_unique<Binding>(std::forward<Value>(value));
|
||||
|
@ -553,7 +553,7 @@ namespace u_detail {
|
|||
int usertype_storage_metatabe_count = stack::push(L, new_table(0, 1));
|
||||
stack_table usertype_storage_metatable(L, -usertype_storage_metatabe_count);
|
||||
// set the destruction routine on the metatable
|
||||
stack::set_field(L, meta_function::garbage_collect, detail::user_alloc_destruct<T>, usertype_storage_metatable.stack_index());
|
||||
stack::set_field(L, meta_function::garbage_collect, detail::user_alloc_destruct<usertype_storage<T>>, usertype_storage_metatable.stack_index());
|
||||
// set the metatable on the usertype storage userdata
|
||||
stack::set_field(L, metatable_key, usertype_storage_metatable, usertype_storage_ref.stack_index());
|
||||
usertype_storage_metatable.pop();
|
||||
|
@ -638,7 +638,7 @@ namespace u_detail {
|
|||
}
|
||||
|
||||
template <typename T>
|
||||
inline int register_usertype(lua_State* L, optional<no_construction> no_default_constructor = nullopt) {
|
||||
inline int register_usertype(lua_State* L, automagic_enrollments enrollments = {}) {
|
||||
using u_traits = usertype_traits<T>;
|
||||
using u_const_traits = usertype_traits<const T>;
|
||||
using u_unique_traits = usertype_traits<detail::unique_usertype<T>>;
|
||||
|
@ -704,7 +704,7 @@ namespace u_detail {
|
|||
// STEP 4: add some useful information to the type table
|
||||
stack_reference stacked_type_table(L, -storage.type_table.push());
|
||||
stack::set_field(L, "name", detail::demangle<T>(), stacked_type_table.stack_index());
|
||||
stack::set_field(L, "is", &u_detail::is_check<T>, stacked_type_table.stack_index());
|
||||
stack::set_field(L, "is", &detail::is_check<T>, stacked_type_table.stack_index());
|
||||
stacked_type_table.pop();
|
||||
|
||||
// STEP 5: create and hook up metatable,
|
||||
|
@ -781,14 +781,12 @@ namespace u_detail {
|
|||
stack::set_field(L, detail::base_class_cast_key(), (void*)&detail::inheritance<T>::type_cast, t.stack_index());
|
||||
}
|
||||
|
||||
auto prop_fx = [&](meta_function mf) {
|
||||
return !storage.properties[static_cast<int>(mf)];
|
||||
};
|
||||
auto prop_fx = properties_enrollment_allowed(storage.properties, enrollments);
|
||||
auto insert_fx = [&](meta_function mf, lua_CFunction reg) {
|
||||
stack::set_field(L, mf, reg, t.stack_index());
|
||||
storage.properties[static_cast<int>(mf)] = true;
|
||||
};
|
||||
u_detail::insert_default_registrations<T>(insert_fx, prop_fx);
|
||||
detail::insert_default_registrations<T>(insert_fx, prop_fx);
|
||||
|
||||
// There are no variables, so serialize the fast function stuff
|
||||
// be sure to reset the index stuff to the non-fast version
|
||||
|
@ -800,8 +798,8 @@ namespace u_detail {
|
|||
stack::set_field(L, meta_function::gc_names, storage.gc_names_table, t.stack_index());
|
||||
|
||||
// fancy new_indexing when using the named table
|
||||
stack::set_field<false, true>(L, metatable_key, storage.metametatable, t.stack_index());
|
||||
stack_reference stack_metametatable(L, -storage.metametatable.push());
|
||||
stack::set_field<false, true>(L, metatable_key, storage.named_metatable, t.stack_index());
|
||||
stack_reference stack_metametatable(L, -storage.named_metatable.push());
|
||||
stack::set_field<false, true>(L, meta_function::index, make_closure(uts::meta_index_call, nullptr, make_light(storage), make_light(base_storage), nullptr, toplevel_magic), stack_metametatable.stack_index());
|
||||
stack::set_field<false, true>(L, meta_function::new_index, make_closure(uts::meta_new_index_call, nullptr, make_light(storage), make_light(base_storage), nullptr, toplevel_magic), stack_metametatable.stack_index());
|
||||
stack_metametatable.pop();
|
||||
|
@ -819,7 +817,7 @@ namespace u_detail {
|
|||
|
||||
// can only use set AFTER we initialize all the metatables
|
||||
if constexpr (std::is_default_constructible_v<T>) {
|
||||
if (no_default_constructor == nullopt) {
|
||||
if (enrollments.default_constructor) {
|
||||
storage.set(L, meta_function::construct, constructors<T()>());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1119,16 +1119,6 @@ TEST_CASE("containers/non_copyable", "make sure non-copyable types in containers
|
|||
|
||||
lua["v"] = std::vector<non_copyable>{};
|
||||
|
||||
auto pfr = lua.safe_script("t = test.new() t.b = v", sol::script_pass_on_error);
|
||||
REQUIRE_FALSE(pfr.valid());
|
||||
}
|
||||
SECTION("simple") {
|
||||
sol::state lua;
|
||||
lua.new_simple_usertype<test>("test",
|
||||
"b", sol::readonly(&test::b));
|
||||
|
||||
lua["v"] = std::vector<non_copyable>{};
|
||||
|
||||
auto pfr = lua.safe_script("t = test.new() t.b = v", sol::script_pass_on_error);
|
||||
REQUIRE_FALSE(pfr.valid());
|
||||
}
|
||||
|
|
|
@ -170,36 +170,6 @@ end
|
|||
sol::function f = lua.safe_script(R"(
|
||||
return function(e)
|
||||
end
|
||||
)");
|
||||
gc_entity* target = nullptr;
|
||||
{
|
||||
gc_entity e;
|
||||
target = &e;
|
||||
{
|
||||
f(e); // same with std::ref(e)!
|
||||
lua.collect_garbage(); // destroys e for some reason
|
||||
}
|
||||
{
|
||||
f(&e); // same with std::ref(e)!
|
||||
lua.collect_garbage(); // destroys e for some reason
|
||||
}
|
||||
{
|
||||
f(std::ref(e)); // same with std::ref(e)!
|
||||
lua.collect_garbage(); // destroys e for some reason
|
||||
}
|
||||
}
|
||||
REQUIRE(entities.size() == 1);
|
||||
REQUIRE(entities.back() == target);
|
||||
}
|
||||
SECTION("simple") {
|
||||
entities.clear();
|
||||
|
||||
sol::state lua;
|
||||
lua.open_libraries();
|
||||
lua.new_simple_usertype<gc_entity>("entity");
|
||||
sol::function f = lua.safe_script(R"(
|
||||
return function(e)
|
||||
end
|
||||
)");
|
||||
gc_entity* target = nullptr;
|
||||
{
|
||||
|
@ -443,27 +413,6 @@ TEST_CASE("gc/usertypes", "show that proper copies / destruction happens for use
|
|||
REQUIRE(created == 4);
|
||||
REQUIRE(destroyed == 4);
|
||||
}
|
||||
SECTION("simple") {
|
||||
created = 0;
|
||||
destroyed = 0;
|
||||
{
|
||||
sol::state lua;
|
||||
lua.new_simple_usertype<x>("x");
|
||||
x x1;
|
||||
x x2;
|
||||
lua.set("x1copy", x1, "x2copy", x2, "x1ref", std::ref(x1));
|
||||
x& x1copyref = lua["x1copy"];
|
||||
x& x2copyref = lua["x2copy"];
|
||||
x& x1ref = lua["x1ref"];
|
||||
REQUIRE(created == 4);
|
||||
REQUIRE(destroyed == 0);
|
||||
REQUIRE(std::addressof(x1) == std::addressof(x1ref));
|
||||
REQUIRE(std::addressof(x1copyref) != std::addressof(x1));
|
||||
REQUIRE(std::addressof(x2copyref) != std::addressof(x2));
|
||||
}
|
||||
REQUIRE(created == 4);
|
||||
REQUIRE(destroyed == 4);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("gc/double-deletion tests", "make sure usertypes are properly destructed and don't double-delete memory or segfault") {
|
||||
|
@ -492,21 +441,6 @@ TEST_CASE("gc/double-deletion tests", "make sure usertypes are properly destruct
|
|||
)", sol::script_pass_on_error);
|
||||
REQUIRE(result1.valid());
|
||||
|
||||
for (int i = 0; i < 1000; ++i) {
|
||||
lua["testCrash"]();
|
||||
}
|
||||
}
|
||||
SECTION("simple") {
|
||||
lua.new_simple_usertype<crash_class>("CrashClass",
|
||||
sol::call_constructor, sol::constructors<sol::types<>>());
|
||||
|
||||
auto result1 = lua.safe_script(R"(
|
||||
function testCrash()
|
||||
local x = CrashClass()
|
||||
end
|
||||
)", sol::script_pass_on_error);
|
||||
REQUIRE(result1.valid());
|
||||
|
||||
for (int i = 0; i < 1000; ++i) {
|
||||
lua["testCrash"]();
|
||||
}
|
||||
|
@ -554,34 +488,6 @@ TEST_CASE("gc/shared_ptr regression", "metatables should not screw over unique u
|
|||
REQUIRE(created == 1);
|
||||
REQUIRE(destroyed == 1);
|
||||
}
|
||||
SECTION("simple") {
|
||||
created = 0;
|
||||
destroyed = 0;
|
||||
{
|
||||
std::list<std::shared_ptr<test>> tests;
|
||||
sol::state lua;
|
||||
lua.open_libraries();
|
||||
|
||||
lua.new_simple_usertype<test>("test",
|
||||
"create", [&]() -> std::shared_ptr<test> {
|
||||
tests.push_back(std::make_shared<test>());
|
||||
return tests.back();
|
||||
});
|
||||
REQUIRE(created == 0);
|
||||
REQUIRE(destroyed == 0);
|
||||
auto result1 = lua.safe_script("x = test.create()", sol::script_pass_on_error);
|
||||
REQUIRE(result1.valid());
|
||||
REQUIRE(created == 1);
|
||||
REQUIRE(destroyed == 0);
|
||||
REQUIRE_FALSE(tests.empty());
|
||||
std::shared_ptr<test>& x = lua["x"];
|
||||
std::size_t xuse = x.use_count();
|
||||
std::size_t tuse = tests.back().use_count();
|
||||
REQUIRE(xuse == tuse);
|
||||
}
|
||||
REQUIRE(created == 1);
|
||||
REQUIRE(destroyed == 1);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("gc/double deleter guards", "usertype metatables internally must not rely on C++ state") {
|
||||
|
@ -603,24 +509,6 @@ TEST_CASE("gc/double deleter guards", "usertype metatables internally must not r
|
|||
};
|
||||
REQUIRE_NOTHROW(routine());
|
||||
}
|
||||
SECTION("simple") {
|
||||
struct sc_a {
|
||||
int xv;
|
||||
};
|
||||
struct sc_b {
|
||||
int yv;
|
||||
};
|
||||
auto routine = []() {
|
||||
sol::state lua;
|
||||
lua.new_simple_usertype<sc_a>("c_a", "x", &sc_a::xv);
|
||||
lua.new_simple_usertype<sc_b>("c_b", "y", &sc_b::yv);
|
||||
lua = sol::state();
|
||||
lua.new_simple_usertype<sc_a>("c_a", "x", &sc_a::xv);
|
||||
lua.new_simple_usertype<sc_b>("c_b", "y", &sc_b::yv);
|
||||
lua = sol::state();
|
||||
};
|
||||
REQUIRE_NOTHROW(routine());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("gc/alignment", "test that allocation is always on aligned boundaries, no matter the wrapper / type") {
|
||||
|
|
|
@ -27,6 +27,58 @@
|
|||
|
||||
#include <iostream>
|
||||
|
||||
class TestClass00 {
|
||||
public:
|
||||
int Thing() const {
|
||||
return 123;
|
||||
}
|
||||
};
|
||||
|
||||
class TestClass01 : public TestClass00 {
|
||||
public:
|
||||
TestClass01()
|
||||
: a(1) {
|
||||
}
|
||||
TestClass01(const TestClass00& other)
|
||||
: a(other.Thing()) {
|
||||
}
|
||||
|
||||
int a;
|
||||
};
|
||||
|
||||
class TestClass02 : public TestClass01 {
|
||||
public:
|
||||
TestClass02()
|
||||
: b(2) {
|
||||
}
|
||||
TestClass02(const TestClass01& other)
|
||||
: b(other.a) {
|
||||
}
|
||||
TestClass02(const TestClass00& other)
|
||||
: b(other.Thing()) {
|
||||
}
|
||||
|
||||
int b;
|
||||
};
|
||||
|
||||
class TestClass03 : public TestClass02 {
|
||||
public:
|
||||
TestClass03()
|
||||
: c(2) {
|
||||
}
|
||||
TestClass03(const TestClass02& other)
|
||||
: c(other.b) {
|
||||
}
|
||||
TestClass03(const TestClass01& other)
|
||||
: c(other.a) {
|
||||
}
|
||||
TestClass03(const TestClass00& other)
|
||||
: c(other.Thing()) {
|
||||
}
|
||||
|
||||
int c;
|
||||
};
|
||||
|
||||
TEST_CASE("inheritance/basic", "test that metatables are properly inherited") {
|
||||
struct A {
|
||||
int a = 5;
|
||||
|
@ -82,87 +134,28 @@ TEST_CASE("inheritance/basic", "test that metatables are properly inherited") {
|
|||
}
|
||||
|
||||
TEST_CASE("inheritance/multi base", "test that multiple bases all work and overloading for constructors works with them") {
|
||||
class TestClass00 {
|
||||
public:
|
||||
int Thing() const {
|
||||
return 123;
|
||||
}
|
||||
};
|
||||
|
||||
class TestClass01 : public TestClass00 {
|
||||
public:
|
||||
TestClass01()
|
||||
: a(1) {
|
||||
}
|
||||
TestClass01(const TestClass00& other)
|
||||
: a(other.Thing()) {
|
||||
}
|
||||
|
||||
int a;
|
||||
};
|
||||
|
||||
class TestClass02 : public TestClass01 {
|
||||
public:
|
||||
TestClass02()
|
||||
: b(2) {
|
||||
}
|
||||
TestClass02(const TestClass01& other)
|
||||
: b(other.a) {
|
||||
}
|
||||
TestClass02(const TestClass00& other)
|
||||
: b(other.Thing()) {
|
||||
}
|
||||
|
||||
int b;
|
||||
};
|
||||
|
||||
class TestClass03 : public TestClass02 {
|
||||
public:
|
||||
TestClass03()
|
||||
: c(2) {
|
||||
}
|
||||
TestClass03(const TestClass02& other)
|
||||
: c(other.b) {
|
||||
}
|
||||
TestClass03(const TestClass01& other)
|
||||
: c(other.a) {
|
||||
}
|
||||
TestClass03(const TestClass00& other)
|
||||
: c(other.Thing()) {
|
||||
}
|
||||
|
||||
int c;
|
||||
};
|
||||
|
||||
sol::state lua;
|
||||
|
||||
sol::usertype<TestClass00> s_TestUsertype00(
|
||||
sol::usertype<TestClass00> s_TestUsertype00 = lua.new_usertype<TestClass00>("TestClass00",
|
||||
sol::call_constructor, sol::constructors<sol::types<>>(),
|
||||
"Thing", &TestClass00::Thing);
|
||||
|
||||
lua.set_usertype("TestClass00", s_TestUsertype00);
|
||||
|
||||
sol::usertype<TestClass01> s_TestUsertype01(
|
||||
sol::usertype<TestClass01> s_TestUsertype01 = lua.new_usertype<TestClass01>("TestClass01",
|
||||
sol::call_constructor, sol::constructors<sol::types<>, sol::types<const TestClass00&>>(),
|
||||
sol::base_classes, sol::bases<TestClass00>(),
|
||||
"a", &TestClass01::a);
|
||||
|
||||
lua.set_usertype("TestClass01", s_TestUsertype01);
|
||||
|
||||
sol::usertype<TestClass02> s_TestUsertype02(
|
||||
sol::usertype<TestClass02> s_TestUsertype02 = lua.new_usertype<TestClass02>("TestClass02",
|
||||
sol::call_constructor, sol::constructors<sol::types<>, sol::types<const TestClass01&>, sol::types<const TestClass00&>>(),
|
||||
sol::base_classes, sol::bases<TestClass01, TestClass00>(),
|
||||
"b", &TestClass02::b);
|
||||
|
||||
lua.set_usertype("TestClass02", s_TestUsertype02);
|
||||
|
||||
sol::usertype<TestClass03> s_TestUsertype03(
|
||||
sol::usertype<TestClass03> s_TestUsertype03 = lua.new_usertype<TestClass03>("TestClass03",
|
||||
sol::call_constructor, sol::constructors<sol::types<>, sol::types<const TestClass02&>, sol::types<const TestClass01&>, sol::types<const TestClass00&>>(),
|
||||
sol::base_classes, sol::bases<TestClass02, TestClass01, TestClass00>(),
|
||||
"c", &TestClass03::c);
|
||||
|
||||
lua.set_usertype("TestClass03", s_TestUsertype03);
|
||||
|
||||
auto result1 = lua.safe_script(R"(
|
||||
tc0 = TestClass00()
|
||||
tc2 = TestClass02(tc0)
|
||||
|
@ -185,87 +178,28 @@ tc3 = TestClass03(tc1)
|
|||
}
|
||||
|
||||
TEST_CASE("inheritance/simple multi base", "test that multiple bases all work and overloading for constructors works with them") {
|
||||
class TestClass00 {
|
||||
public:
|
||||
int Thing() const {
|
||||
return 123;
|
||||
}
|
||||
};
|
||||
|
||||
class TestClass01 : public TestClass00 {
|
||||
public:
|
||||
TestClass01()
|
||||
: a(1) {
|
||||
}
|
||||
TestClass01(const TestClass00& other)
|
||||
: a(other.Thing()) {
|
||||
}
|
||||
|
||||
int a;
|
||||
};
|
||||
|
||||
class TestClass02 : public TestClass01 {
|
||||
public:
|
||||
TestClass02()
|
||||
: b(2) {
|
||||
}
|
||||
TestClass02(const TestClass01& other)
|
||||
: b(other.a) {
|
||||
}
|
||||
TestClass02(const TestClass00& other)
|
||||
: b(other.Thing()) {
|
||||
}
|
||||
|
||||
int b;
|
||||
};
|
||||
|
||||
class TestClass03 : public TestClass02 {
|
||||
public:
|
||||
TestClass03()
|
||||
: c(2) {
|
||||
}
|
||||
TestClass03(const TestClass02& other)
|
||||
: c(other.b) {
|
||||
}
|
||||
TestClass03(const TestClass01& other)
|
||||
: c(other.a) {
|
||||
}
|
||||
TestClass03(const TestClass00& other)
|
||||
: c(other.Thing()) {
|
||||
}
|
||||
|
||||
int c;
|
||||
};
|
||||
|
||||
sol::state lua;
|
||||
|
||||
sol::simple_usertype<TestClass00> s_TestUsertype00(lua,
|
||||
sol::usertype<TestClass00> s_TestUsertype00 = lua.new_usertype<TestClass00>("TestClass00",
|
||||
sol::call_constructor, sol::constructors<sol::types<>>(),
|
||||
"Thing", &TestClass00::Thing);
|
||||
|
||||
lua.set_usertype("TestClass00", s_TestUsertype00);
|
||||
|
||||
sol::simple_usertype<TestClass01> s_TestUsertype01(lua,
|
||||
sol::usertype<TestClass01> s_TestUsertype01 = lua.new_usertype<TestClass01>("TestClass01",
|
||||
sol::call_constructor, sol::constructors<sol::types<>, sol::types<const TestClass00&>>(),
|
||||
sol::base_classes, sol::bases<TestClass00>(),
|
||||
"a", &TestClass01::a);
|
||||
|
||||
lua.set_usertype("TestClass01", s_TestUsertype01);
|
||||
|
||||
sol::simple_usertype<TestClass02> s_TestUsertype02(lua,
|
||||
sol::usertype<TestClass02> s_TestUsertype02 = lua.new_usertype<TestClass02>("TestClass02",
|
||||
sol::call_constructor, sol::constructors<sol::types<>, sol::types<const TestClass01&>, sol::types<const TestClass00&>>(),
|
||||
sol::base_classes, sol::bases<TestClass01, TestClass00>(),
|
||||
"b", &TestClass02::b);
|
||||
|
||||
lua.set_usertype("TestClass02", s_TestUsertype02);
|
||||
|
||||
sol::simple_usertype<TestClass03> s_TestUsertype03(lua,
|
||||
sol::usertype<TestClass03> s_TestUsertype03 = lua.new_usertype<TestClass03>("TestClass03",
|
||||
sol::call_constructor, sol::constructors<sol::types<>, sol::types<const TestClass02&>, sol::types<const TestClass01&>, sol::types<const TestClass00&>>(),
|
||||
sol::base_classes, sol::bases<TestClass02, TestClass01, TestClass00>(),
|
||||
"c", &TestClass03::c);
|
||||
|
||||
lua.set_usertype("TestClass03", s_TestUsertype03);
|
||||
|
||||
auto result1 = lua.safe_script(R"(
|
||||
tc0 = TestClass00()
|
||||
tc2 = TestClass02(tc0)
|
||||
|
|
|
@ -120,53 +120,6 @@ TEST_CASE("operators/default", "test that generic equality operators and all sor
|
|||
lua.new_usertype<U>("U");
|
||||
lua.new_usertype<V>("V");
|
||||
|
||||
// Can only compare identity here
|
||||
{
|
||||
auto result1 = lua.safe_script("assert(t1 == t1)"
|
||||
"assert(t2 == t2)"
|
||||
"assert(t3 == t3)", sol::script_pass_on_error);
|
||||
REQUIRE(result1.valid());
|
||||
}
|
||||
{
|
||||
auto result1 = lua.safe_script("assert(t1 == t2)"
|
||||
"assert(not (t1 == t3))"
|
||||
"assert(not (t2 == t3))", sol::script_pass_on_error);
|
||||
REQUIRE(result1.valid());
|
||||
}
|
||||
// Object should compare equal to themselves
|
||||
// (and not invoke operator==; pointer test should be sufficient)
|
||||
{
|
||||
auto result1 = lua.safe_script("assert(u1 == u1)"
|
||||
"assert(u2 == u2)"
|
||||
"assert(u3 == u3)", sol::script_pass_on_error);
|
||||
REQUIRE(result1.valid());
|
||||
}
|
||||
{
|
||||
auto result1 = lua.safe_script("assert(not (u1 == u2))"
|
||||
"assert(u1 == u3)"
|
||||
"assert(not (u2 == u3))", sol::script_pass_on_error);
|
||||
REQUIRE(result1.valid());
|
||||
}
|
||||
// Object should compare equal to themselves
|
||||
// (and not invoke operator==; pointer test should be sufficient)
|
||||
{
|
||||
auto result1 = lua.safe_script("assert(v1 == v1)"
|
||||
"assert(v2 == v2)"
|
||||
"assert(v3 == v3)", sol::script_pass_on_error);
|
||||
REQUIRE(result1.valid());
|
||||
}
|
||||
{
|
||||
auto result1 = lua.safe_script("assert(not (v1 == v2))"
|
||||
"assert(v1 == v3)"
|
||||
"assert(not (v2 == v3))", sol::script_pass_on_error);
|
||||
REQUIRE(result1.valid());
|
||||
}
|
||||
}
|
||||
SECTION("simple") {
|
||||
lua.new_simple_usertype<T>("T");
|
||||
lua.new_simple_usertype<U>("U");
|
||||
lua.new_simple_usertype<V>("V");
|
||||
|
||||
// Can only compare identity here
|
||||
{
|
||||
auto result1 = lua.safe_script("assert(t1 == t1)"
|
||||
|
@ -240,15 +193,6 @@ TEST_CASE("operators/call", "test call operator generation") {
|
|||
REQUIRE(v == 11);
|
||||
}
|
||||
}
|
||||
SECTION("simple") {
|
||||
lua.new_simple_usertype<callable>("callable");
|
||||
{
|
||||
lua.safe_script("obj = callable.new()");
|
||||
lua.safe_script("v = obj(2, 'bark woof')");
|
||||
int v = lua["v"];
|
||||
REQUIRE(v == 11);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct stringable {
|
||||
|
@ -316,16 +260,6 @@ TEST_CASE("operators/stringable", "test std::ostream stringability") {
|
|||
REQUIRE(stringable::last_print_ptr == &obj);
|
||||
}
|
||||
}
|
||||
SECTION("simple") {
|
||||
lua.new_simple_usertype<stringable>("stringable");
|
||||
{
|
||||
auto result1 = lua.safe_script(R"(obj = stringable.new()
|
||||
print(obj))", sol::script_pass_on_error);
|
||||
REQUIRE(result1.valid());
|
||||
stringable& obj = lua["obj"];
|
||||
REQUIRE(stringable::last_print_ptr == &obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("operators/adl_stringable", "test adl to_string stringability") {
|
||||
|
@ -349,15 +283,6 @@ TEST_CASE("operators/adl_stringable", "test adl to_string stringability") {
|
|||
REQUIRE(adl_stringable::last_print_ptr == &obj);
|
||||
}
|
||||
}
|
||||
SECTION("simple") {
|
||||
lua.new_simple_usertype<adl_stringable>("stringable");
|
||||
{
|
||||
lua.safe_script("obj = stringable.new()");
|
||||
lua.safe_script("print(obj)");
|
||||
adl_stringable& obj = lua["obj"];
|
||||
REQUIRE(adl_stringable::last_print_ptr == &obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("operators/inside::adl_stringable2", "test adl to_string stringability from inside a namespace") {
|
||||
|
@ -381,15 +306,6 @@ TEST_CASE("operators/inside::adl_stringable2", "test adl to_string stringability
|
|||
REQUIRE(inside::adl_stringable2::last_print_ptr == &obj);
|
||||
}
|
||||
}
|
||||
SECTION("simple") {
|
||||
lua.new_simple_usertype<inside::adl_stringable2>("stringable");
|
||||
{
|
||||
lua.safe_script("obj = stringable.new()");
|
||||
lua.safe_script("print(obj)");
|
||||
inside::adl_stringable2& obj = lua["obj"];
|
||||
REQUIRE(inside::adl_stringable2::last_print_ptr == &obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("operators/member_stringable", "test member to_string stringability") {
|
||||
|
@ -413,15 +329,6 @@ TEST_CASE("operators/member_stringable", "test member to_string stringability")
|
|||
REQUIRE(member_stringable::last_print_ptr == &obj);
|
||||
}
|
||||
}
|
||||
SECTION("simple") {
|
||||
lua.new_simple_usertype<member_stringable>("stringable");
|
||||
{
|
||||
lua.safe_script("obj = stringable.new()");
|
||||
lua.safe_script("print(obj)");
|
||||
member_stringable& obj = lua["obj"];
|
||||
REQUIRE(member_stringable::last_print_ptr == &obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("operators/container-like", "test that generic begin/end and iterator are automatically bound") {
|
||||
|
@ -506,13 +413,4 @@ TEST_CASE("operators/length", "test that size is automatically bound to the leng
|
|||
REQUIRE(s == 6);
|
||||
}
|
||||
}
|
||||
SECTION("simple") {
|
||||
lua.new_simple_usertype<sizable>("sizable");
|
||||
{
|
||||
lua.safe_script("obj = sizable.new()");
|
||||
lua.safe_script("s = #obj");
|
||||
std::size_t s = lua["s"];
|
||||
REQUIRE(s == 6);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -317,8 +317,7 @@ struct alignas(16) weird_aligned_wrapper {
|
|||
TEST_CASE("usertype/usertype", "Show that we can create classes from usertype and use them") {
|
||||
sol::state lua;
|
||||
|
||||
sol::usertype<fuser> lc{ "add", &fuser::add, "add2", &fuser::add2 };
|
||||
lua.set_usertype(lc);
|
||||
sol::usertype<fuser> lc = lua.new_usertype<fuser>("fuser", "add", &fuser::add, "add2", &fuser::add2);
|
||||
|
||||
lua.safe_script(
|
||||
"a = fuser:new()\n"
|
||||
|
@ -346,8 +345,10 @@ TEST_CASE("usertype/usertype-constructors", "Show that we can create classes fro
|
|||
sol::state lua;
|
||||
|
||||
sol::constructors<sol::types<>, sol::types<int>, sol::types<int, int>> con;
|
||||
sol::usertype<crapola::fuser> lc(con, "add", &crapola::fuser::add, "add2", &crapola::fuser::add2);
|
||||
lua.set_usertype(lc);
|
||||
sol::usertype<crapola::fuser> lc = lua.new_usertype<crapola::fuser>("fuser",
|
||||
con,
|
||||
"add", &crapola::fuser::add,
|
||||
"add2", &crapola::fuser::add2);
|
||||
|
||||
lua.safe_script(
|
||||
"a = fuser.new(2)\n"
|
||||
|
@ -414,9 +415,7 @@ TEST_CASE("usertype/usertype-utility-derived", "usertype classes must play nice
|
|||
sol::state lua;
|
||||
lua.open_libraries(sol::lib::base);
|
||||
sol::constructors<sol::types<int>> basector;
|
||||
sol::usertype<Base> baseusertype(basector, "get_num", &Base::get_num);
|
||||
|
||||
lua.set_usertype(baseusertype);
|
||||
sol::usertype<Base> baseusertype = lua.new_usertype<Base>("Base", basector, "get_num", &Base::get_num);
|
||||
|
||||
lua.safe_script("base = Base.new(5)");
|
||||
{
|
||||
|
@ -425,12 +424,10 @@ TEST_CASE("usertype/usertype-utility-derived", "usertype classes must play nice
|
|||
}
|
||||
|
||||
sol::constructors<sol::types<int>> derivedctor;
|
||||
sol::usertype<Derived> derivedusertype(derivedctor,
|
||||
sol::usertype<Derived> derivedusertype = lua.new_usertype<Derived>("Derived", derivedctor,
|
||||
"get_num_10", &Derived::get_num_10,
|
||||
"get_num", &Derived::get_num);
|
||||
|
||||
lua.set_usertype(derivedusertype);
|
||||
|
||||
lua.safe_script("derived = Derived.new(7)");
|
||||
lua.safe_script(
|
||||
"dgn = derived:get_num()\n"
|
||||
|
@ -532,8 +529,7 @@ TEST_CASE("usertype/issue-number-thirty-five", "using value types created from l
|
|||
lua.open_libraries(sol::lib::base);
|
||||
|
||||
sol::constructors<sol::types<float, float, float>> ctor;
|
||||
sol::usertype<Vec> udata(ctor, "normalized", &Vec::normalized, "length", &Vec::length);
|
||||
lua.set_usertype(udata);
|
||||
sol::usertype<Vec> udata = lua.new_usertype<Vec>("Vec", ctor, "normalized", &Vec::normalized, "length", &Vec::length);
|
||||
|
||||
{
|
||||
auto result = lua.safe_script(
|
||||
|
@ -555,11 +551,11 @@ TEST_CASE("usertype/lua-stored-usertype", "ensure usertype values can be stored
|
|||
|
||||
{
|
||||
sol::constructors<sol::types<float, float, float>> ctor;
|
||||
sol::usertype<Vec> udata(ctor,
|
||||
sol::usertype<Vec> udata = lua.new_usertype<Vec>("Vec",
|
||||
ctor,
|
||||
"normalized", &Vec::normalized,
|
||||
"length", &Vec::length);
|
||||
|
||||
lua.set_usertype(udata);
|
||||
// usertype dies, but still usable in lua!
|
||||
}
|
||||
|
||||
|
@ -583,13 +579,13 @@ TEST_CASE("usertype/member-variables", "allow table-like accessors to behave as
|
|||
sol::state lua;
|
||||
lua.open_libraries(sol::lib::base);
|
||||
sol::constructors<sol::types<float, float, float>> ctor;
|
||||
sol::usertype<Vec> udata(ctor,
|
||||
sol::usertype<Vec> udata = lua.new_usertype<Vec>("Vec",
|
||||
ctor,
|
||||
"x", &Vec::x,
|
||||
"y", &Vec::y,
|
||||
"z", &Vec::z,
|
||||
"normalized", &Vec::normalized,
|
||||
"length", &Vec::length);
|
||||
lua.set_usertype(udata);
|
||||
|
||||
REQUIRE_NOTHROW(lua.safe_script(
|
||||
"v = Vec.new(1, 2, 3)\n"
|
||||
|
@ -639,9 +635,8 @@ TEST_CASE("usertype/nonmember-functions", "let users set non-member functions th
|
|||
"gief", &giver::gief,
|
||||
"__tostring", [](const giver& t) {
|
||||
return std::to_string(t.a) + ": giving value";
|
||||
})
|
||||
.get<sol::table>("giver")
|
||||
.set_function("stuff", giver::stuff);
|
||||
});
|
||||
lua.get<sol::table>("giver").set_function("stuff", giver::stuff);
|
||||
|
||||
{
|
||||
auto result = lua.safe_script("giver.stuff()", sol::script_pass_on_error);
|
||||
|
|
|
@ -210,15 +210,15 @@ TEST_CASE("variadics/variadic_results", "returning a variable amount of argument
|
|||
}
|
||||
|
||||
TEST_CASE("variadics/fallback_constructor", "ensure constructor matching behaves properly in the presence of variadic fallbacks") {
|
||||
struct vec2 {
|
||||
struct vec2x {
|
||||
float x = 0, y = 0;
|
||||
};
|
||||
|
||||
sol::state lua;
|
||||
|
||||
lua.new_simple_usertype<vec2>("vec2",
|
||||
sol::call_constructor, sol::factories([]() { return vec2{}; }, [](vec2 const& v) -> vec2 { return v; }, [](sol::variadic_args va) {
|
||||
vec2 res{};
|
||||
lua.new_usertype<vec2x>("vec2x",
|
||||
sol::call_constructor, sol::factories([]() { return vec2x{}; }, [](vec2x const& v) -> vec2x { return v; }, [](sol::variadic_args va) {
|
||||
vec2x res{};
|
||||
if (va.size() == 1) {
|
||||
res.x = va[0].get<float>();
|
||||
res.y = va[0].get<float>();
|
||||
|
@ -233,16 +233,16 @@ TEST_CASE("variadics/fallback_constructor", "ensure constructor matching behaves
|
|||
return res; }));
|
||||
|
||||
REQUIRE_NOTHROW([&]() {
|
||||
lua.safe_script("v0 = vec2();");
|
||||
lua.safe_script("v1 = vec2(1);");
|
||||
lua.safe_script("v2 = vec2(1, 2);");
|
||||
lua.safe_script("v3 = vec2(v2)");
|
||||
lua.safe_script("v0 = vec2x();");
|
||||
lua.safe_script("v1 = vec2x(1);");
|
||||
lua.safe_script("v2 = vec2x(1, 2);");
|
||||
lua.safe_script("v3 = vec2x(v2)");
|
||||
}());
|
||||
|
||||
vec2& v0 = lua["v0"];
|
||||
vec2& v1 = lua["v1"];
|
||||
vec2& v2 = lua["v2"];
|
||||
vec2& v3 = lua["v3"];
|
||||
vec2x& v0 = lua["v0"];
|
||||
vec2x& v1 = lua["v1"];
|
||||
vec2x& v2 = lua["v2"];
|
||||
vec2x& v3 = lua["v3"];
|
||||
|
||||
REQUIRE(v0.x == 0);
|
||||
REQUIRE(v0.y == 0);
|
||||
|
|
Loading…
Reference in New Issue
Block a user