SUPER DUPER UPDATE WOO

This commit is contained in:
ThePhD 2019-02-14 02:40:57 -05:00
parent ffe77ccb3f
commit b938e42af6
No known key found for this signature in database
GPG Key ID: 1509DB1C0F702BFA
31 changed files with 2663 additions and 2354 deletions

View File

@ -85,7 +85,7 @@ function (MAKE_EXAMPLE example_source_file example_suffix target_sol)
else() else()
target_compile_options(${example_name} target_compile_options(${example_name}
PRIVATE -std=c++1z PRIVATE -std=c++1z
-Wall -Wpendatic -Werror -pedantic -pedantic-errors -Wall -Wpedantic -Werror -pedantic -pedantic-errors
-Wno-noexcept-type -Wno-noexcept-type
-Wno-unknown-warning -Wno-unknown-warning-option) -Wno-unknown-warning -Wno-unknown-warning-option)
endif() endif()

View File

@ -29,36 +29,27 @@ private:
int v_ = 50; int v_ = 50;
}; };
namespace sol { template <typename T, typename Handler>
namespace stack { inline bool sol_lua_interop_check(sol::types<T>, lua_State* L, int relindex, sol::type index_type, Handler&& handler, sol::stack::record& tracking) {
template <typename T> // just marking unused parameters for no compiler warnings
struct userdata_checker<extensible<T>> { (void)index_type;
template <typename Handler> (void)handler;
static bool check(lua_State* L, int relindex, type index_type, Handler&& handler, record& tracking) { tracking.use(1);
// just marking unused parameters for no compiler warnings int index = lua_absindex(L, relindex);
(void)index_type; T* corrected = luabridge::Userdata::get<T>(L, index, true);
(void)handler; return corrected != nullptr;
tracking.use(1); }
int index = lua_absindex(L, relindex);
T* corrected = luabridge::Userdata::get<T>(L, index, true); template <typename T>
return corrected != nullptr; inline std::pair<bool, T*> sol_lua_interop_get(sol::types<T> t, lua_State* L, int relindex, void* unadjusted_pointer, sol::stack::record& tracking) {
} (void)unadjusted_pointer;
}; int index = lua_absindex(L, relindex);
if (!sol_lua_interop_check(t, L, index, sol::type::userdata, sol::no_panic, tracking)) {
template <typename T> return { false, nullptr };
struct userdata_getter<extensible<T>> { }
static std::pair<bool, T*> get(lua_State* L, int relindex, void* unadjusted_pointer, record& tracking) { T* corrected = luabridge::Userdata::get<T>(L, index, true);
(void)unadjusted_pointer; return { true, corrected };
int index = lua_absindex(L, relindex);
if (!userdata_checker<extensible<T>>::check(L, index, type::userdata, no_panic, tracking)) {
return { false, nullptr };
}
T* corrected = luabridge::Userdata::get<T>(L, index, true);
return { true, corrected };
}
};
} }
} // namespace sol::stack
void register_sol_stuff(lua_State* L) { void register_sol_stuff(lua_State* L) {
// grab raw state and put into state_view // grab raw state and put into state_view

View File

@ -39,46 +39,37 @@ private:
int v_; int v_;
}; };
namespace sol { template <typename T, typename Handler>
namespace stack { inline bool sol_lua_interop_check(sol::types<T>, lua_State* L, int relindex, sol::type index_type, Handler&& handler, sol::stack::record& tracking) {
template <typename T> // just marking unused parameters for no compiler warnings
struct userdata_checker<extensible<T>> { (void)index_type;
template <typename Handler> (void)handler;
static bool check(lua_State* L, int relindex, type index_type, Handler&& handler, record& tracking) { // using 1 element
// just marking unused parameters for no compiler warnings tracking.use(1);
(void)index_type; int index = lua_absindex(L, relindex);
(void)handler; // use kaguya's own detail wrapper check to see if it's correct
// using 1 element bool is_correct_type = kaguya::detail::object_wrapper_type_check(L, index);
tracking.use(1); return is_correct_type;
int index = lua_absindex(L, relindex); }
// use kaguya's own detail wrapper check to see if it's correct
bool is_correct_type = kaguya::detail::object_wrapper_type_check(L, index); template <typename T>
return is_correct_type; inline std::pair<bool, T*> sol_lua_interop_get(sol::types<T>, lua_State* L, int relindex, void* unadjusted_pointer, sol::stack::record& tracking) {
} // you may not need to specialize this method every time:
}; // some libraries are compatible with sol2's layout
template <typename T> // kaguya's storage of data is incompatible with sol's
struct userdata_getter<extensible<T>> { // it stores the data directly in the pointer, not a pointer inside of the `void*`
static std::pair<bool, T*> get(lua_State* L, int relindex, void* unadjusted_pointer, record& tracking) { // therefore, leave the raw userdata pointer as-is,
// you may not need to specialize this method every time: // if it's of the right type
// some libraries are compatible with sol2's layout int index = lua_absindex(L, relindex);
if (!kaguya::detail::object_wrapper_type_check(L, index)) {
// kaguya's storage of data is incompatible with sol's return { false, nullptr };
// it stores the data directly in the pointer, not a pointer inside of the `void*` }
// therefore, leave the raw userdata pointer as-is, // using 1 element
// if it's of the right type tracking.use(1);
int index = lua_absindex(L, relindex); kaguya::ObjectWrapperBase* base = kaguya::object_wrapper(L, index);
if (!kaguya::detail::object_wrapper_type_check(L, index)) { return { true, static_cast<T*>(base->get()) };
return { false, nullptr };
}
// using 1 element
tracking.use(1);
kaguya::ObjectWrapperBase* base = kaguya::object_wrapper(L, index);
return { true, static_cast<T*>(base->get()) };
}
};
} }
} // namespace sol::stack
void register_sol_stuff(lua_State* L) { void register_sol_stuff(lua_State* L) {
// grab raw state and put into state_view // grab raw state and put into state_view

View File

@ -35,42 +35,33 @@ private:
int v_; int v_;
}; };
namespace sol { template <typename T, typename Handler>
namespace stack { inline bool sol_lua_interop_check(sol::types<T>, lua_State* L, int relindex, sol::type index_type, Handler&& handler, sol::stack::record& tracking) {
template <typename T> // just marking unused parameters for no compiler warnings
struct userdata_checker<extensible<T>> { (void)index_type;
template <typename Handler> (void)handler;
static bool check(lua_State* L, int relindex, type index_type, Handler&& handler, record& tracking) { // using 1 element
// just marking unused parameters for no compiler warnings tracking.use(1);
(void)index_type; int index = lua_absindex(L, relindex);
(void)handler; if (lua_getmetatable(L, index) == 1) {
// using 1 element luaL_getmetatable(L, luwra::internal::UserTypeReg<T>::name.c_str());
tracking.use(1); bool is_correct_type = lua_rawequal(L, -2, -1) == 1;
int index = lua_absindex(L, relindex); lua_pop(L, 2);
if (lua_getmetatable(L, index) == 1) { return is_correct_type;
luaL_getmetatable(L, luwra::internal::UserTypeReg<T>::name.c_str()); }
bool is_correct_type = lua_rawequal(L, -2, -1) == 1; return false;
lua_pop(L, 2); }
return is_correct_type;
} template <typename T>
return false; inline std::pair<bool, T*> sol_lua_interop_get(sol::types<T> t, lua_State* L, int relindex, void* unadjusted_pointer, sol::stack::record& tracking) {
} // you may not need to specialize this method every time:
}; // some libraries are compatible with sol2's layout
int index = lua_absindex(L, relindex);
template <typename T> if (!sol_lua_interop_check(t, L, index, sol::type::userdata, sol::no_panic, tracking)) {
struct userdata_getter<extensible<T>> { return { false, nullptr };
static std::pair<bool, T*> get(lua_State* L, int relindex, void* unadjusted_pointer, record& tracking) { }
// you may not need to specialize this method every time: return { true, static_cast<T*>(unadjusted_pointer) };
// some libraries are compatible with sol2's layout
int index = lua_absindex(L, relindex);
if (!userdata_checker<extensible<T>>::check(L, index, type::userdata, no_panic, tracking)) {
return { false, nullptr };
}
return { true, static_cast<T*>(unadjusted_pointer) };
}
};
} }
} // namespace sol::stack
void register_sol_stuff(lua_State* L) { void register_sol_stuff(lua_State* L) {
// grab raw state and put into state_view // grab raw state and put into state_view

View File

@ -15,24 +15,23 @@
// I don't know where else you're gonna find the reference, // I don't know where else you're gonna find the reference,
// http://usefulgamedev.weebly.com/tolua-example.html // http://usefulgamedev.weebly.com/tolua-example.html
namespace sol {
namespace stack { /* NOTE: there is no sol_lua_interop_get here,
template <typename T> because tolua types are -- thankfully -- memory-compatible
struct userdata_checker<extensible<T>> { in most cases with sol.
template <typename Handler> Please check other examples like kaguya or LuaBribe for an example
static bool check(lua_State* L, int relindex, type index_type, Handler&& handler, record& tracking) { of how to also write the getter for your type*/
tracking.use(1); template <typename T, typename Handler>
// just marking unused parameters for no compiler warnings inline bool sol_lua_interop_check(sol::types<T>, lua_State* L, int relindex, sol::type index_type, Handler&& handler, sol::stack::record& tracking) {
(void)index_type; tracking.use(1);
(void)handler; // just marking unused parameters for no compiler warnings
int index = lua_absindex(L, relindex); (void)index_type;
std::string name = sol::detail::short_demangle<T>(); (void)handler;
tolua_Error tolua_err; int index = lua_absindex(L, relindex);
return tolua_isusertype(L, index, name.c_str(), 0, &tolua_err); std::string name = sol::detail::short_demangle<T>();
} tolua_Error tolua_err;
}; return tolua_isusertype(L, index, name.c_str(), 0, &tolua_err);
} }
} // namespace sol::stack
void register_sol_stuff(lua_State* L) { void register_sol_stuff(lua_State* L) {
// grab raw state and put into state_view // grab raw state and put into state_view

View File

@ -49,7 +49,7 @@ namespace sol { namespace detail {
template <typename Arg, typename... Args, template <typename Arg, typename... Args,
typename = std::enable_if_t<!std::is_same_v<std::remove_reference_t<std::remove_cv_t<Arg>>, typename = std::enable_if_t<!std::is_same_v<std::remove_reference_t<std::remove_cv_t<Arg>>,
ebco> && !std::is_same_v<std::remove_reference_t<std::remove_cv_t<Arg>>, T>>> ebco> && !std::is_same_v<std::remove_reference_t<std::remove_cv_t<Arg>>, T>>>
ebco(Arg&& arg, Args&&... args) : T(std::forward<Arg>(arg), std::forward<Args>(args)...){}; ebco(Arg&& arg, Args&&... args) : T(std::forward<Arg>(arg), std::forward<Args>(args)...){}
T& value() { T& value() {
return value_; return value_;
@ -70,7 +70,7 @@ namespace sol { namespace detail {
template <typename Arg, typename... Args, template <typename Arg, typename... Args,
typename = std::enable_if_t<!std::is_same_v<std::remove_reference_t<std::remove_cv_t<Arg>>, typename = std::enable_if_t<!std::is_same_v<std::remove_reference_t<std::remove_cv_t<Arg>>,
ebco> && !std::is_same_v<std::remove_reference_t<std::remove_cv_t<Arg>>, T>>> ebco> && !std::is_same_v<std::remove_reference_t<std::remove_cv_t<Arg>>, T>>>
ebco(Arg&& arg, Args&&... args) : T(std::forward<Arg>(arg), std::forward<Args>(args)...){}; ebco(Arg&& arg, Args&&... args) : T(std::forward<Arg>(arg), std::forward<Args>(args)...){}
ebco& operator=(const ebco&) = default; ebco& operator=(const ebco&) = default;
ebco& operator=(ebco&&) = default; ebco& operator=(ebco&&) = default;

View File

@ -1149,20 +1149,26 @@ namespace sol {
/// \synopsis template <class U> optional(const optional<U> &rhs); /// \synopsis template <class U> optional(const optional<U> &rhs);
template <class U, detail::enable_from_other<T, U, const U&>* = nullptr, detail::enable_if_t<std::is_convertible<const U&, T>::value>* = nullptr> template <class U, detail::enable_from_other<T, U, const U&>* = nullptr, detail::enable_if_t<std::is_convertible<const U&, T>::value>* = nullptr>
optional(const optional<U>& rhs) { optional(const optional<U>& rhs) {
this->construct(*rhs); if (rhs.has_value()) {
this->construct(*rhs);
}
} }
/// \exclude /// \exclude
template <class U, detail::enable_from_other<T, U, const U&>* = nullptr, detail::enable_if_t<!std::is_convertible<const U&, T>::value>* = nullptr> template <class U, detail::enable_from_other<T, U, const U&>* = nullptr, detail::enable_if_t<!std::is_convertible<const U&, T>::value>* = nullptr>
explicit optional(const optional<U>& rhs) { explicit optional(const optional<U>& rhs) {
this->construct(*rhs); if (rhs.has_value()) {
this->construct(*rhs);
}
} }
/// Converting move constructor. /// Converting move constructor.
/// \synopsis template <class U> optional(optional<U> &&rhs); /// \synopsis template <class U> optional(optional<U> &&rhs);
template <class U, detail::enable_from_other<T, U, U&&>* = nullptr, detail::enable_if_t<std::is_convertible<U&&, T>::value>* = nullptr> template <class U, detail::enable_from_other<T, U, U&&>* = nullptr, detail::enable_if_t<std::is_convertible<U&&, T>::value>* = nullptr>
optional(optional<U>&& rhs) { optional(optional<U>&& rhs) {
this->construct(std::move(*rhs)); if (rhs.has_value()) {
this->construct(std::move(*rhs));
}
} }
/// \exclude /// \exclude

View File

@ -71,13 +71,21 @@ namespace sol { namespace stack {
} // namespace stack_detail } // namespace stack_detail
template <typename T, typename> template <typename T, typename>
struct userdata_checker { struct unqualified_interop_checker {
template <typename Handler> template <typename Handler>
static bool check(lua_State*, int, type, Handler&&, record&) { static bool check(lua_State*, int, type, Handler&&, record&) {
return false; return false;
} }
}; };
template <typename T, typename>
struct qualified_interop_checker {
template <typename Handler>
static bool check(lua_State* L, int index, type index_type, Handler&& handler, record& tracking) {
return stack_detail::unqualified_interop_check<T>(L, index, index_type, std::forward<Handler>(handler), tracking);
}
};
template <typename T, type expected, typename> template <typename T, type expected, typename>
struct unqualified_checker { struct unqualified_checker {
template <typename Handler> template <typename Handler>
@ -446,15 +454,13 @@ namespace sol { namespace stack {
template <typename Handler> template <typename Handler>
static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { static bool check(lua_State* L, int index, Handler&& handler, record& tracking) {
const type indextype = type_of(L, index); const type indextype = type_of(L, index);
return check(types<T>(), L, index, indextype, handler, tracking); return check(types<T>(), L, index, indextype, std::forward<Handler>(handler), tracking);
} }
template <typename U, typename Handler> template <typename U, typename Handler>
static bool check(types<U>, lua_State* L, int index, type indextype, Handler&& handler, record& tracking) { static bool check(types<U>, lua_State* L, int index, type indextype, Handler&& handler, record& tracking) {
#if defined(SOL_ENABLE_INTEROP) && SOL_ENABLE_INTEROP #if defined(SOL_ENABLE_INTEROP) && SOL_ENABLE_INTEROP
userdata_checker<extensible<T>> uc; if (stack_detail::interop_check<U>(L, index, indextype, handler, tracking)) {
(void)uc;
if (uc.check(L, index, indextype, handler, tracking)) {
return true; return true;
} }
#endif // interop extensibility #endif // interop extensibility
@ -463,8 +469,7 @@ namespace sol { namespace stack {
handler(L, index, type::userdata, indextype, "value is not a valid userdata"); handler(L, index, type::userdata, indextype, "value is not a valid userdata");
return false; return false;
} }
if (meta::any<std::is_same<T, lightuserdata_value>, std::is_same<T, userdata_value>, std::is_same<T, userdata>, std::is_same<T, lightuserdata>>:: if (meta::any<std::is_same<T, lightuserdata_value>, std::is_same<T, userdata_value>, std::is_same<T, userdata>, std::is_same<T, lightuserdata>>::value)
value)
return true; return true;
if (lua_getmetatable(L, index) == 0) { if (lua_getmetatable(L, index) == 0) {
return true; return true;

View File

@ -98,14 +98,13 @@ namespace sol {
} }
inline void* align_usertype_pointer(void* ptr) { inline void* align_usertype_pointer(void* ptr) {
typedef std::integral_constant<bool, using use_align = std::integral_constant<bool,
#if defined(SOL_NO_MEMORY_ALIGNMENT) && SOL_NO_MEMORY_ALIGNMENT #if defined(SOL_NO_MEMORY_ALIGNMENT) && SOL_NO_MEMORY_ALIGNMENT
false false
#else #else
(std::alignment_of<void*>::value > 1) (std::alignment_of<void*>::value > 1)
#endif #endif
> >;
use_align;
if (!use_align::value) { if (!use_align::value) {
return ptr; return ptr;
} }
@ -115,14 +114,13 @@ namespace sol {
template <bool pre_aligned = false, bool pre_shifted = false> template <bool pre_aligned = false, bool pre_shifted = false>
inline void* align_usertype_unique_destructor(void* ptr) { inline void* align_usertype_unique_destructor(void* ptr) {
typedef std::integral_constant<bool, using use_align = std::integral_constant<bool,
#if defined(SOL_NO_MEMORY_ALIGNMENT) && SOL_NO_MEMORY_ALIGNMENT #if defined(SOL_NO_MEMORY_ALIGNMENT) && SOL_NO_MEMORY_ALIGNMENT
false false
#else #else
(std::alignment_of<unique_destructor>::value > 1) (std::alignment_of<unique_destructor>::value > 1)
#endif #endif
> >;
use_align;
if (!pre_aligned) { if (!pre_aligned) {
ptr = align_usertype_pointer(ptr); ptr = align_usertype_pointer(ptr);
} }
@ -138,14 +136,13 @@ namespace sol {
template <bool pre_aligned = false, bool pre_shifted = false> template <bool pre_aligned = false, bool pre_shifted = false>
inline void* align_usertype_unique_tag(void* ptr) { inline void* align_usertype_unique_tag(void* ptr) {
typedef std::integral_constant<bool, using use_align = std::integral_constant<bool,
#if defined(SOL_NO_MEMORY_ALIGNMENT) && SOL_NO_MEMORY_ALIGNMENT #if defined(SOL_NO_MEMORY_ALIGNMENT) && SOL_NO_MEMORY_ALIGNMENT
false false
#else #else
(std::alignment_of<unique_tag>::value > 1) (std::alignment_of<unique_tag>::value > 1)
#endif #endif
> >;
use_align;
if (!pre_aligned) { if (!pre_aligned) {
ptr = align_usertype_unique_destructor(ptr); ptr = align_usertype_unique_destructor(ptr);
} }
@ -590,7 +587,9 @@ namespace sol {
template <typename T, typename = void> template <typename T, typename = void>
struct qualified_getter; struct qualified_getter;
template <typename T, typename = void> template <typename T, typename = void>
struct userdata_getter; struct qualified_interop_getter;
template <typename T, typename = void>
struct unqualified_interop_getter;
template <typename T, typename = void> template <typename T, typename = void>
struct popper; struct popper;
template <typename T, typename = void> template <typename T, typename = void>
@ -600,7 +599,9 @@ namespace sol {
template <typename T, type = lua_type_of<T>::value, typename = void> template <typename T, type = lua_type_of<T>::value, typename = void>
struct qualified_checker; struct qualified_checker;
template <typename T, typename = void> template <typename T, typename = void>
struct userdata_checker; struct qualified_interop_checker;
template <typename T, typename = void>
struct unqualified_interop_checker;
template <typename T, typename = void> template <typename T, typename = void>
struct unqualified_check_getter; struct unqualified_check_getter;
template <typename T, typename = void> template <typename T, typename = void>
@ -646,6 +647,19 @@ namespace sol {
static constexpr bool value = std::is_same_v<decltype(test<T>(nullptr)), meta::sfinae_yes_t>; static constexpr bool value = std::is_same_v<decltype(test<T>(nullptr)), meta::sfinae_yes_t>;
}; };
template <typename T>
struct is_adl_sol_lua_interop_get {
private:
template <typename C>
static meta::sfinae_yes_t test(
std::remove_reference_t<decltype(sol_lua_interop_get(types<C>(), static_cast<lua_State*>(nullptr), -1, static_cast<void*>(nullptr), std::declval<stack::record&>()))>*);
template <typename C>
static meta::sfinae_no_t test(...);
public:
static constexpr bool value = std::is_same_v<decltype(test<T>(nullptr)), meta::sfinae_yes_t>;
};
template <typename T> template <typename T>
struct is_adl_sol_lua_check { struct is_adl_sol_lua_check {
private: private:
@ -659,6 +673,19 @@ namespace sol {
static constexpr bool value = std::is_same_v<decltype(test<T>(nullptr)), meta::sfinae_yes_t>; static constexpr bool value = std::is_same_v<decltype(test<T>(nullptr)), meta::sfinae_yes_t>;
}; };
template <typename T>
struct is_adl_sol_lua_interop_check {
private:
template <typename C>
static meta::sfinae_yes_t test(std::remove_reference_t<decltype(
sol_lua_interop_check(types<C>(), static_cast<lua_State*>(nullptr), -1, type::none, no_panic, std::declval<stack::record&>()))>*);
template <typename C>
static meta::sfinae_no_t test(...);
public:
static constexpr bool value = std::is_same_v<decltype(test<T>(nullptr)), meta::sfinae_yes_t>;
};
template <typename T> template <typename T>
struct is_adl_sol_lua_check_get { struct is_adl_sol_lua_check_get {
private: private:
@ -700,9 +727,15 @@ namespace sol {
template <typename T> template <typename T>
inline constexpr bool is_adl_sol_lua_get_v = is_adl_sol_lua_get<T>::value; inline constexpr bool is_adl_sol_lua_get_v = is_adl_sol_lua_get<T>::value;
template <typename T>
inline constexpr bool is_adl_sol_lua_interop_get_v = is_adl_sol_lua_interop_get<T>::value;
template <typename T> template <typename T>
inline constexpr bool is_adl_sol_lua_check_v = is_adl_sol_lua_check<T>::value; inline constexpr bool is_adl_sol_lua_check_v = is_adl_sol_lua_check<T>::value;
template <typename T>
inline constexpr bool is_adl_sol_lua_interop_check_v = is_adl_sol_lua_interop_check<T>::value;
template <typename T> template <typename T>
inline constexpr bool is_adl_sol_lua_check_get_v = is_adl_sol_lua_check_get<T>::value; inline constexpr bool is_adl_sol_lua_check_get_v = is_adl_sol_lua_check_get<T>::value;
@ -792,6 +825,58 @@ namespace sol {
return g.get(L, index, tracking); return g.get(L, index, tracking);
} }
} }
template <typename T>
inline decltype(auto) unqualified_interop_get(lua_State* L, int index, void* unadjusted_pointer, record& tracking) {
using Tu = meta::unqualified_t<T>;
if constexpr (meta::meta_detail::is_adl_sol_lua_interop_get_v<Tu>) {
return sol_lua_interop_get(types<Tu>(), L, index, unadjusted_pointer, tracking);
}
else {
unqualified_interop_getter<Tu> g{};
(void)g;
return g.get(L, index, unadjusted_pointer, tracking);
}
}
template <typename T>
inline decltype(auto) interop_get(lua_State* L, int index, void* unadjusted_pointer, record& tracking) {
if constexpr (meta::meta_detail::is_adl_sol_lua_interop_get_v<T>) {
return sol_lua_interop_get(types<T>(), L, index, unadjusted_pointer, tracking);
}
else {
qualified_interop_getter<T> g{};
(void)g;
return g.get(L, index, unadjusted_pointer, tracking);
}
}
template <typename T, typename Handler>
bool unqualified_interop_check(lua_State* L, int index, type index_type, Handler&& handler, record& tracking) {
using Tu = meta::unqualified_t<T>;
if constexpr (meta::meta_detail::is_adl_sol_lua_interop_check_v<Tu>) {
return sol_lua_interop_check(types<Tu>(), L, index, index_type, std::forward<Handler>(handler), tracking);
}
else {
unqualified_interop_checker<Tu> c;
// VC++ has a bad warning here: shut it up
(void)c;
return c.check(L, index, index_type, std::forward<Handler>(handler), tracking);
}
}
template <typename T, typename Handler>
bool interop_check(lua_State* L, int index, type index_type, Handler&& handler, record& tracking) {
if constexpr (meta::meta_detail::is_adl_sol_lua_interop_check_v<T>) {
return sol_lua_interop_check(types<T>(), L, index, index_type, std::forward<Handler>(handler), tracking);
}
else {
qualified_interop_checker<T> c;
// VC++ has a bad warning here: shut it up
(void)c;
return c.check(L, index, index_type, std::forward<Handler>(handler), tracking);
}
}
} // namespace stack_detail } // namespace stack_detail
inline bool maybe_indexable(lua_State* L, int index = -1) { inline bool maybe_indexable(lua_State* L, int index = -1) {
@ -868,11 +953,10 @@ namespace sol {
template <typename T, typename Arg, typename... Args> template <typename T, typename Arg, typename... Args>
inline int push_reference(lua_State* L, Arg&& arg, Args&&... args) { inline int push_reference(lua_State* L, Arg&& arg, Args&&... args) {
typedef meta::all<std::is_lvalue_reference<T>, using use_reference_tag = meta::all<std::is_lvalue_reference<T>,
meta::neg<std::is_const<T>>, meta::neg<std::is_const<T>>,
meta::neg<is_lua_primitive<meta::unqualified_t<T>>>, meta::neg<is_lua_primitive<meta::unqualified_t<T>>>,
meta::neg<is_unique_usertype<meta::unqualified_t<T>>>> meta::neg<is_unique_usertype<meta::unqualified_t<T>>>>;
use_reference_tag;
using Tr = meta::conditional_t<use_reference_tag::value, detail::as_reference_tag, meta::unqualified_t<T>>; using Tr = meta::conditional_t<use_reference_tag::value, detail::as_reference_tag, meta::unqualified_t<T>>;
return stack::push<Tr>(L, std::forward<Arg>(arg), std::forward<Args>(args)...); return stack::push<Tr>(L, std::forward<Arg>(arg), std::forward<Args>(args)...);
} }
@ -913,6 +997,32 @@ namespace sol {
return pushcount; return pushcount;
} }
template <typename T, typename Handler>
bool unqualified_check(lua_State* L, int index, Handler&& handler, record& tracking) {
using Tu = meta::unqualified_t<T>;
if constexpr (meta::meta_detail::is_adl_sol_lua_check_v<Tu>) {
return sol_lua_check(types<Tu>(), L, index, std::forward<Handler>(handler), tracking);
}
else {
unqualified_checker<Tu> c;
// VC++ has a bad warning here: shut it up
(void)c;
return c.check(L, index, std::forward<Handler>(handler), tracking);
}
}
template <typename T, typename Handler>
bool unqualified_check(lua_State* L, int index, Handler&& handler) {
record tracking{};
return unqualified_check<T>(L, index, std::forward<Handler>(handler), tracking);
}
template <typename T>
bool unqualified_check(lua_State* L, int index = -lua_size<meta::unqualified_t<T>>::value) {
auto handler = no_panic;
return unqualified_check<T>(L, index, handler);
}
template <typename T, typename Handler> template <typename T, typename Handler>
bool check(lua_State* L, int index, Handler&& handler, record& tracking) { bool check(lua_State* L, int index, Handler&& handler, record& tracking) {
if constexpr (meta::meta_detail::is_adl_sol_lua_check_v<T>) { if constexpr (meta::meta_detail::is_adl_sol_lua_check_v<T>) {
@ -938,32 +1048,6 @@ namespace sol {
return check<T>(L, index, handler); return check<T>(L, index, handler);
} }
template <typename T, typename Handler>
bool unqualified_check(lua_State* L, int index, Handler&& handler, record& tracking) {
typedef meta::unqualified_t<T> Tu;
if constexpr (meta::meta_detail::is_adl_sol_lua_check_v<Tu>) {
return sol_lua_check(types<Tu>(), L, index, std::forward<Handler>(handler), tracking);
}
else {
unqualified_checker<Tu> c;
// VC++ has a bad warning here: shut it up
(void)c;
return c.check(L, index, std::forward<Handler>(handler), tracking);
}
}
template <typename T, typename Handler>
bool unqualified_check(lua_State* L, int index, Handler&& handler) {
record tracking{};
return unqualified_check<T>(L, index, std::forward<Handler>(handler), tracking);
}
template <typename T>
bool unqualified_check(lua_State* L, int index = -lua_size<meta::unqualified_t<T>>::value) {
auto handler = no_panic;
return unqualified_check<T>(L, index, handler);
}
template <typename T, typename Handler> template <typename T, typename Handler>
bool check_usertype(lua_State* L, int index, type index_type, Handler&& handler, record& tracking) { bool check_usertype(lua_State* L, int index, type index_type, Handler&& handler, record& tracking) {
using Tu = meta::unqualified_t<T>; using Tu = meta::unqualified_t<T>;
@ -1067,6 +1151,8 @@ namespace sol {
} }
}; };
} // namespace stack_detail } // namespace stack_detail
template <bool b, typename... Args, typename Handler> template <bool b, typename... Args, typename Handler>
@ -1159,7 +1245,6 @@ namespace sol {
return get<T>(L, index, tracking); return get<T>(L, index, tracking);
} }
template <typename T> template <typename T>
inline decltype(auto) get_usertype(lua_State* L, int index, record& tracking) { inline decltype(auto) get_usertype(lua_State* L, int index, record& tracking) {
using UT = meta::conditional_t<std::is_pointer<T>::value, detail::as_pointer_tag<std::remove_pointer_t<T>>, detail::as_value_tag<T>>; using UT = meta::conditional_t<std::is_pointer<T>::value, detail::as_pointer_tag<std::remove_pointer_t<T>>, detail::as_value_tag<T>>;
@ -1239,7 +1324,7 @@ namespace sol {
template <typename T, typename F> template <typename T, typename F>
inline void modify_unique_usertype_as(const stack_reference& obj, F&& f) { inline void modify_unique_usertype_as(const stack_reference& obj, F&& f) {
typedef unique_usertype_traits<T> u_traits; using u_traits = unique_usertype_traits<T>;
void* raw = lua_touserdata(obj.lua_state(), obj.stack_index()); void* raw = lua_touserdata(obj.lua_state(), obj.stack_index());
void* ptr_memory = detail::align_usertype_pointer(raw); void* ptr_memory = detail::align_usertype_pointer(raw);
void* uu_memory = detail::align_usertype_unique<T>(raw); void* uu_memory = detail::align_usertype_unique<T>(raw);
@ -1250,9 +1335,10 @@ namespace sol {
template <typename F> template <typename F>
inline void modify_unique_usertype(const stack_reference& obj, F&& f) { inline void modify_unique_usertype(const stack_reference& obj, F&& f) {
typedef meta::bind_traits<meta::unqualified_t<F>> bt; using bt = meta::bind_traits<meta::unqualified_t<F>>;
typedef typename bt::template arg_at<0> T; using T = typename bt::template arg_at<0>;
modify_unique_usertype_as<meta::unqualified_t<T>>(obj, std::forward<F>(f)); using Tu = meta::unqualified_t<T>;
modify_unique_usertype_as<Tu>(obj, std::forward<F>(f));
} }
} // namespace stack } // namespace stack

View File

@ -97,7 +97,7 @@ namespace sol { namespace stack {
template <typename BaseCh, typename S> template <typename BaseCh, typename S>
inline S get_into(lua_State* L, int index, record& tracking) { inline S get_into(lua_State* L, int index, record& tracking) {
typedef typename S::value_type Ch; using Ch = typename S::value_type;
tracking.use(1); tracking.use(1);
size_t len; size_t len;
auto utf8p = lua_tolstring(L, index, &len); auto utf8p = lua_tolstring(L, index, &len);
@ -114,16 +114,7 @@ namespace sol { namespace stack {
convert<BaseCh>(strb, stre, copy_units); convert<BaseCh>(strb, stre, copy_units);
return r; return r;
} }
} } // namespace stack_detail
template <typename U>
struct userdata_getter<U> {
typedef stack_detail::strip_extensible_t<U> T;
static std::pair<bool, T*> get(lua_State*, int, void*, record&) {
return { false, nullptr };
}
};
template <typename T, typename> template <typename T, typename>
struct unqualified_getter { struct unqualified_getter {
@ -139,6 +130,22 @@ namespace sol { namespace stack {
} }
}; };
template <typename U, typename>
struct unqualified_interop_getter {
using T = stack_detail::strip_extensible_t<U>;
static std::pair<bool, T*> get(lua_State*, int, void*, record&) {
return { false, nullptr };
}
};
template <typename T, typename>
struct qualified_interop_getter {
static decltype(auto) get(lua_State* L, int index, void* unadjusted_pointer, record& tracking) {
return stack_detail::unqualified_interop_get<T>(L, index, unadjusted_pointer, tracking);
}
};
template <typename T> template <typename T>
struct unqualified_getter<T, std::enable_if_t<std::is_floating_point<T>::value>> { struct unqualified_getter<T, std::enable_if_t<std::is_floating_point<T>::value>> {
static T get(lua_State* L, int index, record& tracking) { static T get(lua_State* L, int index, record& tracking) {
@ -796,9 +803,7 @@ namespace sol { namespace stack {
static T* get_no_lua_nil(lua_State* L, int index, record& tracking) { static T* get_no_lua_nil(lua_State* L, int index, record& tracking) {
void* memory = lua_touserdata(L, index); void* memory = lua_touserdata(L, index);
#if defined(SOL_ENABLE_INTEROP) && SOL_ENABLE_INTEROP #if defined(SOL_ENABLE_INTEROP) && SOL_ENABLE_INTEROP
userdata_getter<extensible<T>> ug; auto ugr = stack_detail::interop_get<T>(L, index, memory, tracking);
(void)ug;
auto ugr = ug.get(L, index, memory, tracking);
if (ugr.first) { if (ugr.first) {
return ugr.second; return ugr.second;
} }
@ -951,9 +956,9 @@ namespace sol { namespace stack {
return V(); return V();
} }
else { else {
using T = std::variant_alternative_t<0, V>; //using T = std::variant_alternative_t<0, V>;
std::abort(); std::abort();
/*return V(std::in_place_index<0>, stack::get<T>(L, index, tracking));*/ //return V(std::in_place_index<0>, stack::get<T>(L, index, tracking));
} }
} }

View File

@ -20,8 +20,8 @@
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// This file was generated with a script. // This file was generated with a script.
// Generated 2019-02-11 10:50:20.059748 UTC // Generated 2019-02-14 07:36:40.809154 UTC
// This header was generated with sol v2.20.6 (revision 4fd197d) // This header was generated with sol v2.20.6 (revision ffe77cc)
// https://github.com/ThePhD/sol2 // https://github.com/ThePhD/sol2
#ifndef SOL_SINGLE_INCLUDE_FORWARD_HPP #ifndef SOL_SINGLE_INCLUDE_FORWARD_HPP

View File

@ -20,8 +20,8 @@
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// This file was generated with a script. // This file was generated with a script.
// Generated 2019-02-11 10:50:18.478770 UTC // Generated 2019-02-14 07:36:40.566598 UTC
// This header was generated with sol v2.20.6 (revision 4fd197d) // This header was generated with sol v2.20.6 (revision ffe77cc)
// https://github.com/ThePhD/sol2 // https://github.com/ThePhD/sol2
#ifndef SOL_SINGLE_INCLUDE_HPP #ifndef SOL_SINGLE_INCLUDE_HPP
@ -4485,20 +4485,26 @@ namespace sol {
/// \synopsis template <class U> optional(const optional<U> &rhs); /// \synopsis template <class U> optional(const optional<U> &rhs);
template <class U, detail::enable_from_other<T, U, const U&>* = nullptr, detail::enable_if_t<std::is_convertible<const U&, T>::value>* = nullptr> template <class U, detail::enable_from_other<T, U, const U&>* = nullptr, detail::enable_if_t<std::is_convertible<const U&, T>::value>* = nullptr>
optional(const optional<U>& rhs) { optional(const optional<U>& rhs) {
this->construct(*rhs); if (rhs.has_value()) {
this->construct(*rhs);
}
} }
/// \exclude /// \exclude
template <class U, detail::enable_from_other<T, U, const U&>* = nullptr, detail::enable_if_t<!std::is_convertible<const U&, T>::value>* = nullptr> template <class U, detail::enable_from_other<T, U, const U&>* = nullptr, detail::enable_if_t<!std::is_convertible<const U&, T>::value>* = nullptr>
explicit optional(const optional<U>& rhs) { explicit optional(const optional<U>& rhs) {
this->construct(*rhs); if (rhs.has_value()) {
this->construct(*rhs);
}
} }
/// Converting move constructor. /// Converting move constructor.
/// \synopsis template <class U> optional(optional<U> &&rhs); /// \synopsis template <class U> optional(optional<U> &&rhs);
template <class U, detail::enable_from_other<T, U, U&&>* = nullptr, detail::enable_if_t<std::is_convertible<U&&, T>::value>* = nullptr> template <class U, detail::enable_from_other<T, U, U&&>* = nullptr, detail::enable_if_t<std::is_convertible<U&&, T>::value>* = nullptr>
optional(optional<U>&& rhs) { optional(optional<U>&& rhs) {
this->construct(std::move(*rhs)); if (rhs.has_value()) {
this->construct(std::move(*rhs));
}
} }
/// \exclude /// \exclude
@ -5847,7 +5853,7 @@ namespace sol { namespace detail {
template <typename Arg, typename... Args, template <typename Arg, typename... Args,
typename = std::enable_if_t<!std::is_same_v<std::remove_reference_t<std::remove_cv_t<Arg>>, typename = std::enable_if_t<!std::is_same_v<std::remove_reference_t<std::remove_cv_t<Arg>>,
ebco> && !std::is_same_v<std::remove_reference_t<std::remove_cv_t<Arg>>, T>>> ebco> && !std::is_same_v<std::remove_reference_t<std::remove_cv_t<Arg>>, T>>>
ebco(Arg&& arg, Args&&... args) : T(std::forward<Arg>(arg), std::forward<Args>(args)...){}; ebco(Arg&& arg, Args&&... args) : T(std::forward<Arg>(arg), std::forward<Args>(args)...){}
T& value() { T& value() {
return value_; return value_;
@ -5868,7 +5874,7 @@ namespace sol { namespace detail {
template <typename Arg, typename... Args, template <typename Arg, typename... Args,
typename = std::enable_if_t<!std::is_same_v<std::remove_reference_t<std::remove_cv_t<Arg>>, typename = std::enable_if_t<!std::is_same_v<std::remove_reference_t<std::remove_cv_t<Arg>>,
ebco> && !std::is_same_v<std::remove_reference_t<std::remove_cv_t<Arg>>, T>>> ebco> && !std::is_same_v<std::remove_reference_t<std::remove_cv_t<Arg>>, T>>>
ebco(Arg&& arg, Args&&... args) : T(std::forward<Arg>(arg), std::forward<Args>(args)...){}; ebco(Arg&& arg, Args&&... args) : T(std::forward<Arg>(arg), std::forward<Args>(args)...){}
ebco& operator=(const ebco&) = default; ebco& operator=(const ebco&) = default;
ebco& operator=(ebco&&) = default; ebco& operator=(ebco&&) = default;
@ -8751,14 +8757,13 @@ namespace sol {
} }
inline void* align_usertype_pointer(void* ptr) { inline void* align_usertype_pointer(void* ptr) {
typedef std::integral_constant<bool, using use_align = std::integral_constant<bool,
#if defined(SOL_NO_MEMORY_ALIGNMENT) && SOL_NO_MEMORY_ALIGNMENT #if defined(SOL_NO_MEMORY_ALIGNMENT) && SOL_NO_MEMORY_ALIGNMENT
false false
#else #else
(std::alignment_of<void*>::value > 1) (std::alignment_of<void*>::value > 1)
#endif #endif
> >;
use_align;
if (!use_align::value) { if (!use_align::value) {
return ptr; return ptr;
} }
@ -8768,14 +8773,13 @@ namespace sol {
template <bool pre_aligned = false, bool pre_shifted = false> template <bool pre_aligned = false, bool pre_shifted = false>
inline void* align_usertype_unique_destructor(void* ptr) { inline void* align_usertype_unique_destructor(void* ptr) {
typedef std::integral_constant<bool, using use_align = std::integral_constant<bool,
#if defined(SOL_NO_MEMORY_ALIGNMENT) && SOL_NO_MEMORY_ALIGNMENT #if defined(SOL_NO_MEMORY_ALIGNMENT) && SOL_NO_MEMORY_ALIGNMENT
false false
#else #else
(std::alignment_of<unique_destructor>::value > 1) (std::alignment_of<unique_destructor>::value > 1)
#endif #endif
> >;
use_align;
if (!pre_aligned) { if (!pre_aligned) {
ptr = align_usertype_pointer(ptr); ptr = align_usertype_pointer(ptr);
} }
@ -8791,14 +8795,13 @@ namespace sol {
template <bool pre_aligned = false, bool pre_shifted = false> template <bool pre_aligned = false, bool pre_shifted = false>
inline void* align_usertype_unique_tag(void* ptr) { inline void* align_usertype_unique_tag(void* ptr) {
typedef std::integral_constant<bool, using use_align = std::integral_constant<bool,
#if defined(SOL_NO_MEMORY_ALIGNMENT) && SOL_NO_MEMORY_ALIGNMENT #if defined(SOL_NO_MEMORY_ALIGNMENT) && SOL_NO_MEMORY_ALIGNMENT
false false
#else #else
(std::alignment_of<unique_tag>::value > 1) (std::alignment_of<unique_tag>::value > 1)
#endif #endif
> >;
use_align;
if (!pre_aligned) { if (!pre_aligned) {
ptr = align_usertype_unique_destructor(ptr); ptr = align_usertype_unique_destructor(ptr);
} }
@ -9243,7 +9246,9 @@ namespace sol {
template <typename T, typename = void> template <typename T, typename = void>
struct qualified_getter; struct qualified_getter;
template <typename T, typename = void> template <typename T, typename = void>
struct userdata_getter; struct qualified_interop_getter;
template <typename T, typename = void>
struct unqualified_interop_getter;
template <typename T, typename = void> template <typename T, typename = void>
struct popper; struct popper;
template <typename T, typename = void> template <typename T, typename = void>
@ -9253,7 +9258,9 @@ namespace sol {
template <typename T, type = lua_type_of<T>::value, typename = void> template <typename T, type = lua_type_of<T>::value, typename = void>
struct qualified_checker; struct qualified_checker;
template <typename T, typename = void> template <typename T, typename = void>
struct userdata_checker; struct qualified_interop_checker;
template <typename T, typename = void>
struct unqualified_interop_checker;
template <typename T, typename = void> template <typename T, typename = void>
struct unqualified_check_getter; struct unqualified_check_getter;
template <typename T, typename = void> template <typename T, typename = void>
@ -9299,6 +9306,19 @@ namespace sol {
static constexpr bool value = std::is_same_v<decltype(test<T>(nullptr)), meta::sfinae_yes_t>; static constexpr bool value = std::is_same_v<decltype(test<T>(nullptr)), meta::sfinae_yes_t>;
}; };
template <typename T>
struct is_adl_sol_lua_interop_get {
private:
template <typename C>
static meta::sfinae_yes_t test(
std::remove_reference_t<decltype(sol_lua_interop_get(types<C>(), static_cast<lua_State*>(nullptr), -1, static_cast<void*>(nullptr), std::declval<stack::record&>()))>*);
template <typename C>
static meta::sfinae_no_t test(...);
public:
static constexpr bool value = std::is_same_v<decltype(test<T>(nullptr)), meta::sfinae_yes_t>;
};
template <typename T> template <typename T>
struct is_adl_sol_lua_check { struct is_adl_sol_lua_check {
private: private:
@ -9312,6 +9332,19 @@ namespace sol {
static constexpr bool value = std::is_same_v<decltype(test<T>(nullptr)), meta::sfinae_yes_t>; static constexpr bool value = std::is_same_v<decltype(test<T>(nullptr)), meta::sfinae_yes_t>;
}; };
template <typename T>
struct is_adl_sol_lua_interop_check {
private:
template <typename C>
static meta::sfinae_yes_t test(std::remove_reference_t<decltype(
sol_lua_interop_check(types<C>(), static_cast<lua_State*>(nullptr), -1, type::none, no_panic, std::declval<stack::record&>()))>*);
template <typename C>
static meta::sfinae_no_t test(...);
public:
static constexpr bool value = std::is_same_v<decltype(test<T>(nullptr)), meta::sfinae_yes_t>;
};
template <typename T> template <typename T>
struct is_adl_sol_lua_check_get { struct is_adl_sol_lua_check_get {
private: private:
@ -9353,9 +9386,15 @@ namespace sol {
template <typename T> template <typename T>
inline constexpr bool is_adl_sol_lua_get_v = is_adl_sol_lua_get<T>::value; inline constexpr bool is_adl_sol_lua_get_v = is_adl_sol_lua_get<T>::value;
template <typename T>
inline constexpr bool is_adl_sol_lua_interop_get_v = is_adl_sol_lua_interop_get<T>::value;
template <typename T> template <typename T>
inline constexpr bool is_adl_sol_lua_check_v = is_adl_sol_lua_check<T>::value; inline constexpr bool is_adl_sol_lua_check_v = is_adl_sol_lua_check<T>::value;
template <typename T>
inline constexpr bool is_adl_sol_lua_interop_check_v = is_adl_sol_lua_interop_check<T>::value;
template <typename T> template <typename T>
inline constexpr bool is_adl_sol_lua_check_get_v = is_adl_sol_lua_check_get<T>::value; inline constexpr bool is_adl_sol_lua_check_get_v = is_adl_sol_lua_check_get<T>::value;
@ -9444,6 +9483,58 @@ namespace sol {
return g.get(L, index, tracking); return g.get(L, index, tracking);
} }
} }
template <typename T>
inline decltype(auto) unqualified_interop_get(lua_State* L, int index, void* unadjusted_pointer, record& tracking) {
using Tu = meta::unqualified_t<T>;
if constexpr (meta::meta_detail::is_adl_sol_lua_interop_get_v<Tu>) {
return sol_lua_interop_get(types<Tu>(), L, index, unadjusted_pointer, tracking);
}
else {
unqualified_interop_getter<Tu> g{};
(void)g;
return g.get(L, index, unadjusted_pointer, tracking);
}
}
template <typename T>
inline decltype(auto) interop_get(lua_State* L, int index, void* unadjusted_pointer, record& tracking) {
if constexpr (meta::meta_detail::is_adl_sol_lua_interop_get_v<T>) {
return sol_lua_interop_get(types<T>(), L, index, unadjusted_pointer, tracking);
}
else {
qualified_interop_getter<T> g{};
(void)g;
return g.get(L, index, unadjusted_pointer, tracking);
}
}
template <typename T, typename Handler>
bool unqualified_interop_check(lua_State* L, int index, type index_type, Handler&& handler, record& tracking) {
using Tu = meta::unqualified_t<T>;
if constexpr (meta::meta_detail::is_adl_sol_lua_interop_check_v<Tu>) {
return sol_lua_interop_check(types<Tu>(), L, index, index_type, std::forward<Handler>(handler), tracking);
}
else {
unqualified_interop_checker<Tu> c;
// VC++ has a bad warning here: shut it up
(void)c;
return c.check(L, index, index_type, std::forward<Handler>(handler), tracking);
}
}
template <typename T, typename Handler>
bool interop_check(lua_State* L, int index, type index_type, Handler&& handler, record& tracking) {
if constexpr (meta::meta_detail::is_adl_sol_lua_interop_check_v<T>) {
return sol_lua_interop_check(types<T>(), L, index, index_type, std::forward<Handler>(handler), tracking);
}
else {
qualified_interop_checker<T> c;
// VC++ has a bad warning here: shut it up
(void)c;
return c.check(L, index, index_type, std::forward<Handler>(handler), tracking);
}
}
} // namespace stack_detail } // namespace stack_detail
inline bool maybe_indexable(lua_State* L, int index = -1) { inline bool maybe_indexable(lua_State* L, int index = -1) {
@ -9520,11 +9611,10 @@ namespace sol {
template <typename T, typename Arg, typename... Args> template <typename T, typename Arg, typename... Args>
inline int push_reference(lua_State* L, Arg&& arg, Args&&... args) { inline int push_reference(lua_State* L, Arg&& arg, Args&&... args) {
typedef meta::all<std::is_lvalue_reference<T>, using use_reference_tag = meta::all<std::is_lvalue_reference<T>,
meta::neg<std::is_const<T>>, meta::neg<std::is_const<T>>,
meta::neg<is_lua_primitive<meta::unqualified_t<T>>>, meta::neg<is_lua_primitive<meta::unqualified_t<T>>>,
meta::neg<is_unique_usertype<meta::unqualified_t<T>>>> meta::neg<is_unique_usertype<meta::unqualified_t<T>>>>;
use_reference_tag;
using Tr = meta::conditional_t<use_reference_tag::value, detail::as_reference_tag, meta::unqualified_t<T>>; using Tr = meta::conditional_t<use_reference_tag::value, detail::as_reference_tag, meta::unqualified_t<T>>;
return stack::push<Tr>(L, std::forward<Arg>(arg), std::forward<Args>(args)...); return stack::push<Tr>(L, std::forward<Arg>(arg), std::forward<Args>(args)...);
} }
@ -9565,6 +9655,32 @@ namespace sol {
return pushcount; return pushcount;
} }
template <typename T, typename Handler>
bool unqualified_check(lua_State* L, int index, Handler&& handler, record& tracking) {
using Tu = meta::unqualified_t<T>;
if constexpr (meta::meta_detail::is_adl_sol_lua_check_v<Tu>) {
return sol_lua_check(types<Tu>(), L, index, std::forward<Handler>(handler), tracking);
}
else {
unqualified_checker<Tu> c;
// VC++ has a bad warning here: shut it up
(void)c;
return c.check(L, index, std::forward<Handler>(handler), tracking);
}
}
template <typename T, typename Handler>
bool unqualified_check(lua_State* L, int index, Handler&& handler) {
record tracking{};
return unqualified_check<T>(L, index, std::forward<Handler>(handler), tracking);
}
template <typename T>
bool unqualified_check(lua_State* L, int index = -lua_size<meta::unqualified_t<T>>::value) {
auto handler = no_panic;
return unqualified_check<T>(L, index, handler);
}
template <typename T, typename Handler> template <typename T, typename Handler>
bool check(lua_State* L, int index, Handler&& handler, record& tracking) { bool check(lua_State* L, int index, Handler&& handler, record& tracking) {
if constexpr (meta::meta_detail::is_adl_sol_lua_check_v<T>) { if constexpr (meta::meta_detail::is_adl_sol_lua_check_v<T>) {
@ -9590,32 +9706,6 @@ namespace sol {
return check<T>(L, index, handler); return check<T>(L, index, handler);
} }
template <typename T, typename Handler>
bool unqualified_check(lua_State* L, int index, Handler&& handler, record& tracking) {
typedef meta::unqualified_t<T> Tu;
if constexpr (meta::meta_detail::is_adl_sol_lua_check_v<Tu>) {
return sol_lua_check(types<Tu>(), L, index, std::forward<Handler>(handler), tracking);
}
else {
unqualified_checker<Tu> c;
// VC++ has a bad warning here: shut it up
(void)c;
return c.check(L, index, std::forward<Handler>(handler), tracking);
}
}
template <typename T, typename Handler>
bool unqualified_check(lua_State* L, int index, Handler&& handler) {
record tracking{};
return unqualified_check<T>(L, index, std::forward<Handler>(handler), tracking);
}
template <typename T>
bool unqualified_check(lua_State* L, int index = -lua_size<meta::unqualified_t<T>>::value) {
auto handler = no_panic;
return unqualified_check<T>(L, index, handler);
}
template <typename T, typename Handler> template <typename T, typename Handler>
bool check_usertype(lua_State* L, int index, type index_type, Handler&& handler, record& tracking) { bool check_usertype(lua_State* L, int index, type index_type, Handler&& handler, record& tracking) {
using Tu = meta::unqualified_t<T>; using Tu = meta::unqualified_t<T>;
@ -9890,7 +9980,7 @@ namespace sol {
template <typename T, typename F> template <typename T, typename F>
inline void modify_unique_usertype_as(const stack_reference& obj, F&& f) { inline void modify_unique_usertype_as(const stack_reference& obj, F&& f) {
typedef unique_usertype_traits<T> u_traits; using u_traits = unique_usertype_traits<T>;
void* raw = lua_touserdata(obj.lua_state(), obj.stack_index()); void* raw = lua_touserdata(obj.lua_state(), obj.stack_index());
void* ptr_memory = detail::align_usertype_pointer(raw); void* ptr_memory = detail::align_usertype_pointer(raw);
void* uu_memory = detail::align_usertype_unique<T>(raw); void* uu_memory = detail::align_usertype_unique<T>(raw);
@ -9901,9 +9991,10 @@ namespace sol {
template <typename F> template <typename F>
inline void modify_unique_usertype(const stack_reference& obj, F&& f) { inline void modify_unique_usertype(const stack_reference& obj, F&& f) {
typedef meta::bind_traits<meta::unqualified_t<F>> bt; using bt = meta::bind_traits<meta::unqualified_t<F>>;
typedef typename bt::template arg_at<0> T; using T = typename bt::template arg_at<0>;
modify_unique_usertype_as<meta::unqualified_t<T>>(obj, std::forward<F>(f)); using Tu = meta::unqualified_t<T>;
modify_unique_usertype_as<Tu>(obj, std::forward<F>(f));
} }
} // namespace stack } // namespace stack
@ -10098,13 +10189,21 @@ namespace sol { namespace stack {
} // namespace stack_detail } // namespace stack_detail
template <typename T, typename> template <typename T, typename>
struct userdata_checker { struct unqualified_interop_checker {
template <typename Handler> template <typename Handler>
static bool check(lua_State*, int, type, Handler&&, record&) { static bool check(lua_State*, int, type, Handler&&, record&) {
return false; return false;
} }
}; };
template <typename T, typename>
struct qualified_interop_checker {
template <typename Handler>
static bool check(lua_State* L, int index, type index_type, Handler&& handler, record& tracking) {
return stack_detail::unqualified_interop_check<T>(L, index, index_type, std::forward<Handler>(handler), tracking);
}
};
template <typename T, type expected, typename> template <typename T, type expected, typename>
struct unqualified_checker { struct unqualified_checker {
template <typename Handler> template <typename Handler>
@ -10473,15 +10572,13 @@ namespace sol { namespace stack {
template <typename Handler> template <typename Handler>
static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { static bool check(lua_State* L, int index, Handler&& handler, record& tracking) {
const type indextype = type_of(L, index); const type indextype = type_of(L, index);
return check(types<T>(), L, index, indextype, handler, tracking); return check(types<T>(), L, index, indextype, std::forward<Handler>(handler), tracking);
} }
template <typename U, typename Handler> template <typename U, typename Handler>
static bool check(types<U>, lua_State* L, int index, type indextype, Handler&& handler, record& tracking) { static bool check(types<U>, lua_State* L, int index, type indextype, Handler&& handler, record& tracking) {
#if defined(SOL_ENABLE_INTEROP) && SOL_ENABLE_INTEROP #if defined(SOL_ENABLE_INTEROP) && SOL_ENABLE_INTEROP
userdata_checker<extensible<T>> uc; if (stack_detail::interop_check<U>(L, index, indextype, handler, tracking)) {
(void)uc;
if (uc.check(L, index, indextype, handler, tracking)) {
return true; return true;
} }
#endif // interop extensibility #endif // interop extensibility
@ -10490,8 +10587,7 @@ namespace sol { namespace stack {
handler(L, index, type::userdata, indextype, "value is not a valid userdata"); handler(L, index, type::userdata, indextype, "value is not a valid userdata");
return false; return false;
} }
if (meta::any<std::is_same<T, lightuserdata_value>, std::is_same<T, userdata_value>, std::is_same<T, userdata>, std::is_same<T, lightuserdata>>:: if (meta::any<std::is_same<T, lightuserdata_value>, std::is_same<T, userdata_value>, std::is_same<T, userdata>, std::is_same<T, lightuserdata>>::value)
value)
return true; return true;
if (lua_getmetatable(L, index) == 0) { if (lua_getmetatable(L, index) == 0) {
return true; return true;
@ -11175,7 +11271,7 @@ namespace sol { namespace stack {
template <typename BaseCh, typename S> template <typename BaseCh, typename S>
inline S get_into(lua_State* L, int index, record& tracking) { inline S get_into(lua_State* L, int index, record& tracking) {
typedef typename S::value_type Ch; using Ch = typename S::value_type;
tracking.use(1); tracking.use(1);
size_t len; size_t len;
auto utf8p = lua_tolstring(L, index, &len); auto utf8p = lua_tolstring(L, index, &len);
@ -11192,16 +11288,7 @@ namespace sol { namespace stack {
convert<BaseCh>(strb, stre, copy_units); convert<BaseCh>(strb, stre, copy_units);
return r; return r;
} }
} } // namespace stack_detail
template <typename U>
struct userdata_getter<U> {
typedef stack_detail::strip_extensible_t<U> T;
static std::pair<bool, T*> get(lua_State*, int, void*, record&) {
return { false, nullptr };
}
};
template <typename T, typename> template <typename T, typename>
struct unqualified_getter { struct unqualified_getter {
@ -11217,6 +11304,22 @@ namespace sol { namespace stack {
} }
}; };
template <typename U, typename>
struct unqualified_interop_getter {
using T = stack_detail::strip_extensible_t<U>;
static std::pair<bool, T*> get(lua_State*, int, void*, record&) {
return { false, nullptr };
}
};
template <typename T, typename>
struct qualified_interop_getter {
static decltype(auto) get(lua_State* L, int index, void* unadjusted_pointer, record& tracking) {
return stack_detail::unqualified_interop_get<T>(L, index, unadjusted_pointer, tracking);
}
};
template <typename T> template <typename T>
struct unqualified_getter<T, std::enable_if_t<std::is_floating_point<T>::value>> { struct unqualified_getter<T, std::enable_if_t<std::is_floating_point<T>::value>> {
static T get(lua_State* L, int index, record& tracking) { static T get(lua_State* L, int index, record& tracking) {
@ -11874,9 +11977,7 @@ namespace sol { namespace stack {
static T* get_no_lua_nil(lua_State* L, int index, record& tracking) { static T* get_no_lua_nil(lua_State* L, int index, record& tracking) {
void* memory = lua_touserdata(L, index); void* memory = lua_touserdata(L, index);
#if defined(SOL_ENABLE_INTEROP) && SOL_ENABLE_INTEROP #if defined(SOL_ENABLE_INTEROP) && SOL_ENABLE_INTEROP
userdata_getter<extensible<T>> ug; auto ugr = stack_detail::interop_get<T>(L, index, memory, tracking);
(void)ug;
auto ugr = ug.get(L, index, memory, tracking);
if (ugr.first) { if (ugr.first) {
return ugr.second; return ugr.second;
} }
@ -12028,9 +12129,9 @@ namespace sol { namespace stack {
return V(); return V();
} }
else { else {
using T = std::variant_alternative_t<0, V>; //using T = std::variant_alternative_t<0, V>;
std::abort(); std::abort();
/*return V(std::in_place_index<0>, stack::get<T>(L, index, tracking));*/ //return V(std::in_place_index<0>, stack::get<T>(L, index, tracking));
} }
} }

View File

@ -48,7 +48,7 @@ function(CREATE_TEST test_target_name test_name target_sol)
else() else()
target_compile_options(${test_target_name} target_compile_options(${test_target_name}
PRIVATE -std=c++1z PRIVATE -std=c++1z
-Wall -Wpendatic -Werror -pedantic -pedantic-errors -Wall -Wpedantic -Werror -pedantic -pedantic-errors
-Wno-noexcept-type -pthread -Wno-noexcept-type -pthread
-Wno-unknown-warning -Wno-unknown-warning-option) -Wno-unknown-warning -Wno-unknown-warning-option)

View File

@ -26,6 +26,31 @@
#include <iostream> #include <iostream>
struct woof {
int var;
int func(int x) {
return var + x;
}
double func2(int x, int y) {
return var + x + y + 0.5;
}
std::string func2s(int x, std::string y) {
return y + " " + std::to_string(x);
}
};
struct thing {
int v = 100;
thing() {
}
thing(int x) : v(x) {
}
};
struct non_copyable { struct non_copyable {
non_copyable() = default; non_copyable() = default;
non_copyable(non_copyable&& other) noexcept = default; non_copyable(non_copyable&& other) noexcept = default;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,297 @@
// sol3
// The MIT License (MIT)
// Copyright (c) 2013-2018 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "sol_test.hpp"
#include <catch.hpp>
#include <iterator>
#include <numeric> // std::iota
struct my_object {
private:
std::vector<int> mdata;
public:
static const void* last_printed;
my_object(int sz) : mdata() {
mdata.resize(sz);
std::iota(mdata.begin(), mdata.end(), 1);
}
void operator()(std::size_t count, int value) {
for (; count > 0; --count) {
mdata.push_back(value);
}
}
public: // Container requirements, as per the C++ standard
using value_type = int;
using reference = value_type&;
using const_reference = const value_type&;
using iterator = decltype(mdata)::iterator;
using const_iterator = decltype(mdata)::const_iterator;
using difference_type = decltype(mdata)::difference_type;
using size_type = decltype(mdata)::size_type;
iterator begin() {
return iterator(mdata.begin());
}
iterator end() {
return iterator(mdata.end());
}
const_iterator begin() const {
return const_iterator(mdata.begin());
}
const_iterator end() const {
return const_iterator(mdata.end());
}
const_iterator cbegin() const {
return begin();
}
const_iterator cend() const {
return end();
}
size_type size() const noexcept {
return mdata.size();
}
size_type max_size() const noexcept {
return mdata.max_size();
}
void push_back(const value_type& v) {
mdata.push_back(v);
}
void insert(const_iterator where, const value_type& v) {
mdata.insert(where, v);
}
bool empty() const noexcept {
return mdata.empty();
}
bool operator==(const my_object& right) const {
return mdata == right.mdata;
}
bool operator!=(const my_object& right) const noexcept {
return mdata != right.mdata;
}
std::vector<int>& data() {
return mdata;
}
const std::vector<int>& data() const {
return mdata;
}
};
const void* my_object::last_printed = nullptr;
std::ostream& operator<<(std::ostream& ostr, const my_object& mo) {
my_object::last_printed = static_cast<const void*>(&mo);
ostr << "{ ";
const auto& v = mo.data();
if (v.empty()) {
ostr << "empty";
}
else {
ostr << v[0];
for (std::size_t i = 1; i < v.size(); ++i) {
ostr << ", " << v[i];
}
}
ostr << " }";
return ostr;
}
namespace sol {
template <>
struct is_container<my_object> : std::false_type {};
} // namespace sol
TEST_CASE("containers/as_container reference", "test that we can force a container to be treated like one despite is_container being false_type") {
sol::state lua;
lua.open_libraries(sol::lib::base);
lua.new_usertype<my_object>("my_object",
sol::constructors<my_object(int)>(),
sol::call_constructor,
sol::constructors<my_object(int)>(),
"size",
&my_object::size,
"iterable",
[](my_object& mo) { return sol::as_container(mo); });
#if SOL_LUA_VERSION > 501
auto result1 = lua.safe_script(R"(
mop = my_object.new(20)
for i, v in pairs(mop) do
assert(i == v)
end
print(mop)
)",
sol::script_pass_on_error);
REQUIRE(result1.valid());
REQUIRE_NOTHROW([&]() {
my_object& mo = lua["mop"];
REQUIRE((&mo == my_object::last_printed));
}());
#endif
auto result2 = lua.safe_script(R"(
mo = my_object(10)
c_mo = mo
c_iterable = mo:iterable()
)",
sol::script_pass_on_error);
REQUIRE(result2.valid());
REQUIRE_NOTHROW([&]() {
my_object& mo = lua["c_mo"];
my_object& mo_iterable = lua["c_iterable"];
REQUIRE(&mo == &mo_iterable);
REQUIRE(mo == mo_iterable);
}());
auto result3 = lua.safe_script(R"(
s1 = c_mo:size()
s1_len = #c_mo
s1_iterable = c_iterable:size()
s1_iterable_len = #c_iterable
)");
REQUIRE(result3.valid());
REQUIRE_NOTHROW([&]() {
std::size_t s1 = lua["s1"];
std::size_t s1_len = lua["s1_len"];
std::size_t s1_iterable = lua["s1_iterable"];
std::size_t s1_iterable_len = lua["s1_iterable_len"];
REQUIRE(s1 == 10);
REQUIRE(s1 == s1_len);
REQUIRE(s1 == s1_iterable_len);
REQUIRE(s1_iterable == s1_iterable_len);
}());
auto result4 = lua.safe_script(R"(
for i=1,#c_mo do
v_iterable = c_iterable[i]
assert(v_iterable == i)
end
)",
sol::script_pass_on_error);
REQUIRE(result4.valid());
auto result5 = lua.safe_script(R"(
mo(5, 20)
c_iterable:insert(1, 100)
v1 = c_iterable[1]
s2 = c_mo:size()
s2_len = #c_mo
s2_iterable = c_iterable:size()
s2_iterable_len = #c_iterable
print(mo)
)",
sol::script_pass_on_error);
REQUIRE(result5.valid());
int v1 = lua["v1"];
std::size_t s2 = lua["s2"];
std::size_t s2_len = lua["s2_len"];
std::size_t s2_iterable = lua["s2_iterable"];
std::size_t s2_iterable_len = lua["s2_iterable_len"];
REQUIRE(v1 == 100);
REQUIRE(s2 == 16);
REQUIRE(s2 == s2_len);
REQUIRE(s2 == s2_iterable_len);
REQUIRE(s2_iterable == s2_iterable_len);
my_object& mo = lua["mo"];
REQUIRE(&mo == my_object::last_printed);
}
TEST_CASE("containers/as_container", "test that we can force a container to be treated like one despite the trait being false using the proper marker") {
sol::state lua;
lua.open_libraries(sol::lib::base);
lua.set_function("f", [](int v) { return sol::as_container(my_object(v)); });
#if SOL_LUA_VERSION > 501
auto result1 = lua.safe_script(R"(
mop = f(20)
for i, v in pairs(mop) do
assert(i == v)
end
)");
REQUIRE(result1.valid());
#endif
auto result2 = lua.safe_script(R"(
mo = f(10)
c_iterable = mo
)");
REQUIRE(result2.valid());
{
my_object& mo = lua["mo"];
my_object& mo_iterable = lua["c_iterable"];
REQUIRE(&mo == &mo_iterable);
REQUIRE(mo == mo_iterable);
}
auto result3 = lua.safe_script(R"(
s1_iterable = c_iterable:size()
s1_iterable_len = #c_iterable
)");
REQUIRE(result3.valid());
{
std::size_t s1_iterable = lua["s1_iterable"];
std::size_t s1_iterable_len = lua["s1_iterable_len"];
REQUIRE(s1_iterable == 10);
REQUIRE(s1_iterable == s1_iterable_len);
}
auto result4 = lua.safe_script(R"(
for i=1,#c_iterable do
v_iterable = c_iterable[i]
assert(v_iterable == i)
end
)");
REQUIRE(result4.valid());
auto result5 = lua.safe_script(R"(
c_iterable:insert(1, 100)
v1 = c_iterable:get(1)
s2_iterable = c_iterable:size()
s2_iterable_len = #c_iterable
)");
REQUIRE(result5.valid());
{
int v1 = lua["v1"];
std::size_t s2_iterable = lua["s2_iterable"];
std::size_t s2_iterable_len = lua["s2_iterable_len"];
REQUIRE(v1 == 100);
REQUIRE(s2_iterable_len == 11);
REQUIRE(s2_iterable == s2_iterable_len);
}
}

View File

@ -0,0 +1,377 @@
// sol3
// The MIT License (MIT)
// Copyright (c) 2013-2018 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "sol_test.hpp"
#include <catch.hpp>
#include <set>
#include <map>
template <typename T>
void ordered_container_check(sol::state& lua, T& items) {
{
auto r1 = lua.safe_script(R"(
for i=1,#c do
v = c[(i + 10)]
assert(v == (i + 10))
end
)",
sol::script_pass_on_error);
REQUIRE(r1.valid());
}
{
auto r1 = lua.safe_script("i1 = c:find(11)", sol::script_pass_on_error);
REQUIRE(r1.valid());
auto r2 = lua.safe_script("i2 = c:find(14)", sol::script_pass_on_error);
REQUIRE(r2.valid());
}
{
auto r1 = lua.safe_script("io1 = c:index_of(12)", sol::script_pass_on_error);
REQUIRE(r1.valid());
auto r2 = lua.safe_script("io2 = c:index_of(13)", sol::script_pass_on_error);
REQUIRE(r2.valid());
}
{
auto r1 = lua.safe_script("v1 = c:get(11)", sol::script_pass_on_error);
REQUIRE(r1.valid());
auto r2 = lua.safe_script("v2 = c:get(13)", sol::script_pass_on_error);
REQUIRE(r2.valid());
}
{
auto r1 = lua.safe_script("c:set(20)", sol::script_pass_on_error);
REQUIRE(r1.valid());
auto r2 = lua.safe_script("c:set(16)", sol::script_pass_on_error);
REQUIRE(r2.valid());
}
{
auto r5 = lua.safe_script("s1 = #c", sol::script_pass_on_error);
REQUIRE(r5.valid());
auto r1 = lua.safe_script("c:erase(i1)", sol::script_pass_on_error);
REQUIRE(r1.valid());
auto r3 = lua.safe_script("s2 = #c", sol::script_pass_on_error);
REQUIRE(r3.valid());
auto r2 = lua.safe_script("c:erase(i2)", sol::script_pass_on_error);
REQUIRE(r2.valid());
auto r4 = lua.safe_script("s3 = #c", sol::script_pass_on_error);
REQUIRE(r4.valid());
}
{
auto r = lua.safe_script("c:add(17)", sol::script_pass_on_error);
REQUIRE(r.valid());
}
{
auto r = lua.safe_script("c[18] = true", sol::script_pass_on_error);
REQUIRE(r.valid());
}
{
auto r = lua.safe_script("v3 = c[20]", sol::script_pass_on_error);
REQUIRE(r.valid());
}
auto backit = items.begin();
std::size_t len = 0;
{
auto e = items.end();
auto last = backit;
for (; backit != e; ++backit, ++len) {
if (backit == e) {
break;
}
last = backit;
}
backit = last;
}
const int& first = *items.begin();
const int& last = *backit;
int i1 = lua["i1"];
int i2 = lua["i2"];
int io1 = lua["io1"];
int io2 = lua["io2"];
std::size_t s1 = lua["s1"];
std::size_t s2 = lua["s2"];
std::size_t s3 = lua["s3"];
int v1 = lua["v1"];
int v2 = lua["v2"];
int v3 = lua["v3"];
int values[] = { 12, 13, 15, 16, 17, 18, 20 };
{
std::size_t idx = 0;
for (const auto& i : items) {
const auto& v = values[idx];
REQUIRE((i == v));
++idx;
}
}
REQUIRE((s1 == 7));
REQUIRE((s2 == 6));
REQUIRE((s3 == 5));
REQUIRE((len == 7));
REQUIRE((first == 12));
REQUIRE((last == 20));
REQUIRE((i1 == 11));
REQUIRE((i2 == 14));
REQUIRE((io1 == 2));
REQUIRE((io2 == 3));
REQUIRE((v1 == 11));
REQUIRE((v2 == 13));
REQUIRE((v3 == 20));
}
template <typename T>
void associative_ordered_container_check(sol::state& lua, T& items) {
{
auto r1 = lua.safe_script(R"(
for i=1,#c do
v = c[(i + 10)]
assert(v == (i + 20))
end
)",
sol::script_pass_on_error);
REQUIRE(r1.valid());
}
{
auto r1 = lua.safe_script("i1 = c:find(11)", sol::script_pass_on_error);
REQUIRE(r1.valid());
auto r2 = lua.safe_script("i2 = c:find(14)", sol::script_pass_on_error);
REQUIRE(r2.valid());
}
{
auto r1 = lua.safe_script("io1 = c:index_of(12)", sol::script_pass_on_error);
REQUIRE(r1.valid());
auto r2 = lua.safe_script("io2 = c:index_of(13)", sol::script_pass_on_error);
REQUIRE(r2.valid());
}
{
auto r1 = lua.safe_script("v1 = c:get(11)", sol::script_pass_on_error);
REQUIRE(r1.valid());
auto r2 = lua.safe_script("v2 = c:get(13)", sol::script_pass_on_error);
REQUIRE(r2.valid());
}
{
auto r1 = lua.safe_script("c:set(20, 30)", sol::script_pass_on_error);
REQUIRE(r1.valid());
auto r2 = lua.safe_script("c:set(16, 26)", sol::script_pass_on_error);
REQUIRE(r2.valid());
auto r3 = lua.safe_script("c:set(12, 31)", sol::script_pass_on_error);
REQUIRE(r3.valid());
}
{
auto r5 = lua.safe_script("s1 = #c", sol::script_pass_on_error);
REQUIRE(r5.valid());
auto r1 = lua.safe_script("c:erase(11)", sol::script_pass_on_error);
REQUIRE(r1.valid());
auto r3 = lua.safe_script("s2 = #c", sol::script_pass_on_error);
REQUIRE(r3.valid());
auto r2 = lua.safe_script("c:erase(14)", sol::script_pass_on_error);
REQUIRE(r2.valid());
auto r4 = lua.safe_script("s3 = #c", sol::script_pass_on_error);
REQUIRE(r4.valid());
}
{
auto r = lua.safe_script("c:add(17, 27)", sol::script_pass_on_error);
REQUIRE(r.valid());
}
{
auto r = lua.safe_script("c[18] = 28", sol::script_pass_on_error);
REQUIRE(r.valid());
}
{
auto r = lua.safe_script("v3 = c[20]", sol::script_pass_on_error);
REQUIRE(r.valid());
}
auto backit = items.begin();
std::size_t len = 0;
{
auto e = items.end();
auto last = backit;
for (; backit != e; ++backit, ++len) {
if (backit == e) {
break;
}
last = backit;
}
backit = last;
}
const std::pair<const short, int>& first = *items.begin();
const std::pair<const short, int>& last = *backit;
int i1 = lua["i1"];
int i2 = lua["i2"];
int io1 = lua["io1"];
int io2 = lua["io2"];
std::size_t s1 = lua["s1"];
std::size_t s2 = lua["s2"];
std::size_t s3 = lua["s3"];
int v1 = lua["v1"];
int v2 = lua["v2"];
int v3 = lua["v3"];
std::pair<const short, int> values[]
= { { (short)12, 31 }, { (short)13, 23 }, { (short)15, 25 }, { (short)16, 26 }, { (short)17, 27 }, { (short)18, 28 }, { (short)20, 30 } };
{
std::size_t idx = 0;
for (const auto& i : items) {
const auto& v = values[idx];
REQUIRE((i == v));
++idx;
}
}
REQUIRE((s1 == 7));
REQUIRE((s2 == 6));
REQUIRE((s3 == 5));
REQUIRE((len == 7));
REQUIRE((first.first == 12));
REQUIRE((last.first == 20));
REQUIRE((first.second == 31));
REQUIRE((last.second == 30));
REQUIRE((i1 == 21));
REQUIRE((i2 == 24));
REQUIRE((io1 == 2));
REQUIRE((io2 == 3));
REQUIRE((v1 == 21));
REQUIRE((v2 == 23));
REQUIRE((v3 == 30));
}
template <typename T>
void associative_ordered_container_key_value_check(sol::state& lua, T& data, T& reflect) {
typedef typename T::key_type K;
typedef typename T::mapped_type V;
lua["collect"] = [&reflect](K k, V v) { reflect.insert({ k, v }); };
#if SOL_LUA_VERSION > 502
lua["val"] = data;
auto r = lua.safe_script(R"(
for k, v in pairs(val) do
collect(k, v)
end
print()
)",
sol::script_pass_on_error);
REQUIRE(r.valid());
#else
reflect = data;
#endif
REQUIRE((data == reflect));
}
template <typename T>
void ordered_lookup_container_check(sol::state& lua, T&) {
auto result0 = lua.safe_script("assert(c['a'] == 'a')", sol::script_default_on_error);
REQUIRE(result0.valid());
auto result1 = lua.safe_script("assert(c['b'] == 'b')", sol::script_default_on_error);
REQUIRE(result1.valid());
auto result2 = lua.safe_script("assert(c['c'] == 'c')", sol::script_default_on_error);
REQUIRE(result2.valid());
}
TEST_CASE("containers/ordered lookup containers", "check ordered container types") {
SECTION("set") {
sol::state lua;
lua.open_libraries(sol::lib::base);
std::set<int> items{ 11, 12, 13, 14, 15 };
lua["c"] = &items;
ordered_container_check(lua, items);
}
SECTION("set string") {
sol::state lua;
lua.open_libraries(sol::lib::base);
std::set<std::string> items({ "a", "b", "c" });
lua["c"] = &items;
ordered_lookup_container_check(lua, items);
}
SECTION("multiset") {
sol::state lua;
lua.open_libraries(sol::lib::base);
std::multiset<int> items{ 11, 12, 13, 14, 15 };
lua["c"] = &items;
ordered_container_check(lua, items);
}
SECTION("multiset string") {
sol::state lua;
lua.open_libraries(sol::lib::base);
std::multiset<std::string> items({ "a", "b", "c" });
lua["c"] = &items;
ordered_lookup_container_check(lua, items);
}
}
TEST_CASE("containers/associative ordered containers", "check associative (map) containers that are ordered fulfill basic functionality requirements") {
SECTION("map") {
sol::state lua;
lua.open_libraries(sol::lib::base);
std::map<short, int> items{ { (short)11, 21 }, { (short)12, 22 }, { (short)13, 23 }, { (short)14, 24 }, { (short)15, 25 } };
lua["c"] = &items;
associative_ordered_container_check(lua, items);
}
SECTION("map string") {
sol::state lua;
lua.open_libraries(sol::lib::base);
std::map<std::string, std::string> items{ { "a", "a" }, { "b", "b" }, { "c", "c" } };
lua["c"] = &items;
ordered_lookup_container_check(lua, items);
}
SECTION("multimap") {
sol::state lua;
lua.open_libraries(sol::lib::base);
std::multimap<short, int> items{ { (short)11, 21 }, { (short)12, 22 }, { (short)13, 23 }, { (short)14, 24 }, { (short)15, 25 } };
lua["c"] = &items;
associative_ordered_container_check(lua, items);
}
SECTION("multimap string") {
sol::state lua;
lua.open_libraries(sol::lib::base);
std::multimap<std::string, std::string> items{ { "a", "a" }, { "b", "b" }, { "c", "c" } };
lua["c"] = &items;
ordered_lookup_container_check(lua, items);
}
}
TEST_CASE("containers/associative ordered pairs", "check to make sure pairs works properly for key-value types") {
struct bar {};
std::unique_ptr<bar> ua(new bar()), ub(new bar()), uc(new bar());
bar* a = ua.get();
bar* b = ub.get();
bar* c = uc.get();
SECTION("map") {
sol::state lua;
lua.open_libraries(sol::lib::base);
std::map<std::string, bar*> data({ { "a", a }, { "b", b }, { "c", c } });
std::map<std::string, bar*> reflect;
associative_ordered_container_key_value_check(lua, data, reflect);
}
SECTION("multimap") {
sol::state lua;
lua.open_libraries(sol::lib::base);
std::multimap<std::string, bar*> data({ { "a", a }, { "b", b }, { "c", c } });
std::multimap<std::string, bar*> reflect;
associative_ordered_container_key_value_check(lua, data, reflect);
}
}

View File

@ -0,0 +1,269 @@
// sol3
// The MIT License (MIT)
// Copyright (c) 2013-2018 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "sol_test.hpp"
#include <catch.hpp>
#include <unordered_map>
#include <unordered_set>
template <typename T>
void unordered_container_check(sol::state& lua, T& items) {
{
auto r1 = lua.safe_script("i1 = c:find(11)", sol::script_pass_on_error);
REQUIRE(r1.valid());
auto r2 = lua.safe_script("i2 = c:find(14)", sol::script_pass_on_error);
REQUIRE(r2.valid());
}
{
auto r1 = lua.safe_script("io1 = c:index_of(12)", sol::script_pass_on_error);
REQUIRE_FALSE(r1.valid());
auto r2 = lua.safe_script("io2 = c:index_of(13)", sol::script_pass_on_error);
REQUIRE_FALSE(r2.valid());
}
{
auto r1 = lua.safe_script("v1 = c:get(11)", sol::script_pass_on_error);
REQUIRE(r1.valid());
auto r2 = lua.safe_script("v2 = c:get(13)", sol::script_pass_on_error);
REQUIRE(r2.valid());
}
{
auto r1 = lua.safe_script("c:set(20)", sol::script_pass_on_error);
REQUIRE(r1.valid());
auto r2 = lua.safe_script("c:set(16)", sol::script_pass_on_error);
REQUIRE(r2.valid());
}
{
auto r5 = lua.safe_script("s1 = #c", sol::script_pass_on_error);
REQUIRE(r5.valid());
auto r1 = lua.safe_script("c:erase(i1)", sol::script_pass_on_error);
REQUIRE(r1.valid());
auto r3 = lua.safe_script("s2 = #c", sol::script_pass_on_error);
REQUIRE(r3.valid());
auto r2 = lua.safe_script("c:erase(i2)", sol::script_pass_on_error);
REQUIRE(r2.valid());
auto r4 = lua.safe_script("s3 = #c", sol::script_pass_on_error);
REQUIRE(r4.valid());
}
{
auto r = lua.safe_script("c:add(17)", sol::script_pass_on_error);
REQUIRE(r.valid());
}
{
auto r = lua.safe_script("c[18] = true", sol::script_pass_on_error);
REQUIRE(r.valid());
}
{
auto r = lua.safe_script("v3 = c[20]", sol::script_pass_on_error);
REQUIRE(r.valid());
}
std::size_t len = items.size();
int i1 = lua["i1"];
int i2 = lua["i2"];
std::size_t s1 = lua["s1"];
std::size_t s2 = lua["s2"];
std::size_t s3 = lua["s3"];
int v1 = lua["v1"];
int v2 = lua["v2"];
int v3 = lua["v3"];
int values[] = { 12, 13, 15, 16, 17, 18, 20 };
{
for (const auto& v : values) {
auto it = items.find(v);
REQUIRE((it != items.cend()));
REQUIRE((*it == v));
}
}
REQUIRE((s1 == 7));
REQUIRE((s2 == 6));
REQUIRE((s3 == 5));
REQUIRE((len == 7));
REQUIRE((i1 == 11));
REQUIRE((i2 == 14));
REQUIRE((v1 == 11));
REQUIRE((v2 == 13));
REQUIRE((v3 == 20));
}
template <typename T>
void associative_unordered_container_check(sol::state& lua, T& items) {
{
auto r1 = lua.safe_script("i1 = c:find(11)", sol::script_pass_on_error);
REQUIRE(r1.valid());
auto r2 = lua.safe_script("i2 = c:find(14)", sol::script_pass_on_error);
REQUIRE(r2.valid());
}
{
auto r1 = lua.safe_script("io1 = c:index_of(12)", sol::script_pass_on_error);
REQUIRE_FALSE(r1.valid());
auto r2 = lua.safe_script("io2 = c:index_of(13)", sol::script_pass_on_error);
REQUIRE_FALSE(r2.valid());
}
{
auto r1 = lua.safe_script("v1 = c:get(11)", sol::script_pass_on_error);
REQUIRE(r1.valid());
auto r2 = lua.safe_script("v2 = c:get(13)", sol::script_pass_on_error);
REQUIRE(r2.valid());
}
{
auto r1 = lua.safe_script("c:set(20, 30)", sol::script_pass_on_error);
REQUIRE(r1.valid());
auto r2 = lua.safe_script("c:set(16, 26)", sol::script_pass_on_error);
REQUIRE(r2.valid());
auto r3 = lua.safe_script("c:set(12, 31)", sol::script_pass_on_error);
REQUIRE(r3.valid());
}
{
auto r5 = lua.safe_script("s1 = #c", sol::script_pass_on_error);
REQUIRE(r5.valid());
auto r1 = lua.safe_script("c:erase(11)", sol::script_pass_on_error);
REQUIRE(r1.valid());
auto r3 = lua.safe_script("s2 = #c", sol::script_pass_on_error);
REQUIRE(r3.valid());
auto r2 = lua.safe_script("c:erase(14)", sol::script_pass_on_error);
REQUIRE(r2.valid());
auto r4 = lua.safe_script("s3 = #c", sol::script_pass_on_error);
REQUIRE(r4.valid());
}
{
auto r = lua.safe_script("c:add(17, 27)", sol::script_pass_on_error);
REQUIRE(r.valid());
}
{
auto r = lua.safe_script("c[18] = 28", sol::script_pass_on_error);
REQUIRE(r.valid());
}
{
auto r = lua.safe_script("v3 = c[20]", sol::script_pass_on_error);
REQUIRE(r.valid());
}
std::size_t len = items.size();
int i1 = lua["i1"];
int i2 = lua["i2"];
std::size_t s1 = lua["s1"];
std::size_t s2 = lua["s2"];
std::size_t s3 = lua["s3"];
int v1 = lua["v1"];
int v2 = lua["v2"];
int v3 = lua["v3"];
std::pair<const short, int> values[]
= { { (short)12, 31 }, { (short)13, 23 }, { (short)15, 25 }, { (short)16, 26 }, { (short)17, 27 }, { (short)18, 28 }, { (short)20, 30 } };
{
for (const auto& v : values) {
auto it = items.find(v.first);
REQUIRE((it != items.cend()));
REQUIRE((it->second == v.second));
}
}
REQUIRE((s1 == 7));
REQUIRE((s2 == 6));
REQUIRE((s3 == 5));
REQUIRE((len == 7));
REQUIRE((i1 == 21));
REQUIRE((i2 == 24));
REQUIRE((v1 == 21));
REQUIRE((v2 == 23));
REQUIRE((v3 == 30));
}
template <typename T>
void unordered_lookup_container_check(sol::state& lua, T&) {
auto result0 = lua.safe_script("assert(c['a'] == 'a')", sol::script_default_on_error);
REQUIRE(result0.valid());
auto result1 = lua.safe_script("assert(c['b'] == 'b')", sol::script_default_on_error);
REQUIRE(result1.valid());
auto result2 = lua.safe_script("assert(c['c'] == 'c')", sol::script_default_on_error);
REQUIRE(result2.valid());
}
TEST_CASE("containers/unordered lookup containers", "check ordered container types") {
SECTION("unordered_set") {
sol::state lua;
lua.open_libraries(sol::lib::base);
std::unordered_set<int> items{ 11, 12, 13, 14, 15 };
lua["c"] = &items;
unordered_container_check(lua, items);
}
SECTION("unordered_set string") {
sol::state lua;
lua.open_libraries(sol::lib::base);
std::unordered_set<std::string> items({ "a", "b", "c" });
lua["c"] = &items;
unordered_lookup_container_check(lua, items);
}
SECTION("unordered_multiset") {
sol::state lua;
lua.open_libraries(sol::lib::base);
std::unordered_multiset<int> items{ 11, 12, 13, 14, 15 };
lua["c"] = &items;
unordered_container_check(lua, items);
}
SECTION("unordered_multiset string") {
sol::state lua;
lua.open_libraries(sol::lib::base);
std::unordered_multiset<std::string> items({ "a", "b", "c" });
lua["c"] = &items;
unordered_lookup_container_check(lua, items);
}
}
TEST_CASE("containers/associative unordered containers", "check associative (map) containers that are ordered that they fulfill basic requirements") {
SECTION("unordered_map") {
sol::state lua;
lua.open_libraries(sol::lib::base);
std::unordered_map<short, int> items{ { (short)11, 21 }, { (short)12, 22 }, { (short)13, 23 }, { (short)14, 24 }, { (short)15, 25 } };
lua["c"] = &items;
associative_unordered_container_check(lua, items);
}
SECTION("unordered_map string") {
sol::state lua;
lua.open_libraries(sol::lib::base);
std::unordered_map<std::string, std::string> items{ { "a", "a" }, { "b", "b" }, { "c", "c" } };
lua["c"] = &items;
unordered_lookup_container_check(lua, items);
}
SECTION("unordered_multimap") {
sol::state lua;
lua.open_libraries(sol::lib::base);
std::unordered_multimap<short, int> items{ { (short)11, 21 }, { (short)12, 22 }, { (short)13, 23 }, { (short)14, 24 }, { (short)15, 25 } };
lua["c"] = &items;
associative_unordered_container_check(lua, items);
}
SECTION("unordered_multimap string") {
sol::state lua;
lua.open_libraries(sol::lib::base);
std::unordered_multimap<std::string, std::string> items{ { "a", "a" }, { "b", "b" }, { "c", "c" } };
lua["c"] = &items;
unordered_lookup_container_check(lua, items);
}
}

View File

@ -37,46 +37,6 @@
#include <set> #include <set>
#include <unordered_set> #include <unordered_set>
auto test_table_return_one() {
return sol::as_table(std::vector<int>{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 });
}
auto test_table_return_two() {
return sol::as_table(std::vector<std::pair<std::string, int>>{ { "one", 1 }, { "two", 2 }, { "three", 3 } });
}
auto test_table_return_three() {
return sol::as_table(std::map<std::string, std::string>{ { "name", "Rapptz" }, { "friend", "ThePhD" }, { "project", "sol" } });
}
auto test_table_return_four() {
return sol::as_table(std::array<std::pair<std::string, int>, 4>{ { { "one", 1 }, { "two", 2 }, { "three", 3 }, { "four", 4 } } });
}
template <typename S, typename T>
void check_ordered_values(S& src, T& target) {
std::size_t idx = 0;
auto b = std::begin(target);
auto e = std::end(target);
for (; b != e; ++b, ++idx) {
const auto& v = src[idx];
REQUIRE((*b == v));
}
}
template <typename S, typename T>
void check_unordered_values(S& src, T& target) {
std::size_t idx = 0;
auto b = std::begin(target);
auto e = std::end(target);
for (; b != e; ++b, ++idx) {
auto sb = std::begin(src);
auto se = std::end(src);
auto it = std::find(sb, se, *b);
REQUIRE((it != se));
}
}
TEST_CASE("containers/returns", "make sure that even references to vectors are being serialized as tables") { TEST_CASE("containers/returns", "make sure that even references to vectors are being serialized as tables") {
sol::state lua; sol::state lua;
std::vector<int> v{ 1, 2, 3 }; std::vector<int> v{ 1, 2, 3 };
@ -98,123 +58,6 @@ TEST_CASE("containers/returns", "make sure that even references to vectors are b
REQUIRE(matching); REQUIRE(matching);
} }
TEST_CASE("containers/vector roundtrip", "make sure vectors can be round-tripped") {
sol::state lua;
std::vector<int> v{ 1, 2, 3 };
lua.set_function("f", [&]() -> std::vector<int>& {
return v;
});
auto result1 = lua.safe_script("x = f()", sol::script_pass_on_error);
REQUIRE(result1.valid());
std::vector<int> x = lua["x"];
bool areequal = x == v;
REQUIRE(areequal);
}
TEST_CASE("containers/deque roundtrip", "make sure deques can be round-tripped") {
sol::state lua;
std::deque<int> v{ 1, 2, 3 };
lua.set_function("f", [&]() -> std::deque<int>& {
return v;
});
auto result1 = lua.safe_script("x = f()", sol::script_pass_on_error);
REQUIRE(result1.valid());
std::deque<int> x = lua["x"];
bool areequal = x == v;
REQUIRE(areequal);
}
TEST_CASE("containers/array roundtrip", "make sure arrays can be round-tripped") {
sol::state lua;
std::array<int, 3> v{ { 1, 2, 3 } };
lua.set_function("f", [&]() -> std::array<int, 3>& {
return v;
});
auto result1 = lua.safe_script("x = f()", sol::script_pass_on_error);
REQUIRE(result1.valid());
std::array<int, 3> x = lua["x"];
bool areequal = x == v;
REQUIRE(areequal);
}
TEST_CASE("containers/list roundtrip", "make sure lists can be round-tripped") {
sol::state lua;
std::list<int> v{ 1, 2, 3 };
lua.set_function("f", [&]() -> std::list<int>& {
return v;
});
auto result1 = lua.safe_script("x = f()", sol::script_pass_on_error);
REQUIRE(result1.valid());
std::list<int> x = lua["x"];
bool areequal = x == v;
REQUIRE(areequal);
}
TEST_CASE("containers/forward_list roundtrip", "make sure forward_lists can be round-tripped") {
sol::state lua;
std::forward_list<int> v{ 1, 2, 3 };
lua.set_function("f", [&]() -> std::forward_list<int>& {
return v;
});
auto result1 = lua.safe_script("x = f()", sol::script_pass_on_error);
REQUIRE(result1.valid());
std::forward_list<int> x = lua["x"];
bool areequal = x == v;
REQUIRE(areequal);
}
TEST_CASE("containers/map roundtrip", "make sure maps can be round-tripped") {
sol::state lua;
std::map<std::string, int> v{ { "a", 1 }, { "b", 2 }, { "c", 3 } };
lua.set_function("f", [&]() -> std::map<std::string, int>& {
return v;
});
auto result1 = lua.safe_script("x = f()", sol::script_pass_on_error);
REQUIRE(result1.valid());
std::map<std::string, int> x = lua["x"];
bool areequal = x == v;
REQUIRE(areequal);
}
TEST_CASE("containers/unordered_map roundtrip", "make sure unordered_maps can be round-tripped") {
sol::state lua;
std::unordered_map<std::string, int> v{ { "a", 1 }, { "b", 2 }, { "c", 3 } };
lua.set_function("f", [&]() -> std::unordered_map<std::string, int>& {
return v;
});
auto result1 = lua.safe_script("x = f()", sol::script_pass_on_error);
REQUIRE(result1.valid());
std::unordered_map<std::string, int> x = lua["x"];
bool areequal = x == v;
REQUIRE(areequal);
}
TEST_CASE("containers/unordered_set roundtrip", "make sure unordered_sets can be round-tripped") {
sol::state lua;
std::unordered_set<int> v{ 1, 2, 3 };
lua.set_function("f", [&]() -> std::unordered_set<int>& {
return v;
});
auto result1 = lua.safe_script("x = f()", sol::script_pass_on_error);
REQUIRE(result1.valid());
std::unordered_set<int> x = lua["x"];
bool areequal = x == v;
REQUIRE(areequal);
}
TEST_CASE("containers/set roundtrip", "make sure sets can be round-tripped") {
sol::state lua;
std::set<int> v{ 1, 2, 3 };
lua.set_function("f", [&]() -> std::set<int>& {
return v;
});
auto result1 = lua.safe_script("x = f()", sol::script_pass_on_error);
REQUIRE(result1.valid());
std::set<int> x = lua["x"];
bool areequal = x == v;
REQUIRE(areequal);
}
TEST_CASE("containers/custom usertype", "make sure container usertype metatables can be overridden") { TEST_CASE("containers/custom usertype", "make sure container usertype metatables can be overridden") {
typedef std::unordered_map<int, int> bark; typedef std::unordered_map<int, int> bark;
@ -305,33 +148,6 @@ TEST_CASE("containers/const serialization", "make sure containers are turned int
} }
#endif #endif
TEST_CASE("containers/table serialization", "ensure types can be serialized as tables still") {
typedef std::vector<int> woof;
sol::state lua;
lua.open_libraries();
lua.set("b", sol::as_table(woof{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30 }));
{
auto result = lua.safe_script("for k, v in ipairs(b) do assert(k == v) end", sol::script_pass_on_error);
REQUIRE(result.valid());
}
woof w{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30 };
lua.set("b", sol::as_table(w));
{
auto result = lua.safe_script("for k, v in ipairs(b) do assert(k == v) end", sol::script_pass_on_error);
REQUIRE(result.valid());
}
lua.set("b", sol::as_table(&w));
{
auto result = lua.safe_script("for k, v in ipairs(b) do assert(k == v) end", sol::script_pass_on_error);
REQUIRE(result.valid());
}
lua.set("b", sol::as_table(std::ref(w)));
{
auto result = lua.safe_script("for k, v in ipairs(b) do assert(k == v) end", sol::script_pass_on_error);
REQUIRE(result.valid());
}
}
TEST_CASE("containers/const correctness", "usertype metatable names should reasonably ignore const attributes") { TEST_CASE("containers/const correctness", "usertype metatable names should reasonably ignore const attributes") {
struct Vec { struct Vec {
int x, y, z; int x, y, z;
@ -369,84 +185,6 @@ end
REQUIRE(pfr2.valid()); REQUIRE(pfr2.valid());
} }
TEST_CASE("containers/arbitrary creation", "userdata and tables should be usable from standard containers") {
sol::state lua;
lua.open_libraries(sol::lib::base);
lua.set_function("test_one", test_table_return_one);
lua.set_function("test_two", test_table_return_two);
lua.set_function("test_three", test_table_return_three);
lua.set_function("test_four", test_table_return_four);
{
auto result = lua.safe_script("a = test_one()", sol::script_pass_on_error);
REQUIRE(result.valid());
}
{
auto result = lua.safe_script("b = test_two()", sol::script_pass_on_error);
REQUIRE(result.valid());
}
{
auto result = lua.safe_script("c = test_three()", sol::script_pass_on_error);
REQUIRE(result.valid());
}
{
auto result = lua.safe_script("d = test_four()", sol::script_pass_on_error);
REQUIRE(result.valid());
}
{
auto result = lua.safe_script("assert(#a == 10, 'error')", sol::script_pass_on_error);
REQUIRE(result.valid());
}
{
auto result = lua.safe_script("assert(a[3] == 3, 'error')", sol::script_pass_on_error);
REQUIRE(result.valid());
}
{
auto result = lua.safe_script("assert(b.one == 1, 'error')", sol::script_pass_on_error);
REQUIRE(result.valid());
}
{
auto result = lua.safe_script("assert(b.three == 3, 'error')", sol::script_pass_on_error);
REQUIRE(result.valid());
}
{
auto result = lua.safe_script("assert(c.name == 'Rapptz', 'error')", sol::script_pass_on_error);
REQUIRE(result.valid());
}
{
auto result = lua.safe_script("assert(c.project == 'sol', 'error')", sol::script_pass_on_error);
REQUIRE(result.valid());
}
{
auto result = lua.safe_script("assert(d.one == 1, 'error')", sol::script_pass_on_error);
REQUIRE(result.valid());
}
{
auto result = lua.safe_script("assert(d.three == 3, 'error')", sol::script_pass_on_error);
REQUIRE(result.valid());
}
{
auto result = lua.safe_script("assert(d.four == 4, 'error')", sol::script_pass_on_error);
REQUIRE(result.valid());
}
sol::table a = lua.get<sol::table>("a");
sol::table b = lua.get<sol::table>("b");
sol::table c = lua.get<sol::table>("c");
sol::table d = lua["d"];
REQUIRE(a.size() == 10ULL);
REQUIRE(a.get<int>(3) == 3);
REQUIRE(b.get<int>("one") == 1);
REQUIRE(b.get<int>("three") == 3);
REQUIRE(c.get<std::string>("name") == "Rapptz");
REQUIRE(c.get<std::string>("project") == "sol");
REQUIRE(d.get<int>("one") == 1);
REQUIRE(d.get<int>("three") == 3);
REQUIRE(d.get<int>("four") == 4);
}
TEST_CASE("containers/usertype transparency", "Make sure containers pass their arguments through transparently and push the results as references, not new values") { TEST_CASE("containers/usertype transparency", "Make sure containers pass their arguments through transparently and push the results as references, not new values") {
class A { class A {
public: public:
@ -616,41 +354,6 @@ TEST_CASE("containers/to_args", "Test that the to_args abstractions works") {
REQUIRE(d == 12); REQUIRE(d == 12);
} }
TEST_CASE("containers/ipairs test", "ensure that abstractions roundtrip properly") {
struct thing {
int x = 20;
};
thing t{};
sol::state lua;
lua.open_libraries();
lua.set_function("f", [&t]() {
return std::vector<thing*>(5, &t);
});
auto result1 = lua.safe_script(R"(
c = f()
)", sol::script_pass_on_error);
REQUIRE(result1.valid());
auto result2 = lua.safe_script(R"(
check = {}
local i = 1
while c[i] do
check[i] = c[i]
i = i + 1
end
)", sol::script_pass_on_error);
REQUIRE(result2.valid());
sol::table c = lua["check"];
for (std::size_t i = 1; i < 6; ++i) {
thing& ct = c[i];
REQUIRE(&t == &ct);
REQUIRE(ct.x == 20);
}
}
TEST_CASE("containers/append idiom", "ensure the append-idiom works as intended") { TEST_CASE("containers/append idiom", "ensure the append-idiom works as intended") {
sol::state lua; sol::state lua;
lua.open_libraries(sol::lib::base); lua.open_libraries(sol::lib::base);
@ -670,7 +373,7 @@ function f_append(vec)
vec[#vec + 1] = -54 vec[#vec + 1] = -54
print("#vec in lua: " .. #vec) print("#vec in lua: " .. #vec)
end end
)"); )", sol::script_pass_on_error);
REQUIRE(result1.valid()); REQUIRE(result1.valid());
std::vector<int> fill_cmp{ 1, 2, 3 }; std::vector<int> fill_cmp{ 1, 2, 3 };
@ -716,8 +419,8 @@ TEST_CASE("containers/non_copyable", "make sure non-copyable types in containers
} }
TEST_CASE("containers/pairs", "test how well pairs work with the underlying system") { TEST_CASE("containers/pairs", "test how well pairs work with the underlying system") {
typedef std::pair<std::string, int> pair_arr_t[5]; using pair_arr_t = std::pair<std::string, int>[5];
typedef int arr_t[5]; using arr_t = int[5];
sol::state lua; sol::state lua;
@ -825,52 +528,3 @@ TEST_CASE("containers/pointer types", "check that containers with unique usertyp
int val2 = b2->get(); int val2 = b2->get();
REQUIRE(val2 == 500); REQUIRE(val2 == 500);
} }
TEST_CASE("containers/initializer-list", "test initializer lists get pushed as tables directly rather than userdata") {
SECTION("array-like") {
sol::state lua;
lua.open_libraries(sol::lib::base, sol::lib::table);
lua["c"] = { 1, 2, 3, 4, 5 };
auto result1 = lua.safe_script(R"lua(
for k, v in pairs(c) do
assert(k == v)
end
)lua", sol::script_pass_on_error);
sol::as_table_t<std::vector<int>> t1vector = lua["c"];
sol::as_table_t<std::deque<int>> t1deque = lua["c"];
sol::as_table_t<std::list<int>> t1list = lua["c"];
sol::as_table_t<std::forward_list<int>> t1flist = lua["c"];
sol::as_table_t<std::set<int>> t1set = lua["c"];
const int src[5] = { 1, 2, 3, 4, 5 };
check_ordered_values(src, t1vector.source);
check_ordered_values(src, t1deque.source);
check_ordered_values(src, t1list.source);
check_ordered_values(src, t1flist.source);
check_ordered_values(src, t1set.source);
}
SECTION("map-like") {
sol::state lua;
lua.open_libraries(sol::lib::base, sol::lib::table);
std::pair<const std::string, int> src[5]{
{ "a", 21 },
{ "b", 22 },
{ "c", 23 },
{ "d", 24 },
{ "e", 25 }
};
lua["c"] = std::initializer_list<std::pair<std::string, int>>{
{ "a", 21 },
{ "b", 22 },
{ "c", 23 },
{ "d", 24 },
{ "e", 25 }
};
sol::as_table_t<std::unordered_map<std::string, int>> t1umap = lua["c"];
sol::as_table_t<std::unordered_multimap<std::string, int>> t1ummap = lua["c"];
check_unordered_values(src, t1umap.source);
check_unordered_values(src, t1ummap.source);
}
}

View File

@ -0,0 +1,172 @@
// sol3
// The MIT License (MIT)
// Copyright (c) 2013-2018 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "sol_test.hpp"
#include "common_classes.hpp"
#include <catch.hpp>
#include <iterator>
#include <vector>
#include <list>
#include <forward_list>
#include <map>
#include <deque>
#include <array>
#include <unordered_map>
#include <set>
#include <unordered_set>
TEST_CASE("containers/vector roundtrip", "make sure vectors can be round-tripped") {
sol::state lua;
std::vector<int> v{ 1, 2, 3 };
lua.set_function("f", [&]() -> std::vector<int>& { return v; });
auto result1 = lua.safe_script("x = f()", sol::script_pass_on_error);
REQUIRE(result1.valid());
std::vector<int> x = lua["x"];
bool areequal = x == v;
REQUIRE(areequal);
}
TEST_CASE("containers/deque roundtrip", "make sure deques can be round-tripped") {
sol::state lua;
std::deque<int> v{ 1, 2, 3 };
lua.set_function("f", [&]() -> std::deque<int>& { return v; });
auto result1 = lua.safe_script("x = f()", sol::script_pass_on_error);
REQUIRE(result1.valid());
std::deque<int> x = lua["x"];
bool areequal = x == v;
REQUIRE(areequal);
}
TEST_CASE("containers/array roundtrip", "make sure arrays can be round-tripped") {
sol::state lua;
std::array<int, 3> v{ { 1, 2, 3 } };
lua.set_function("f", [&]() -> std::array<int, 3>& { return v; });
auto result1 = lua.safe_script("x = f()", sol::script_pass_on_error);
REQUIRE(result1.valid());
std::array<int, 3> x = lua["x"];
bool areequal = x == v;
REQUIRE(areequal);
}
TEST_CASE("containers/list roundtrip", "make sure lists can be round-tripped") {
sol::state lua;
std::list<int> v{ 1, 2, 3 };
lua.set_function("f", [&]() -> std::list<int>& { return v; });
auto result1 = lua.safe_script("x = f()", sol::script_pass_on_error);
REQUIRE(result1.valid());
std::list<int> x = lua["x"];
bool areequal = x == v;
REQUIRE(areequal);
}
TEST_CASE("containers/forward_list roundtrip", "make sure forward_lists can be round-tripped") {
sol::state lua;
std::forward_list<int> v{ 1, 2, 3 };
lua.set_function("f", [&]() -> std::forward_list<int>& { return v; });
auto result1 = lua.safe_script("x = f()", sol::script_pass_on_error);
REQUIRE(result1.valid());
std::forward_list<int> x = lua["x"];
bool areequal = x == v;
REQUIRE(areequal);
}
TEST_CASE("containers/map roundtrip", "make sure maps can be round-tripped") {
sol::state lua;
std::map<std::string, int> v{ { "a", 1 }, { "b", 2 }, { "c", 3 } };
lua.set_function("f", [&]() -> std::map<std::string, int>& { return v; });
auto result1 = lua.safe_script("x = f()", sol::script_pass_on_error);
REQUIRE(result1.valid());
std::map<std::string, int> x = lua["x"];
bool areequal = x == v;
REQUIRE(areequal);
}
TEST_CASE("containers/unordered_map roundtrip", "make sure unordered_maps can be round-tripped") {
sol::state lua;
std::unordered_map<std::string, int> v{ { "a", 1 }, { "b", 2 }, { "c", 3 } };
lua.set_function("f", [&]() -> std::unordered_map<std::string, int>& { return v; });
auto result1 = lua.safe_script("x = f()", sol::script_pass_on_error);
REQUIRE(result1.valid());
std::unordered_map<std::string, int> x = lua["x"];
bool areequal = x == v;
REQUIRE(areequal);
}
TEST_CASE("containers/unordered_set roundtrip", "make sure unordered_sets can be round-tripped") {
sol::state lua;
std::unordered_set<int> v{ 1, 2, 3 };
lua.set_function("f", [&]() -> std::unordered_set<int>& { return v; });
auto result1 = lua.safe_script("x = f()", sol::script_pass_on_error);
REQUIRE(result1.valid());
std::unordered_set<int> x = lua["x"];
bool areequal = x == v;
REQUIRE(areequal);
}
TEST_CASE("containers/set roundtrip", "make sure sets can be round-tripped") {
sol::state lua;
std::set<int> v{ 1, 2, 3 };
lua.set_function("f", [&]() -> std::set<int>& { return v; });
auto result1 = lua.safe_script("x = f()", sol::script_pass_on_error);
REQUIRE(result1.valid());
std::set<int> x = lua["x"];
bool areequal = x == v;
REQUIRE(areequal);
}
TEST_CASE("containers/ipairs test", "ensure that abstractions roundtrip properly") {
struct thing {
int x = 20;
};
thing t{};
sol::state lua;
lua.open_libraries();
lua.set_function("f", [&t]() { return std::vector<thing*>(5, &t); });
auto result1 = lua.safe_script(R"(
c = f()
)",
sol::script_pass_on_error);
REQUIRE(result1.valid());
auto result2 = lua.safe_script(R"(
check = {}
local i = 1
while c[i] do
check[i] = c[i]
i = i + 1
end
)",
sol::script_pass_on_error);
REQUIRE(result2.valid());
sol::table c = lua["check"];
for (std::size_t i = 1; i < 6; ++i) {
thing& ct = c[i];
REQUIRE(&t == &ct);
REQUIRE(ct.x == 20);
}
}

View File

@ -0,0 +1,222 @@
// sol3
// The MIT License (MIT)
// Copyright (c) 2013-2018 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "sol_test.hpp"
#include "common_classes.hpp"
#include <catch.hpp>
#include <iterator>
#include <vector>
#include <list>
#include <forward_list>
#include <map>
#include <deque>
#include <array>
#include <unordered_map>
#include <set>
#include <unordered_set>
auto test_table_return_one() {
return sol::as_table(std::vector<int>{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 });
}
auto test_table_return_two() {
return sol::as_table(std::vector<std::pair<std::string, int>>{ { "one", 1 }, { "two", 2 }, { "three", 3 } });
}
auto test_table_return_three() {
return sol::as_table(std::map<std::string, std::string>{ { "name", "Rapptz" }, { "friend", "ThePhD" }, { "project", "sol" } });
}
auto test_table_return_four() {
return sol::as_table(std::array<std::pair<std::string, int>, 4>{ { { "one", 1 }, { "two", 2 }, { "three", 3 }, { "four", 4 } } });
}
template <typename S, typename T>
void check_ordered_values(S& src, T& target) {
std::size_t idx = 0;
auto b = std::begin(target);
auto e = std::end(target);
for (; b != e; ++b, ++idx) {
const auto& v = src[idx];
REQUIRE((*b == v));
}
}
template <typename S, typename T>
void table_check_unordered_values(S& src, T& target) {
std::size_t idx = 0;
auto b = std::begin(target);
auto e = std::end(target);
for (; b != e; ++b, ++idx) {
auto sb = std::begin(src);
auto se = std::end(src);
auto it = std::find(sb, se, *b);
REQUIRE((it != se));
}
}
TEST_CASE("containers/arbitrary creation", "userdata and tables should be usable from standard containers") {
sol::state lua;
lua.open_libraries(sol::lib::base);
lua.set_function("test_one", test_table_return_one);
lua.set_function("test_two", test_table_return_two);
lua.set_function("test_three", test_table_return_three);
lua.set_function("test_four", test_table_return_four);
{
auto result = lua.safe_script("a = test_one()", sol::script_pass_on_error);
REQUIRE(result.valid());
}
{
auto result = lua.safe_script("b = test_two()", sol::script_pass_on_error);
REQUIRE(result.valid());
}
{
auto result = lua.safe_script("c = test_three()", sol::script_pass_on_error);
REQUIRE(result.valid());
}
{
auto result = lua.safe_script("d = test_four()", sol::script_pass_on_error);
REQUIRE(result.valid());
}
{
auto result = lua.safe_script("assert(#a == 10, 'error')", sol::script_pass_on_error);
REQUIRE(result.valid());
}
{
auto result = lua.safe_script("assert(a[3] == 3, 'error')", sol::script_pass_on_error);
REQUIRE(result.valid());
}
{
auto result = lua.safe_script("assert(b.one == 1, 'error')", sol::script_pass_on_error);
REQUIRE(result.valid());
}
{
auto result = lua.safe_script("assert(b.three == 3, 'error')", sol::script_pass_on_error);
REQUIRE(result.valid());
}
{
auto result = lua.safe_script("assert(c.name == 'Rapptz', 'error')", sol::script_pass_on_error);
REQUIRE(result.valid());
}
{
auto result = lua.safe_script("assert(c.project == 'sol', 'error')", sol::script_pass_on_error);
REQUIRE(result.valid());
}
{
auto result = lua.safe_script("assert(d.one == 1, 'error')", sol::script_pass_on_error);
REQUIRE(result.valid());
}
{
auto result = lua.safe_script("assert(d.three == 3, 'error')", sol::script_pass_on_error);
REQUIRE(result.valid());
}
{
auto result = lua.safe_script("assert(d.four == 4, 'error')", sol::script_pass_on_error);
REQUIRE(result.valid());
}
sol::table a = lua.get<sol::table>("a");
sol::table b = lua.get<sol::table>("b");
sol::table c = lua.get<sol::table>("c");
sol::table d = lua["d"];
REQUIRE(a.size() == 10ULL);
REQUIRE(a.get<int>(3) == 3);
REQUIRE(b.get<int>("one") == 1);
REQUIRE(b.get<int>("three") == 3);
REQUIRE(c.get<std::string>("name") == "Rapptz");
REQUIRE(c.get<std::string>("project") == "sol");
REQUIRE(d.get<int>("one") == 1);
REQUIRE(d.get<int>("three") == 3);
REQUIRE(d.get<int>("four") == 4);
}
TEST_CASE("containers/table serialization", "ensure types can be serialized as tables still") {
typedef std::vector<int> woof;
sol::state lua;
lua.open_libraries();
lua.set("b", sol::as_table(woof{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30 }));
{
auto result = lua.safe_script("for k, v in ipairs(b) do assert(k == v) end", sol::script_pass_on_error);
REQUIRE(result.valid());
}
woof w{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30 };
lua.set("b", sol::as_table(w));
{
auto result = lua.safe_script("for k, v in ipairs(b) do assert(k == v) end", sol::script_pass_on_error);
REQUIRE(result.valid());
}
lua.set("b", sol::as_table(&w));
{
auto result = lua.safe_script("for k, v in ipairs(b) do assert(k == v) end", sol::script_pass_on_error);
REQUIRE(result.valid());
}
lua.set("b", sol::as_table(std::ref(w)));
{
auto result = lua.safe_script("for k, v in ipairs(b) do assert(k == v) end", sol::script_pass_on_error);
REQUIRE(result.valid());
}
}
TEST_CASE("containers/initializer-list", "test initializer lists get pushed as tables directly rather than userdata") {
SECTION("array-like") {
sol::state lua;
lua.open_libraries(sol::lib::base, sol::lib::table);
lua["c"] = { 1, 2, 3, 4, 5 };
auto result1 = lua.safe_script(R"lua(
for k, v in pairs(c) do
assert(k == v)
end
)lua",
sol::script_pass_on_error);
sol::as_table_t<std::vector<int>> t1vector = lua["c"];
sol::as_table_t<std::deque<int>> t1deque = lua["c"];
sol::as_table_t<std::list<int>> t1list = lua["c"];
sol::as_table_t<std::forward_list<int>> t1flist = lua["c"];
sol::as_table_t<std::set<int>> t1set = lua["c"];
const int src[5] = { 1, 2, 3, 4, 5 };
check_ordered_values(src, t1vector.source);
check_ordered_values(src, t1deque.source);
check_ordered_values(src, t1list.source);
check_ordered_values(src, t1flist.source);
check_ordered_values(src, t1set.source);
}
SECTION("map-like") {
sol::state lua;
lua.open_libraries(sol::lib::base, sol::lib::table);
std::pair<const std::string, int> src[5]{ { "a", 21 }, { "b", 22 }, { "c", 23 }, { "d", 24 }, { "e", 25 } };
lua["c"] = std::initializer_list<std::pair<std::string, int>>{ { "a", 21 }, { "b", 22 }, { "c", 23 }, { "d", 24 }, { "e", 25 } };
sol::as_table_t<std::unordered_map<std::string, int>> t1umap = lua["c"];
sol::as_table_t<std::unordered_multimap<std::string, int>> t1ummap = lua["c"];
table_check_unordered_values(src, t1umap.source);
table_check_unordered_values(src, t1ummap.source);
}
}

View File

@ -0,0 +1,289 @@
// sol3
// The MIT License (MIT)
// Copyright (c) 2013-2018 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "sol_test.hpp"
#include "common_classes.hpp"
#include <catch.hpp>
TEST_CASE("usertype/usertype", "Show that we can create classes from usertype and use them") {
sol::state lua;
sol::usertype<fuser> lc = lua.new_usertype<fuser>("fuser", "add", &fuser::add, "add2", &fuser::add2);
lua.safe_script(
"a = fuser:new()\n"
"b = a:add(1)\n"
"c = a:add2(1)\n");
sol::object a = lua.get<sol::object>("a");
sol::object b = lua.get<sol::object>("b");
sol::object c = lua.get<sol::object>("c");
REQUIRE((a.is<sol::userdata_value>()));
auto atype = a.get_type();
auto btype = b.get_type();
auto ctype = c.get_type();
REQUIRE((atype == sol::type::userdata));
REQUIRE((btype == sol::type::number));
REQUIRE((ctype == sol::type::number));
int bresult = b.as<int>();
int cresult = c.as<int>();
REQUIRE(bresult == 1);
REQUIRE(cresult == 3);
}
TEST_CASE("usertype/usertype fundamentals", "Verify new_usertype registers basic member functions and a constructor") {
sol::state lua;
lua.new_usertype<fuser>("fuser", "add", &fuser::add, "add2", &fuser::add2);
lua.safe_script(
"a = fuser.new()\n"
"b = a:add(1)\n"
"c = a:add2(1)\n");
sol::object a = lua.get<sol::object>("a");
sol::object b = lua.get<sol::object>("b");
sol::object c = lua.get<sol::object>("c");
REQUIRE((a.is<sol::userdata_value>()));
auto atype = a.get_type();
auto btype = b.get_type();
auto ctype = c.get_type();
REQUIRE((atype == sol::type::userdata));
REQUIRE((btype == sol::type::number));
REQUIRE((ctype == sol::type::number));
int bresult = b.as<int>();
int cresult = c.as<int>();
REQUIRE(bresult == 1);
REQUIRE(cresult == 3);
}
TEST_CASE("usertype/safety", "crash with an exception -- not a segfault -- on bad userdata calls") {
class Test {
public:
void sayHello() {
std::cout << "Hey\n";
}
};
sol::state lua;
lua.new_usertype<Test>("Test", "sayHello", &Test::sayHello);
static const std::string code = R"(
local t = Test.new()
t:sayHello() --Works fine
t.sayHello() --Uh oh.
)";
auto result = lua.safe_script(code, sol::script_pass_on_error);
REQUIRE_FALSE(result.valid());
}
TEST_CASE("regressions/one", "issue number 48") {
sol::state lua;
lua.new_usertype<vars>("vars", "boop", &vars::boop);
auto code
= "beep = vars.new()\n"
"beep.boop = 1";
auto result1 = lua.safe_script(code, sol::script_pass_on_error);
REQUIRE(result1.valid());
// test for segfault
auto my_var = lua.get<vars>("beep");
auto& my_var_ref = lua.get<vars>("beep");
auto* my_var_ptr = lua.get<vars*>("beep");
REQUIRE(my_var.boop == 1);
REQUIRE(my_var_ref.boop == 1);
REQUIRE(my_var_ptr->boop == 1);
REQUIRE(std::addressof(my_var_ref) == my_var_ptr);
std::cout << "----- end of 3" << std::endl;
}
TEST_CASE("usertype/issue-number-twenty-five", "Using pointers and references from C++ classes in Lua") {
struct test {
int x = 0;
test& set() {
x = 10;
return *this;
}
int get() {
return x;
}
test* pget() {
return this;
}
test create_get() {
return *this;
}
int fun(int xa) {
return xa * 10;
}
};
sol::state lua;
lua.open_libraries(sol::lib::base);
lua.new_usertype<test>("test", "set", &test::set, "get", &test::get, "pointer_get", &test::pget, "fun", &test::fun, "create_get", &test::create_get);
{
auto result = lua.safe_script("x = test.new()", sol::script_pass_on_error);
REQUIRE(result.valid());
}
{
auto result = lua.safe_script("assert(x:set():get() == 10)", sol::script_pass_on_error);
REQUIRE(result.valid());
}
{
auto result = lua.safe_script("y = x:pointer_get()", sol::script_pass_on_error);
REQUIRE(result.valid());
}
{
auto result = lua.safe_script("y:set():get()", sol::script_pass_on_error);
REQUIRE(result.valid());
}
{
auto result = lua.safe_script("y:fun(10)", sol::script_pass_on_error);
REQUIRE(result.valid());
}
{
auto result = lua.safe_script("x:fun(10)", sol::script_pass_on_error);
REQUIRE(result.valid());
}
{
auto result = lua.safe_script("assert(y:fun(10) == x:fun(10), '...')", sol::script_pass_on_error);
REQUIRE(result.valid());
}
{
auto result = lua.safe_script("assert(y:fun(10) == 100, '...')", sol::script_pass_on_error);
REQUIRE(result.valid());
}
{
auto result = lua.safe_script("assert(y:set():get() == y:set():get(), '...')", sol::script_pass_on_error);
REQUIRE(result.valid());
}
{
auto result = lua.safe_script("assert(y:set():get() == 10, '...')", sol::script_pass_on_error);
REQUIRE(result.valid());
}
}
TEST_CASE("usertype/issue-number-thirty-five", "using value types created from lua-called C++ code, fixing user-defined types with constructors") {
sol::state lua;
lua.open_libraries(sol::lib::base);
sol::constructors<sol::types<float, float, float>> ctor;
lua.new_usertype<Vec>("Vec", ctor, "normalized", &Vec::normalized, "length", &Vec::length);
{
auto result = lua.safe_script(
"v = Vec.new(1, 2, 3)\n"
"print(v:length())");
REQUIRE(result.valid());
}
{
auto result = lua.safe_script(
"v = Vec.new(1, 2, 3)\n"
"print(v:normalized():length())");
REQUIRE(result.valid());
}
}
TEST_CASE("usertype/lua-stored-usertype", "ensure usertype values can be stored without keeping usertype object alive") {
sol::state lua;
lua.open_libraries(sol::lib::base);
{
sol::constructors<sol::types<float, float, float>> ctor;
sol::usertype<Vec> udata = lua.new_usertype<Vec>("Vec", ctor, "normalized", &Vec::normalized, "length", &Vec::length);
// usertype dies, but still usable in lua!
}
{
auto result = lua.safe_script(
"collectgarbage()\n"
"v = Vec.new(1, 2, 3)\n"
"print(v:length())");
REQUIRE(result.valid());
}
{
auto result = lua.safe_script(
"v = Vec.new(1, 2, 3)\n"
"print(v:normalized():length())");
REQUIRE(result.valid());
}
}
TEST_CASE("usertype/get-set-references", "properly get and set with std::ref semantics. Note that to get, we must not use Unqualified<T> on the type...") {
std::cout << "----- in 4" << std::endl;
sol::state lua;
lua.new_usertype<vars>("vars", "boop", &vars::boop);
vars var{};
vars rvar{};
std::cout << "setting beep" << std::endl;
lua.set("beep", var);
std::cout << "setting rbeep" << std::endl;
lua.set("rbeep", std::ref(rvar));
std::cout << "getting my_var" << std::endl;
auto& my_var = lua.get<vars>("beep");
std::cout << "setting rbeep" << std::endl;
auto& ref_var = lua.get<std::reference_wrapper<vars>>("rbeep");
vars& proxy_my_var = lua["beep"];
std::reference_wrapper<vars> proxy_ref_var = lua["rbeep"];
var.boop = 2;
rvar.boop = 5;
// Was return as a value: var must be diferent from "beep"
REQUIRE_FALSE(std::addressof(var) == std::addressof(my_var));
REQUIRE_FALSE(std::addressof(proxy_my_var) == std::addressof(var));
REQUIRE((my_var.boop == 0));
REQUIRE(var.boop != my_var.boop);
REQUIRE(std::addressof(ref_var) == std::addressof(rvar));
REQUIRE(std::addressof(proxy_ref_var.get()) == std::addressof(rvar));
REQUIRE(rvar.boop == 5);
REQUIRE(rvar.boop == ref_var.boop);
std::cout << "----- end of 4" << std::endl;
}
TEST_CASE("usertype/const-pointer", "Make sure const pointers can be taken") {
struct A_x {
int x = 201;
};
struct B_foo {
int foo(const A_x* a) {
return a->x;
};
};
sol::state lua;
lua.new_usertype<B_foo>("B", "foo", &B_foo::foo);
lua.set("a", A_x());
lua.set("b", B_foo());
lua.safe_script("x = b:foo(a)");
int x = lua["x"];
REQUIRE(x == 201);
std::cout << "----- end of 6" << std::endl;
}

View File

@ -0,0 +1,206 @@
// sol3
// The MIT License (MIT)
// Copyright (c) 2013-2018 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "sol_test.hpp"
#include "common_classes.hpp"
#include <catch.hpp>
struct matrix_xf {
float a, b;
static matrix_xf from_lua_table(sol::table t) {
matrix_xf m;
m.a = t[1][1];
m.b = t[1][2];
return m;
}
};
struct matrix_xi {
int a, b;
static matrix_xi from_lua_table(sol::table t) {
matrix_xi m;
m.a = t[1][1];
m.b = t[1][2];
return m;
}
};
TEST_CASE("usertype/call_constructor", "make sure lua types can be constructed with function call constructors") {
sol::state lua;
lua.open_libraries(sol::lib::base);
lua.new_usertype<thing>("thing", "v", &thing::v, sol::call_constructor, sol::constructors<sol::types<>, sol::types<int>>());
lua.safe_script(R"(
t = thing(256)
)");
thing& y = lua["t"];
INFO(y.v);
REQUIRE(y.v == 256);
}
TEST_CASE("usertype/call_constructor factories", "make sure tables can be passed to factory-based call constructors") {
sol::state lua;
lua.open_libraries();
lua.new_usertype<matrix_xf>("mat", sol::call_constructor, sol::factories(&matrix_xf::from_lua_table));
lua.safe_script("m = mat{ {1.1, 2.2} }");
lua.new_usertype<matrix_xi>("mati", sol::call_constructor, sol::factories(&matrix_xi::from_lua_table));
lua.safe_script("mi = mati{ {1, 2} }");
matrix_xf& m = lua["m"];
REQUIRE(m.a == 1.1f);
REQUIRE(m.b == 2.2f);
matrix_xi& mi = lua["mi"];
REQUIRE(mi.a == 1);
REQUIRE(mi.b == 2);
}
TEST_CASE("usertype/call_constructor metatable check", "prevent metatable regression") {
class class01 {
public:
int x = 57;
class01() {
}
};
class class02 {
public:
int x = 50;
class02() {
}
class02(const class01& other) : x(other.x) {
}
};
sol::state lua;
lua.new_usertype<class01>("class01", sol::call_constructor, sol::constructors<sol::types<>, sol::types<const class01&>>());
lua.new_usertype<class02>("class02", sol::call_constructor, sol::constructors<sol::types<>, sol::types<const class02&>, sol::types<const class01&>>());
REQUIRE_NOTHROW(lua.safe_script(R"(
x = class01()
y = class02(x)
)"));
class02& y = lua["y"];
REQUIRE(y.x == 57);
}
TEST_CASE("usertype/blank_constructor", "make sure lua types cannot be constructed with arguments if a blank / empty constructor is provided") {
sol::state lua;
lua.open_libraries(sol::lib::base);
lua.new_usertype<thing>("thing", "v", &thing::v, sol::call_constructor, sol::constructors<>());
auto result = lua.safe_script("t = thing(256)", sol::script_pass_on_error);
REQUIRE_FALSE(result.valid());
}
TEST_CASE("usertype/no_constructor", "make sure lua types cannot be constructed if a blank / empty constructor is provided") {
SECTION("order1") {
sol::state lua;
lua.open_libraries(sol::lib::base);
lua.new_usertype<thing>("thing", "v", &thing::v, sol::call_constructor, sol::no_constructor);
auto result = lua.safe_script("t = thing()", sol::script_pass_on_error);
REQUIRE_FALSE(result.valid());
}
SECTION("order2") {
sol::state lua;
lua.open_libraries(sol::lib::base);
lua.new_usertype<thing>("thing", sol::call_constructor, sol::no_constructor, "v", &thing::v);
auto result = lua.safe_script("t = thing.new()", sol::script_pass_on_error);
REQUIRE_FALSE(result.valid());
}
SECTION("new no_constructor") {
sol::state lua;
lua.open_libraries(sol::lib::base);
lua.new_usertype<thing>("thing", sol::meta_function::construct, sol::no_constructor);
auto result = lua.safe_script("t = thing.new()", sol::script_pass_on_error);
REQUIRE_FALSE(result.valid());
}
SECTION("call no_constructor") {
sol::state lua;
lua.open_libraries(sol::lib::base);
lua.new_usertype<thing>("thing", sol::call_constructor, sol::no_constructor);
auto result = lua.safe_script("t = thing()", sol::script_pass_on_error);
REQUIRE_FALSE(result.valid());
}
}
TEST_CASE("usertype/constructor list", "Show that we can create classes from usertype and use them with multiple constructors") {
sol::state lua;
sol::constructors<sol::types<>, sol::types<int>, sol::types<int, int>> con;
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"
"u = a:add(1)\n"
"v = a:add2(1)\n"
"b = fuser:new()\n"
"w = b:add(1)\n"
"x = b:add2(1)\n"
"c = fuser.new(2, 3)\n"
"y = c:add(1)\n"
"z = c:add2(1)\n");
sol::object a = lua.get<sol::object>("a");
auto atype = a.get_type();
REQUIRE((atype == sol::type::userdata));
sol::object u = lua.get<sol::object>("u");
sol::object v = lua.get<sol::object>("v");
REQUIRE((u.as<int>() == 3));
REQUIRE((v.as<int>() == 5));
sol::object b = lua.get<sol::object>("b");
auto btype = b.get_type();
REQUIRE((btype == sol::type::userdata));
sol::object w = lua.get<sol::object>("w");
sol::object x = lua.get<sol::object>("x");
REQUIRE((w.as<int>() == 1));
REQUIRE((x.as<int>() == 3));
sol::object c = lua.get<sol::object>("c");
auto ctype = c.get_type();
REQUIRE((ctype == sol::type::userdata));
sol::object y = lua.get<sol::object>("y");
sol::object z = lua.get<sol::object>("z");
REQUIRE((y.as<int>() == 7));
REQUIRE((z.as<int>() == 9));
}

View File

@ -31,16 +31,6 @@
#include <list> #include <list>
#include <memory> #include <memory>
struct thing {
int v = 100;
thing() {
}
thing(int x)
: v(x) {
}
};
struct self_test { struct self_test {
int bark; int bark;
@ -62,154 +52,6 @@ struct self_test {
} }
}; };
struct matrix_xf {
float a, b;
static matrix_xf from_lua_table(sol::table t) {
matrix_xf m;
m.a = t[1][1];
m.b = t[1][2];
return m;
}
};
struct matrix_xi {
int a, b;
static matrix_xi from_lua_table(sol::table t) {
matrix_xi m;
m.a = t[1][1];
m.b = t[1][2];
return m;
}
};
TEST_CASE("usertype/usertype", "Show that we can create classes from usertype and use them") {
sol::state lua;
sol::usertype<fuser> lc = lua.new_usertype<fuser>("fuser", "add", &fuser::add, "add2", &fuser::add2);
lua.safe_script(
"a = fuser:new()\n"
"b = a:add(1)\n"
"c = a:add2(1)\n");
sol::object a = lua.get<sol::object>("a");
sol::object b = lua.get<sol::object>("b");
sol::object c = lua.get<sol::object>("c");
REQUIRE((a.is<sol::userdata_value>()));
auto atype = a.get_type();
auto btype = b.get_type();
auto ctype = c.get_type();
REQUIRE((atype == sol::type::userdata));
REQUIRE((btype == sol::type::number));
REQUIRE((ctype == sol::type::number));
int bresult = b.as<int>();
int cresult = c.as<int>();
REQUIRE(bresult == 1);
REQUIRE(cresult == 3);
}
TEST_CASE("usertype/usertype-constructors", "Show that we can create classes from usertype and use them with multiple constructors") {
sol::state lua;
sol::constructors<sol::types<>, sol::types<int>, sol::types<int, int>> con;
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"
"u = a:add(1)\n"
"v = a:add2(1)\n"
"b = fuser:new()\n"
"w = b:add(1)\n"
"x = b:add2(1)\n"
"c = fuser.new(2, 3)\n"
"y = c:add(1)\n"
"z = c:add2(1)\n");
sol::object a = lua.get<sol::object>("a");
auto atype = a.get_type();
REQUIRE((atype == sol::type::userdata));
sol::object u = lua.get<sol::object>("u");
sol::object v = lua.get<sol::object>("v");
REQUIRE((u.as<int>() == 3));
REQUIRE((v.as<int>() == 5));
sol::object b = lua.get<sol::object>("b");
auto btype = b.get_type();
REQUIRE((btype == sol::type::userdata));
sol::object w = lua.get<sol::object>("w");
sol::object x = lua.get<sol::object>("x");
REQUIRE((w.as<int>() == 1));
REQUIRE((x.as<int>() == 3));
sol::object c = lua.get<sol::object>("c");
auto ctype = c.get_type();
REQUIRE((ctype == sol::type::userdata));
sol::object y = lua.get<sol::object>("y");
sol::object z = lua.get<sol::object>("z");
REQUIRE((y.as<int>() == 7));
REQUIRE((z.as<int>() == 9));
}
TEST_CASE("usertype/usertype-utility", "Show internal management of classes registered through new_usertype") {
sol::state lua;
lua.new_usertype<fuser>("fuser", "add", &fuser::add, "add2", &fuser::add2);
lua.safe_script(
"a = fuser.new()\n"
"b = a:add(1)\n"
"c = a:add2(1)\n");
sol::object a = lua.get<sol::object>("a");
sol::object b = lua.get<sol::object>("b");
sol::object c = lua.get<sol::object>("c");
REQUIRE((a.is<sol::userdata_value>()));
auto atype = a.get_type();
auto btype = b.get_type();
auto ctype = c.get_type();
REQUIRE((atype == sol::type::userdata));
REQUIRE((btype == sol::type::number));
REQUIRE((ctype == sol::type::number));
int bresult = b.as<int>();
int cresult = c.as<int>();
REQUIRE(bresult == 1);
REQUIRE(cresult == 3);
}
TEST_CASE("usertype/usertype-utility-derived", "usertype classes must play nice when a derived class does not overload a publically visible base function") {
sol::state lua;
lua.open_libraries(sol::lib::base);
sol::constructors<sol::types<int>> basector;
sol::usertype<Base> baseusertype = lua.new_usertype<Base>("Base", basector, "get_num", &Base::get_num);
lua.safe_script("base = Base.new(5)");
{
auto result = lua.safe_script("print(base:get_num())", sol::script_pass_on_error);
REQUIRE(result.valid());
}
sol::constructors<sol::types<int>> derivedctor;
sol::usertype<Derived> derivedusertype = lua.new_usertype<Derived>("Derived", derivedctor,
"get_num_10", &Derived::get_num_10,
"get_num", &Derived::get_num);
lua.safe_script("derived = Derived.new(7)");
lua.safe_script(
"dgn = derived:get_num()\n"
"print(dgn)");
lua.safe_script(
"dgn10 = derived:get_num_10()\n"
"print(dgn10)");
REQUIRE((lua.get<int>("dgn10") == 70));
REQUIRE((lua.get<int>("dgn") == 7));
}
TEST_CASE("usertype/self-referential usertype", "usertype classes must play nice when C++ object types are requested for C++ code") { TEST_CASE("usertype/self-referential usertype", "usertype classes must play nice when C++ object types are requested for C++ code") {
sol::state lua; sol::state lua;
lua.open_libraries(sol::lib::base); lua.open_libraries(sol::lib::base);
@ -224,178 +66,6 @@ TEST_CASE("usertype/self-referential usertype", "usertype classes must play nice
REQUIRE(result.valid()); REQUIRE(result.valid());
} }
TEST_CASE("usertype/issue-number-twenty-five", "Using pointers and references from C++ classes in Lua") {
struct test {
int x = 0;
test& set() {
x = 10;
return *this;
}
int get() {
return x;
}
test* pget() {
return this;
}
test create_get() {
return *this;
}
int fun(int xa) {
return xa * 10;
}
};
sol::state lua;
lua.open_libraries(sol::lib::base);
lua.new_usertype<test>("test", "set", &test::set, "get", &test::get, "pointer_get", &test::pget, "fun", &test::fun, "create_get", &test::create_get);
{
auto result = lua.safe_script("x = test.new()", sol::script_pass_on_error);
REQUIRE(result.valid());
}
{
auto result = lua.safe_script("assert(x:set():get() == 10)", sol::script_pass_on_error);
REQUIRE(result.valid());
}
{
auto result = lua.safe_script("y = x:pointer_get()", sol::script_pass_on_error);
REQUIRE(result.valid());
}
{
auto result = lua.safe_script("y:set():get()", sol::script_pass_on_error);
REQUIRE(result.valid());
}
{
auto result = lua.safe_script("y:fun(10)", sol::script_pass_on_error);
REQUIRE(result.valid());
}
{
auto result = lua.safe_script("x:fun(10)", sol::script_pass_on_error);
REQUIRE(result.valid());
}
{
auto result = lua.safe_script("assert(y:fun(10) == x:fun(10), '...')", sol::script_pass_on_error);
REQUIRE(result.valid());
}
{
auto result = lua.safe_script("assert(y:fun(10) == 100, '...')", sol::script_pass_on_error);
REQUIRE(result.valid());
}
{
auto result = lua.safe_script("assert(y:set():get() == y:set():get(), '...')", sol::script_pass_on_error);
REQUIRE(result.valid());
}
{
auto result = lua.safe_script("assert(y:set():get() == 10, '...')", sol::script_pass_on_error);
REQUIRE(result.valid());
}
}
TEST_CASE("usertype/issue-number-thirty-five", "using value types created from lua-called C++ code, fixing user-defined types with constructors") {
sol::state lua;
lua.open_libraries(sol::lib::base);
sol::constructors<sol::types<float, float, float>> ctor;
sol::usertype<Vec> udata = lua.new_usertype<Vec>("Vec", ctor, "normalized", &Vec::normalized, "length", &Vec::length);
{
auto result = lua.safe_script(
"v = Vec.new(1, 2, 3)\n"
"print(v:length())");
REQUIRE(result.valid());
}
{
auto result = lua.safe_script(
"v = Vec.new(1, 2, 3)\n"
"print(v:normalized():length())");
REQUIRE(result.valid());
}
}
TEST_CASE("usertype/lua-stored-usertype", "ensure usertype values can be stored without keeping usertype object alive") {
sol::state lua;
lua.open_libraries(sol::lib::base);
{
sol::constructors<sol::types<float, float, float>> ctor;
sol::usertype<Vec> udata = lua.new_usertype<Vec>("Vec",
ctor,
"normalized", &Vec::normalized,
"length", &Vec::length);
// usertype dies, but still usable in lua!
}
{
auto result = lua.safe_script(
"collectgarbage()\n"
"v = Vec.new(1, 2, 3)\n"
"print(v:length())");
REQUIRE(result.valid());
}
{
auto result = lua.safe_script(
"v = Vec.new(1, 2, 3)\n"
"print(v:normalized():length())");
REQUIRE(result.valid());
}
}
TEST_CASE("usertype/member-variables", "allow table-like accessors to behave as member variables for usertype") {
sol::state lua;
lua.open_libraries(sol::lib::base);
sol::constructors<sol::types<float, float, float>> 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);
REQUIRE_NOTHROW(lua.safe_script(
"v = Vec.new(1, 2, 3)\n"
"v2 = Vec.new(0, 1, 0)\n"
"print(v:length())\n"));
REQUIRE_NOTHROW(lua.safe_script(
"v.x = 2\n"
"v2.y = 2\n"
"print(v.x, v.y, v.z)\n"
"print(v2.x, v2.y, v2.z)\n"));
REQUIRE_NOTHROW(lua.safe_script(
"assert(v.x == 2)\n"
"assert(v2.x == 0)\n"
"assert(v2.y == 2)\n"));
REQUIRE_NOTHROW(lua.safe_script(
"v.x = 3\n"
"local x = v.x\n"
"assert(x == 3)\n"));
struct breaks {
sol::function f;
};
lua.open_libraries(sol::lib::base);
lua.set("b", breaks());
lua.new_usertype<breaks>("breaks",
"f", &breaks::f);
breaks& b = lua["b"];
{
auto result = lua.safe_script("b.f = function () print('BARK!') end", sol::script_pass_on_error);
REQUIRE(result.valid());
}
{
auto result = lua.safe_script("b.f()", sol::script_pass_on_error);
REQUIRE(result.valid());
}
REQUIRE_NOTHROW(b.f());
}
TEST_CASE("usertype/nonmember-functions", "let users set non-member functions that take unqualified T as first parameter to usertype") { TEST_CASE("usertype/nonmember-functions", "let users set non-member functions that take unqualified T as first parameter to usertype") {
sol::state lua; sol::state lua;
lua.open_libraries(sol::lib::base); lua.open_libraries(sol::lib::base);
@ -425,354 +95,6 @@ TEST_CASE("usertype/nonmember-functions", "let users set non-member functions th
std::cout << "----- end of 1" << std::endl; std::cout << "----- end of 1" << std::endl;
} }
TEST_CASE("regressions/one", "issue number 48") {
sol::state lua;
lua.new_usertype<vars>("vars",
"boop", &vars::boop);
auto code =
"beep = vars.new()\n"
"beep.boop = 1";
auto result1 = lua.safe_script(code, sol::script_pass_on_error);
REQUIRE(result1.valid());
// test for segfault
auto my_var = lua.get<vars>("beep");
auto& my_var_ref = lua.get<vars>("beep");
auto* my_var_ptr = lua.get<vars*>("beep");
REQUIRE(my_var.boop == 1);
REQUIRE(my_var_ref.boop == 1);
REQUIRE(my_var_ptr->boop == 1);
REQUIRE(std::addressof(my_var_ref) == my_var_ptr);
std::cout << "----- end of 3" << std::endl;
}
TEST_CASE("usertype/get-set-references", "properly get and set with std::ref semantics. Note that to get, we must not use Unqualified<T> on the type...") {
std::cout << "----- in 4" << std::endl;
sol::state lua;
lua.new_usertype<vars>("vars",
"boop", &vars::boop);
vars var{};
vars rvar{};
std::cout << "setting beep" << std::endl;
lua.set("beep", var);
std::cout << "setting rbeep" << std::endl;
lua.set("rbeep", std::ref(rvar));
std::cout << "getting my_var" << std::endl;
auto& my_var = lua.get<vars>("beep");
std::cout << "setting rbeep" << std::endl;
auto& ref_var = lua.get<std::reference_wrapper<vars>>("rbeep");
vars& proxy_my_var = lua["beep"];
std::reference_wrapper<vars> proxy_ref_var = lua["rbeep"];
var.boop = 2;
rvar.boop = 5;
// Was return as a value: var must be diferent from "beep"
REQUIRE_FALSE(std::addressof(var) == std::addressof(my_var));
REQUIRE_FALSE(std::addressof(proxy_my_var) == std::addressof(var));
REQUIRE((my_var.boop == 0));
REQUIRE(var.boop != my_var.boop);
REQUIRE(std::addressof(ref_var) == std::addressof(rvar));
REQUIRE(std::addressof(proxy_ref_var.get()) == std::addressof(rvar));
REQUIRE(rvar.boop == 5);
REQUIRE(rvar.boop == ref_var.boop);
std::cout << "----- end of 4" << std::endl;
}
TEST_CASE("usertype/const-pointer", "Make sure const pointers can be taken") {
struct A_x {
int x = 201;
};
struct B_foo {
int foo(const A_x* a) {
return a->x;
};
};
sol::state lua;
lua.new_usertype<B_foo>("B",
"foo", &B_foo::foo);
lua.set("a", A_x());
lua.set("b", B_foo());
lua.safe_script("x = b:foo(a)");
int x = lua["x"];
REQUIRE(x == 201);
std::cout << "----- end of 6" << std::endl;
}
TEST_CASE("usertype/overloading", "Check if overloading works properly for usertypes") {
struct woof {
int var;
int func(int x) {
return var + x;
}
double func2(int x, int y) {
return var + x + y + 0.5;
}
std::string func2s(int x, std::string y) {
return y + " " + std::to_string(x);
}
};
sol::state lua;
lua.open_libraries(sol::lib::base);
lua.new_usertype<woof>("woof",
"var", &woof::var,
"func", sol::overload(&woof::func, &woof::func2, &woof::func2s));
const std::string bark_58 = "bark 58";
REQUIRE_NOTHROW(lua.safe_script(
"r = woof:new()\n"
"a = r:func(1)\n"
"b = r:func(1, 2)\n"
"c = r:func(58, 'bark')\n"));
REQUIRE((lua["a"] == 1));
REQUIRE((lua["b"] == 3.5));
REQUIRE((lua["c"] == bark_58));
auto result = lua.safe_script("r:func(1,2,'meow')", sol::script_pass_on_error);
REQUIRE_FALSE(result.valid());
std::cout << "----- end of 7" << std::endl;
}
TEST_CASE("usertype/overloading_values", "ensure overloads handle properly") {
struct overloading_test {
int print(int i) {
INFO("Integer print: " << i);
return 500 + i;
}
int print() {
INFO("No param print.");
return 500;
}
};
sol::state lua;
lua.new_usertype<overloading_test>("overloading_test", sol::constructors<>(),
"print", sol::overload(static_cast<int (overloading_test::*)(int)>(&overloading_test::print), static_cast<int (overloading_test::*)()>(&overloading_test::print)),
"print2", sol::overload(static_cast<int (overloading_test::*)()>(&overloading_test::print), static_cast<int (overloading_test::*)(int)>(&overloading_test::print)));
lua.set("test", overloading_test());
sol::function f0_0 = lua.load("return test:print()");
sol::function f0_1 = lua.load("return test:print2()");
sol::function f1_0 = lua.load("return test:print(24)");
sol::function f1_1 = lua.load("return test:print2(24)");
int res = f0_0();
int res2 = f0_1();
int res3 = f1_0();
int res4 = f1_1();
REQUIRE(res == 500);
REQUIRE(res2 == 500);
REQUIRE(res3 == 524);
REQUIRE(res4 == 524);
std::cout << "----- end of 8" << std::endl;
}
TEST_CASE("usertype/reference-and-constness", "Make sure constness compiles properly and errors out at runtime") {
struct bark {
int var = 50;
};
struct woof {
bark b;
};
struct nested {
const int f = 25;
};
struct outer {
nested n;
};
sol::state lua;
lua.new_usertype<woof>("woof",
"b", &woof::b);
lua.new_usertype<bark>("bark",
"var", &bark::var);
lua.new_usertype<outer>("outer",
"n", &outer::n);
lua.set("w", woof());
lua.set("n", nested());
lua.set("o", outer());
lua.set("f", sol::c_call<decltype(&nested::f), &nested::f>);
lua.safe_script(R"(
x = w.b
x.var = 20
val = w.b.var == x.var
v = f(n);
)");
woof& w = lua["w"];
bark& x = lua["x"];
nested& n = lua["n"];
int v = lua["v"];
bool val = lua["val"];
// enforce reference semantics
REQUIRE(std::addressof(w.b) == std::addressof(x));
REQUIRE(n.f == 25);
REQUIRE(v == 25);
REQUIRE(val);
{
auto result = lua.safe_script("f(n, 50)", sol::script_pass_on_error);
REQUIRE_FALSE(result.valid());
}
{
auto result = lua.safe_script("o.n = 25", sol::script_pass_on_error);
REQUIRE_FALSE(result.valid());
}
}
TEST_CASE("usertype/safety", "crash with an exception -- not a segfault -- on bad userdata calls") {
class Test {
public:
void sayHello() {
std::cout << "Hey\n";
}
};
sol::state lua;
lua.new_usertype<Test>("Test", "sayHello", &Test::sayHello);
static const std::string code = R"(
local t = Test.new()
t:sayHello() --Works fine
t.sayHello() --Uh oh.
)";
auto result = lua.safe_script(code, sol::script_pass_on_error);
REQUIRE_FALSE(result.valid());
}
TEST_CASE("usertype/call_constructor", "make sure lua types can be constructed with function call constructors") {
sol::state lua;
lua.open_libraries(sol::lib::base);
lua.new_usertype<thing>("thing",
"v", &thing::v, sol::call_constructor, sol::constructors<sol::types<>, sol::types<int>>());
lua.safe_script(R"(
t = thing(256)
)");
thing& y = lua["t"];
INFO(y.v);
REQUIRE(y.v == 256);
}
TEST_CASE("usertype/call_constructor-factories", "make sure tables can be passed to factory-based call constructors") {
sol::state lua;
lua.open_libraries();
lua.new_usertype<matrix_xf>("mat",
sol::call_constructor, sol::factories(&matrix_xf::from_lua_table));
lua.safe_script("m = mat{ {1.1, 2.2} }");
lua.new_usertype<matrix_xi>("mati",
sol::call_constructor, sol::factories(&matrix_xi::from_lua_table));
lua.safe_script("mi = mati{ {1, 2} }");
matrix_xf& m = lua["m"];
REQUIRE(m.a == 1.1f);
REQUIRE(m.b == 2.2f);
matrix_xi& mi = lua["mi"];
REQUIRE(mi.a == 1);
REQUIRE(mi.b == 2);
}
TEST_CASE("usertype/call_constructor_2", "prevent metatable regression") {
class class01 {
public:
int x = 57;
class01() {
}
};
class class02 {
public:
int x = 50;
class02() {
}
class02(const class01& other)
: x(other.x) {
}
};
sol::state lua;
lua.new_usertype<class01>("class01",
sol::call_constructor, sol::constructors<sol::types<>, sol::types<const class01&>>());
lua.new_usertype<class02>("class02",
sol::call_constructor, sol::constructors<sol::types<>, sol::types<const class02&>, sol::types<const class01&>>());
REQUIRE_NOTHROW(lua.safe_script(R"(
x = class01()
y = class02(x)
)"));
class02& y = lua["y"];
REQUIRE(y.x == 57);
}
TEST_CASE("usertype/blank_constructor", "make sure lua types cannot be constructed with arguments if a blank / empty constructor is provided") {
sol::state lua;
lua.open_libraries(sol::lib::base);
lua.new_usertype<thing>("thing",
"v", &thing::v, sol::call_constructor, sol::constructors<>());
auto result = lua.safe_script("t = thing(256)", sol::script_pass_on_error);
REQUIRE_FALSE(result.valid());
}
TEST_CASE("usertype/no_constructor", "make sure lua types cannot be constructed if a blank / empty constructor is provided") {
SECTION("order1") {
sol::state lua;
lua.open_libraries(sol::lib::base);
lua.new_usertype<thing>("thing",
"v", &thing::v,
sol::call_constructor, sol::no_constructor);
auto result = lua.safe_script("t = thing()", sol::script_pass_on_error);
REQUIRE_FALSE(result.valid());
}
SECTION("order2") {
sol::state lua;
lua.open_libraries(sol::lib::base);
lua.new_usertype<thing>("thing",
sol::call_constructor, sol::no_constructor,
"v", &thing::v);
auto result = lua.safe_script("t = thing.new()", sol::script_pass_on_error);
REQUIRE_FALSE(result.valid());
}
SECTION("new no_constructor") {
sol::state lua;
lua.open_libraries(sol::lib::base);
lua.new_usertype<thing>("thing",
sol::meta_function::construct, sol::no_constructor);
auto result = lua.safe_script("t = thing.new()", sol::script_pass_on_error);
REQUIRE_FALSE(result.valid());
}
SECTION("call no_constructor") {
sol::state lua;
lua.open_libraries(sol::lib::base);
lua.new_usertype<thing>("thing",
sol::call_constructor, sol::no_constructor);
auto result = lua.safe_script("t = thing()", sol::script_pass_on_error);
REQUIRE_FALSE(result.valid());
}
}
TEST_CASE("usertype/abstract-base-class", "Ensure that abstract base classes and such can be registered") { TEST_CASE("usertype/abstract-base-class", "Ensure that abstract base classes and such can be registered") {
sol::state lua; sol::state lua;
lua.new_usertype<abstract_A>("A", "a", &abstract_A::a); lua.new_usertype<abstract_A>("A", "a", &abstract_A::a);

View File

@ -23,6 +23,8 @@
#include "sol_test.hpp" #include "sol_test.hpp"
#include "common_classes.hpp"
#include <catch.hpp> #include <catch.hpp>
#include <iostream> #include <iostream>
@ -257,3 +259,31 @@ TEST_CASE("inheritance/runtime multi base", "test that multiple bases all work a
runtime_A& a_obj = lua["obj"]; runtime_A& a_obj = lua["obj"];
REQUIRE(a_obj.a == 5); REQUIRE(a_obj.a == 5);
} }
TEST_CASE("inheritance/usertype derived non-hiding", "usertype classes must play nice when a derived class does not overload a publically visible base function") {
sol::state lua;
lua.open_libraries(sol::lib::base);
sol::constructors<sol::types<int>> basector;
sol::usertype<Base> baseusertype = lua.new_usertype<Base>("Base", basector, "get_num", &Base::get_num);
lua.safe_script("base = Base.new(5)");
{
auto result = lua.safe_script("print(base:get_num())", sol::script_pass_on_error);
REQUIRE(result.valid());
}
sol::constructors<sol::types<int>> derivedctor;
sol::usertype<Derived> derivedusertype
= lua.new_usertype<Derived>("Derived", derivedctor, "get_num_10", &Derived::get_num_10, "get_num", &Derived::get_num);
lua.safe_script("derived = Derived.new(7)");
lua.safe_script(
"dgn = derived:get_num()\n"
"print(dgn)");
lua.safe_script(
"dgn10 = derived:get_num_10()\n"
"print(dgn10)");
REQUIRE((lua.get<int>("dgn10") == 70));
REQUIRE((lua.get<int>("dgn") == 7));
}

View File

@ -0,0 +1,126 @@
// sol3
// The MIT License (MIT)
// Copyright (c) 2013-2018 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "sol_test.hpp"
#include "common_classes.hpp"
#include <catch.hpp>
TEST_CASE("usertype/member-variables", "allow table-like accessors to behave as member variables for usertype") {
sol::state lua;
lua.open_libraries(sol::lib::base);
sol::constructors<sol::types<float, float, float>> 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);
REQUIRE_NOTHROW(
lua.safe_script("v = Vec.new(1, 2, 3)\n"
"v2 = Vec.new(0, 1, 0)\n"
"print(v:length())\n"));
REQUIRE_NOTHROW(
lua.safe_script("v.x = 2\n"
"v2.y = 2\n"
"print(v.x, v.y, v.z)\n"
"print(v2.x, v2.y, v2.z)\n"));
REQUIRE_NOTHROW(
lua.safe_script("assert(v.x == 2)\n"
"assert(v2.x == 0)\n"
"assert(v2.y == 2)\n"));
REQUIRE_NOTHROW(
lua.safe_script("v.x = 3\n"
"local x = v.x\n"
"assert(x == 3)\n"));
struct breaks {
sol::function f;
};
lua.open_libraries(sol::lib::base);
lua.set("b", breaks());
lua.new_usertype<breaks>("breaks", "f", &breaks::f);
breaks& b = lua["b"];
{
auto result = lua.safe_script("b.f = function () print('BARK!') end", sol::script_pass_on_error);
REQUIRE(result.valid());
}
{
auto result = lua.safe_script("b.f()", sol::script_pass_on_error);
REQUIRE(result.valid());
}
REQUIRE_NOTHROW(b.f());
}
TEST_CASE("usertype/reference-and-constness", "Make sure constness compiles properly and errors out at runtime") {
struct bark {
int var = 50;
};
struct woof {
bark b;
};
struct nested {
const int f = 25;
};
struct outer {
nested n;
};
sol::state lua;
lua.new_usertype<woof>("woof", "b", &woof::b);
lua.new_usertype<bark>("bark", "var", &bark::var);
lua.new_usertype<outer>("outer", "n", &outer::n);
lua.set("w", woof());
lua.set("n", nested());
lua.set("o", outer());
lua.set("f", sol::c_call<decltype(&nested::f), &nested::f>);
lua.safe_script(R"(
x = w.b
x.var = 20
val = w.b.var == x.var
v = f(n);
)");
woof& w = lua["w"];
bark& x = lua["x"];
nested& n = lua["n"];
int v = lua["v"];
bool val = lua["val"];
// enforce reference semantics
REQUIRE(std::addressof(w.b) == std::addressof(x));
REQUIRE(n.f == 25);
REQUIRE(v == 25);
REQUIRE(val);
{
auto result = lua.safe_script("f(n, 50)", sol::script_pass_on_error);
REQUIRE_FALSE(result.valid());
}
{
auto result = lua.safe_script("o.n = 25", sol::script_pass_on_error);
REQUIRE_FALSE(result.valid());
}
}

View File

@ -0,0 +1,89 @@
// sol3
// The MIT License (MIT)
// Copyright (c) 2013-2018 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "sol_test.hpp"
#include "common_classes.hpp"
#include <catch.hpp>
struct overloading_test {
int print(int i) {
INFO("Integer print: " << i);
return 500 + i;
}
int print() {
INFO("No param print.");
return 500;
}
};
TEST_CASE("usertype/overloading", "Check if overloading works properly for usertypes") {
sol::state lua;
lua.open_libraries(sol::lib::base);
lua.new_usertype<woof>("woof", "var", &woof::var, "func", sol::overload(&woof::func, &woof::func2, &woof::func2s));
const std::string bark_58 = "bark 58";
REQUIRE_NOTHROW(
lua.safe_script("r = woof:new()\n"
"a = r:func(1)\n"
"b = r:func(1, 2)\n"
"c = r:func(58, 'bark')\n"));
REQUIRE((lua["a"] == 1));
REQUIRE((lua["b"] == 3.5));
REQUIRE((lua["c"] == bark_58));
auto result = lua.safe_script("r:func(1,2,'meow')", sol::script_pass_on_error);
REQUIRE_FALSE(result.valid());
std::cout << "----- end of 7" << std::endl;
}
TEST_CASE("usertype/overloading_values", "ensure overloads handle properly") {
sol::state lua;
lua.new_usertype<overloading_test>("overloading_test",
sol::constructors<>(),
"print",
sol::overload(
static_cast<int (overloading_test::*)(int)>(&overloading_test::print), static_cast<int (overloading_test::*)()>(&overloading_test::print)),
"print2",
sol::overload(
static_cast<int (overloading_test::*)()>(&overloading_test::print), static_cast<int (overloading_test::*)(int)>(&overloading_test::print)));
lua.set("test", overloading_test());
sol::function f0_0 = lua.load("return test:print()");
sol::function f0_1 = lua.load("return test:print2()");
sol::function f1_0 = lua.load("return test:print(24)");
sol::function f1_1 = lua.load("return test:print2(24)");
int res = f0_0();
int res2 = f0_1();
int res3 = f1_0();
int res4 = f1_1();
REQUIRE(res == 500);
REQUIRE(res2 == 500);
REQUIRE(res3 == 524);
REQUIRE(res4 == 524);
std::cout << "----- end of 8" << std::endl;
}

View File

@ -22,6 +22,7 @@
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "sol_test.hpp" #include "sol_test.hpp"
#include "common_classes.hpp"
#include <catch.hpp> #include <catch.hpp>
@ -106,7 +107,25 @@ TEST_CASE("utility/variant", "test that variant can be round-tripped") {
#endif // C++17 #endif // C++17
} }
TEST_CASE("utility/optional", "test that shit optional can be round-tripped") { TEST_CASE("utility/optional-conversion", "test that regular optional will properly catch certain types") {
sol::state lua;
lua.open_libraries(sol::lib::base);
lua.new_usertype<vars>("vars");
lua["test"] = [](sol::optional<vars> x) {
return static_cast<bool>(x);
};
const auto result = lua.safe_script(R"(
assert(test(vars:new()))
assert(not test(3))
assert(not test(nil))
)", sol::script_pass_on_error);
REQUIRE(result.valid());
}
TEST_CASE("utility/std optional", "test that shit optional can be round-tripped") {
#ifdef SOL_CXX17_FEATURES #ifdef SOL_CXX17_FEATURES
SECTION("okay") { SECTION("okay") {
sol::state lua; sol::state lua;