diff --git a/cmake/Modules/FindLuaBuild/LuaVanilla.cmake b/cmake/Modules/FindLuaBuild/LuaVanilla.cmake index 75d77d67..5ac6a5c9 100644 --- a/cmake/Modules/FindLuaBuild/LuaVanilla.cmake +++ b/cmake/Modules/FindLuaBuild/LuaVanilla.cmake @@ -35,10 +35,12 @@ include(Common/Core) set(LUA_VANILLA_5.1_LATEST_VERSION 5.1.5) set(LUA_VANILLA_5.2_LATEST_VERSION 5.2.4) set(LUA_VANILLA_5.3_LATEST_VERSION 5.3.5) -set(LUA_VANILLA_5.4_LATEST_VERSION 5.4.0) +set(LUA_VANILLA_5.4_LATEST_VERSION 5.4.1) # exact version, coming from CI: pull directly from Lua and use external project to build # list of known md5 / sha1: must update when there are changes +set(LUA_VANILLA_MD5_5.4.1 1d575faef1c907292edd79e7a2784d30) +set(LUA_VANILLA_SHA1_5.4.1 88961e7d4fda58ca2c6163938fd48db8880e803d) set(LUA_VANILLA_MD5_5.4.0 dbf155764e5d433fc55ae80ea7060b60) set(LUA_VANILLA_SHA1_5.4.0 8cdbffa8a214a23d190d7c45f38c19518ae62e89) set(LUA_VANILLA_MD5_5.3.5 4f4b4f323fd3514a68e0ab3da8ce3455) diff --git a/examples/source/coroutine_multiple_stacks.cpp b/examples/source/coroutine_multiple_stacks.cpp new file mode 100644 index 00000000..c8b6d5ab --- /dev/null +++ b/examples/source/coroutine_multiple_stacks.cpp @@ -0,0 +1,49 @@ +#define SOL_ALL_SAFETIES_ON 1 +#include + +#include +#include + +int main () { + std::cout << "=== coroutine - multple threads ===" << std::endl; + + sol::state lua; + lua.open_libraries(sol::lib::base, sol::lib::package, sol::lib::coroutine); + + lua["print"] = [](sol::object v){ + std::cout << v.as() << std::endl; + }; + lua["cyield"] = sol::yielding([](){ + std::cout << "YIELDING" << std::endl; + }); + + // notice the new threads! + sol::thread thread1 = sol::thread::create(lua); + sol::thread thread2 = sol::thread::create(lua); + + // notice we load it FROM the new "execution stack" + // we need it to have thread1's stack perspective + sol::coroutine co1 = thread1.state().load(R"( + print("AA : Step 1") + cyield() + print("AA : Step 2") + )"); + // call first coroutine here + co1(); + + // notice we load it FROM the new "execution stack" + // we need it to have thread2's stack and perspective + sol::coroutine co2 = thread2.state().load(R"( + print("BB : Step 1") + cyield() + print("BB : Step 2") + )"); + + // run the other coroutine + co2(); + co1(); + // tada! they run on + // independent stacks + + return 0; +} diff --git a/include/sol/bind_traits.hpp b/include/sol/bind_traits.hpp index fb89ab8b..ba8beefa 100644 --- a/include/sol/bind_traits.hpp +++ b/include/sol/bind_traits.hpp @@ -30,26 +30,20 @@ namespace sol { namespace meta { namespace meta_detail { - - template - struct check_deducible_signature { - struct nat {}; - template - static auto test(int) -> decltype(&G::operator(), void()); - template - static auto test(...) -> nat; - - using type = std::is_void(0))>; - }; + template + using detect_deducible_signature = decltype(&F::operator(), void()); } // namespace meta_detail - template - struct has_deducible_signature : meta_detail::check_deducible_signature::type {}; + template + using call_operator_deducible = typename is_detected::type; + + template + constexpr inline bool call_operator_deducible_v = call_operator_deducible::value; namespace meta_detail { template - struct void_tuple_element : meta::tuple_element {}; + struct void_tuple_element : meta::tuple_element { }; template struct void_tuple_element> { @@ -84,234 +78,234 @@ namespace sol { namespace meta { using arg_at = void_tuple_element_t; }; - template ::value> - struct fx_traits : basic_traits {}; + template ::value> + struct fx_traits : public basic_traits { }; // Free Functions template - struct fx_traits : basic_traits { + struct fx_traits : public basic_traits { typedef R (*function_pointer_type)(Args...); }; template - struct fx_traits : basic_traits { + struct fx_traits : public basic_traits { typedef R (*function_pointer_type)(Args...); }; template - struct fx_traits : basic_traits { + struct fx_traits : public basic_traits { typedef R (*function_pointer_type)(Args..., ...); }; template - struct fx_traits : basic_traits { + struct fx_traits : public basic_traits { typedef R (*function_pointer_type)(Args..., ...); }; // Member Functions /* C-Style Variadics */ template - struct fx_traits : basic_traits { + struct fx_traits : public basic_traits { typedef R (T::*function_pointer_type)(Args...); }; template - struct fx_traits : basic_traits { + struct fx_traits : public basic_traits { typedef R (T::*function_pointer_type)(Args..., ...); }; /* Const Volatile */ template - struct fx_traits : basic_traits { + struct fx_traits : public basic_traits { typedef R (T::*function_pointer_type)(Args...) const; }; template - struct fx_traits : basic_traits { + struct fx_traits : public basic_traits { typedef R (T::*function_pointer_type)(Args..., ...) const; }; template - struct fx_traits : basic_traits { + struct fx_traits : public basic_traits { typedef R (T::*function_pointer_type)(Args...) const volatile; }; template - struct fx_traits : basic_traits { + struct fx_traits : public basic_traits { typedef R (T::*function_pointer_type)(Args..., ...) const volatile; }; /* Member Function Qualifiers */ template - struct fx_traits : basic_traits { + struct fx_traits : public basic_traits { typedef R (T::*function_pointer_type)(Args...) &; }; template - struct fx_traits : basic_traits { + struct fx_traits : public basic_traits { typedef R (T::*function_pointer_type)(Args..., ...) &; }; template - struct fx_traits : basic_traits { + struct fx_traits : public basic_traits { typedef R (T::*function_pointer_type)(Args...) const&; }; template - struct fx_traits : basic_traits { + struct fx_traits : public basic_traits { typedef R (T::*function_pointer_type)(Args..., ...) const&; }; template - struct fx_traits : basic_traits { + struct fx_traits : public basic_traits { typedef R (T::*function_pointer_type)(Args...) const volatile&; }; template - struct fx_traits : basic_traits { + struct fx_traits : public basic_traits { typedef R (T::*function_pointer_type)(Args..., ...) const volatile&; }; template - struct fx_traits : basic_traits { + struct fx_traits : public basic_traits { typedef R (T::*function_pointer_type)(Args...) &&; }; template - struct fx_traits : basic_traits { + struct fx_traits : public basic_traits { typedef R (T::*function_pointer_type)(Args..., ...) &&; }; template - struct fx_traits : basic_traits { + struct fx_traits : public basic_traits { typedef R (T::*function_pointer_type)(Args...) const&&; }; template - struct fx_traits : basic_traits { + struct fx_traits : public basic_traits { typedef R (T::*function_pointer_type)(Args..., ...) const&&; }; template - struct fx_traits : basic_traits { + struct fx_traits : public basic_traits { typedef R (T::*function_pointer_type)(Args...) const volatile&&; }; template - struct fx_traits : basic_traits { + struct fx_traits : public basic_traits { typedef R (T::*function_pointer_type)(Args..., ...) const volatile&&; }; #if SOL_IS_ON(SOL_USE_NOEXCEPT_FUNCTION_TYPE_I_) template - struct fx_traits : basic_traits { + struct fx_traits : public basic_traits { typedef R (*function_pointer_type)(Args...) noexcept; }; template - struct fx_traits : basic_traits { + struct fx_traits : public basic_traits { typedef R (*function_pointer_type)(Args...) noexcept; }; template - struct fx_traits : basic_traits { + struct fx_traits : public basic_traits { typedef R (*function_pointer_type)(Args..., ...) noexcept; }; template - struct fx_traits : basic_traits { + struct fx_traits : public basic_traits { typedef R (*function_pointer_type)(Args..., ...) noexcept; }; template - struct fx_traits : basic_traits { + struct fx_traits : public basic_traits { typedef R (T::*function_pointer_type)(Args...) noexcept; }; template - struct fx_traits : basic_traits { + struct fx_traits : public basic_traits { typedef R (T::*function_pointer_type)(Args..., ...) noexcept; }; /* Const Volatile */ template - struct fx_traits : basic_traits { + struct fx_traits : public basic_traits { typedef R (T::*function_pointer_type)(Args...) const noexcept; }; template - struct fx_traits : basic_traits { + struct fx_traits : public basic_traits { typedef R (T::*function_pointer_type)(Args..., ...) const noexcept; }; template - struct fx_traits : basic_traits { + struct fx_traits : public basic_traits { typedef R (T::*function_pointer_type)(Args...) const volatile noexcept; }; template - struct fx_traits : basic_traits { + struct fx_traits : public basic_traits { typedef R (T::*function_pointer_type)(Args..., ...) const volatile noexcept; }; template - struct fx_traits : basic_traits { + struct fx_traits : public basic_traits { typedef R (T::*function_pointer_type)(Args...) & noexcept; }; template - struct fx_traits : basic_traits { + struct fx_traits : public basic_traits { typedef R (T::*function_pointer_type)(Args..., ...) & noexcept; }; template - struct fx_traits : basic_traits { + struct fx_traits : public basic_traits { typedef R (T::*function_pointer_type)(Args...) const& noexcept; }; template - struct fx_traits : basic_traits { + struct fx_traits : public basic_traits { typedef R (T::*function_pointer_type)(Args..., ...) const& noexcept; }; template - struct fx_traits : basic_traits { + struct fx_traits : public basic_traits { typedef R (T::*function_pointer_type)(Args...) const volatile& noexcept; }; template - struct fx_traits : basic_traits { + struct fx_traits : public basic_traits { typedef R (T::*function_pointer_type)(Args..., ...) const volatile& noexcept; }; template - struct fx_traits : basic_traits { + struct fx_traits : public basic_traits { typedef R (T::*function_pointer_type)(Args...) && noexcept; }; template - struct fx_traits : basic_traits { + struct fx_traits : public basic_traits { typedef R (T::*function_pointer_type)(Args..., ...) && noexcept; }; template - struct fx_traits : basic_traits { + struct fx_traits : public basic_traits { typedef R (T::*function_pointer_type)(Args...) const&& noexcept; }; template - struct fx_traits : basic_traits { + struct fx_traits : public basic_traits { typedef R (T::*function_pointer_type)(Args..., ...) const&& noexcept; }; template - struct fx_traits : basic_traits { + struct fx_traits : public basic_traits { typedef R (T::*function_pointer_type)(Args...) const volatile&& noexcept; }; template - struct fx_traits : basic_traits { + struct fx_traits : public basic_traits { typedef R (T::*function_pointer_type)(Args..., ...) const volatile&& noexcept; }; @@ -319,194 +313,192 @@ namespace sol { namespace meta { #if SOL_IS_ON(SOL_COMPILER_VCXX_I_) && SOL_IS_ON(SOL_PLATFORM_X86_I_) template - struct fx_traits : basic_traits { + struct fx_traits : public basic_traits { typedef R(__stdcall* function_pointer_type)(Args...); }; template - struct fx_traits : basic_traits { + struct fx_traits : public basic_traits { typedef R(__stdcall* function_pointer_type)(Args...); }; template - struct fx_traits : basic_traits { + struct fx_traits : public basic_traits { typedef R (__stdcall T::*function_pointer_type)(Args...); }; /* Const Volatile */ template - struct fx_traits : basic_traits { + struct fx_traits : public basic_traits { typedef R (__stdcall T::*function_pointer_type)(Args...) const; }; template - struct fx_traits : basic_traits { + struct fx_traits : public basic_traits { typedef R (__stdcall T::*function_pointer_type)(Args...) const volatile; }; /* Member Function Qualifiers */ template - struct fx_traits : basic_traits { + struct fx_traits : public basic_traits { typedef R (__stdcall T::*function_pointer_type)(Args...) &; }; template - struct fx_traits : basic_traits { + struct fx_traits : public basic_traits { typedef R (__stdcall T::*function_pointer_type)(Args...) const&; }; template - struct fx_traits : basic_traits { + struct fx_traits : public basic_traits { typedef R (__stdcall T::*function_pointer_type)(Args...) const volatile&; }; template - struct fx_traits : basic_traits { + struct fx_traits : public basic_traits { typedef R (__stdcall T::*function_pointer_type)(Args...) &&; }; template - struct fx_traits : basic_traits { + struct fx_traits : public basic_traits { typedef R (__stdcall T::*function_pointer_type)(Args...) const&&; }; template - struct fx_traits : basic_traits { + struct fx_traits : public basic_traits { typedef R (__stdcall T::*function_pointer_type)(Args...) const volatile&&; }; #if SOL_IS_ON(SOL_USE_NOEXCEPT_FUNCTION_TYPE_I_) template - struct fx_traits : basic_traits { + struct fx_traits : public basic_traits { typedef R(__stdcall* function_pointer_type)(Args...) noexcept; }; template - struct fx_traits : basic_traits { + struct fx_traits : public basic_traits { typedef R(__stdcall* function_pointer_type)(Args...) noexcept; }; /* __stdcall cannot be applied to functions with varargs*/ /*template - struct fx_traits<__stdcall R(Args..., ...) noexcept, false> : basic_traits { + struct fx_traits<__stdcall R(Args..., ...) noexcept, false> : public basic_traits { typedef R(__stdcall* function_pointer_type)(Args..., ...) noexcept; }; template - struct fx_traits : basic_traits { + struct fx_traits : public basic_traits { typedef R(__stdcall* function_pointer_type)(Args..., ...) noexcept; };*/ template - struct fx_traits : basic_traits { + struct fx_traits : public basic_traits { typedef R (__stdcall T::*function_pointer_type)(Args...) noexcept; }; /* __stdcall does not work with varargs */ /*template - struct fx_traits : basic_traits { + struct fx_traits : public basic_traits { typedef R (__stdcall T::*function_pointer_type)(Args..., ...) noexcept; };*/ /* Const Volatile */ template - struct fx_traits : basic_traits { + struct fx_traits : public basic_traits { typedef R (__stdcall T::*function_pointer_type)(Args...) const noexcept; }; /* __stdcall does not work with varargs */ /*template - struct fx_traits : basic_traits { + struct fx_traits : public basic_traits { typedef R (__stdcall T::*function_pointer_type)(Args..., ...) const noexcept; };*/ template - struct fx_traits : basic_traits { + struct fx_traits : public basic_traits { typedef R (__stdcall T::*function_pointer_type)(Args...) const volatile noexcept; }; /* __stdcall does not work with varargs */ /*template - struct fx_traits : basic_traits { + struct fx_traits : public basic_traits { typedef R (__stdcall T::*function_pointer_type)(Args..., ...) const volatile noexcept; };*/ template - struct fx_traits : basic_traits { + struct fx_traits : public basic_traits { typedef R (__stdcall T::*function_pointer_type)(Args...) & noexcept; }; /* __stdcall does not work with varargs */ /*template - struct fx_traits : basic_traits { + struct fx_traits : public basic_traits { typedef R (__stdcall T::*function_pointer_type)(Args..., ...) & noexcept; };*/ template - struct fx_traits : basic_traits { + struct fx_traits : public basic_traits { typedef R (__stdcall T::*function_pointer_type)(Args...) const& noexcept; }; /* __stdcall does not work with varargs */ /*template - struct fx_traits : basic_traits { + struct fx_traits : public basic_traits { typedef R (__stdcall T::*function_pointer_type)(Args..., ...) const& noexcept; };*/ template - struct fx_traits : basic_traits { + struct fx_traits : public basic_traits { typedef R (__stdcall T::*function_pointer_type)(Args...) const volatile& noexcept; }; /* __stdcall does not work with varargs */ /*template - struct fx_traits : basic_traits { + struct fx_traits : public basic_traits { typedef R (__stdcall T::*function_pointer_type)(Args..., ...) const volatile& noexcept; };*/ template - struct fx_traits : basic_traits { + struct fx_traits : public basic_traits { typedef R (__stdcall T::*function_pointer_type)(Args...) && noexcept; }; /* __stdcall does not work with varargs */ /*template - struct fx_traits : basic_traits { + struct fx_traits : public basic_traits { typedef R (__stdcall T::*function_pointer_type)(Args..., ...) && noexcept; };*/ template - struct fx_traits : basic_traits { + struct fx_traits : public basic_traits { typedef R (__stdcall T::*function_pointer_type)(Args...) const&& noexcept; }; /* __stdcall does not work with varargs */ /*template - struct fx_traits : basic_traits { + struct fx_traits : public basic_traits { typedef R (__stdcall T::*function_pointer_type)(Args..., ...) const&& noexcept; };*/ template - struct fx_traits : basic_traits { + struct fx_traits : public basic_traits { typedef R (__stdcall T::*function_pointer_type)(Args...) const volatile&& noexcept; }; /* __stdcall does not work with varargs */ /*template - struct fx_traits : basic_traits { + struct fx_traits : public basic_traits { typedef R (__stdcall T::*function_pointer_type)(Args..., ...) const volatile&& noexcept; };*/ #endif // noexcept is part of a function's type #endif // __stdcall x86 VC++ bug template - struct fx_traits - : public fx_traits::function_type, false> {}; + struct fx_traits : public fx_traits::function_type, false> { }; template ::value> - struct callable_traits - : public fx_traits> {}; + struct callable_traits : public fx_traits> { }; template struct callable_traits { @@ -532,7 +524,21 @@ namespace sol { namespace meta { } // namespace meta_detail template - struct bind_traits : meta_detail::callable_traits {}; + using bind_traits = meta_detail::callable_traits; + + namespace meta_detail { + template + struct is_probably_stateless_lambda : std::false_type { }; + + template + struct is_probably_stateless_lambda : std::is_convertible::function_type*>::type { }; + } // namespace meta_detail + + template + using is_probably_stateless_lambda = typename meta_detail::is_probably_stateless_lambda && call_operator_deducible_v>::type; + + template + inline constexpr bool is_probably_stateless_lambda_v = is_probably_stateless_lambda::value; template using function_args_t = typename bind_traits::args_list; diff --git a/include/sol/compatibility/lua_version.hpp b/include/sol/compatibility/lua_version.hpp index 0d939d0f..b1782858 100644 --- a/include/sol/compatibility/lua_version.hpp +++ b/include/sol/compatibility/lua_version.hpp @@ -125,7 +125,23 @@ // shoving exceptions through Lua and errors should // always be serialized #define SOL_PROPAGATE_EXCEPTIONS_I_ SOL_DEFAULT_OFF -#endif // LuaJIT beta 02.01.00 have better exception handling on all platforms since beta3 +#endif + +// Some configurations work with exceptions, +// but cannot catch-all everything... +#if defined(SOL_EXCEPTIONS_CATCH_ALL) + #if (SOL_EXCEPTIONS_CATCH_ALL != 0) + #define SOL_EXCEPTIONS_CATCH_ALL_I_ SOL_ON + #else + #define SOL_EXCEPTIONS_CATCH_ALL_I_ SOL_OFF + #endif +#else + #if SOL_IS_ON(SOL_USE_LUAJIT_I_) + #define SOL_EXCEPTIONS_CATCH_ALL_I_ SOL_DEFAULT_OFF + #else + #define SOL_EXCEPTIONS_CATCH_ALL_I_ SOL_DEFAULT_ON + #endif +#endif #if defined(SOL_LUAJIT_USE_EXCEPTION_TRAMPOLINE) #if (SOL_LUAJIT_USE_EXCEPTION_TRAMPOLINE != 0) diff --git a/include/sol/coroutine.hpp b/include/sol/coroutine.hpp index aad5c01c..4c6cf46f 100644 --- a/include/sol/coroutine.hpp +++ b/include/sol/coroutine.hpp @@ -105,29 +105,40 @@ namespace sol { } #endif // Safety } - basic_coroutine(const basic_coroutine&) = default; + + basic_coroutine(const basic_coroutine& other) = default; basic_coroutine& operator=(const basic_coroutine&) = default; - basic_coroutine(basic_coroutine&&) = default; - basic_coroutine& operator=(basic_coroutine&&) = default; - basic_coroutine(const basic_function& b) + + basic_coroutine(basic_coroutine&& other) noexcept : base_t(std::move(other)), error_handler(this->lua_state(), std::move(other.error_handler)) { + } + + basic_coroutine& operator=(basic_coroutine&& other) noexcept { + base_t::operator=(std::move(other)); + // must change the state, since it could change on the coroutine type + error_handler.abandon(); + error_handler = handler_t(this->lua_state(), std::move(other.error_handler)); + return *this; + } + + basic_coroutine(const basic_function& b) noexcept : basic_coroutine(b, detail::get_default_handler::value>(b.lua_state())) { } - basic_coroutine(basic_function&& b) + basic_coroutine(basic_function&& b) noexcept : basic_coroutine(std::move(b), detail::get_default_handler::value>(b.lua_state())) { } - basic_coroutine(const basic_function& b, handler_t eh) : base_t(b), error_handler(std::move(eh)) { + basic_coroutine(const basic_function& b, handler_t eh) noexcept : base_t(b), error_handler(std::move(eh)) { } - basic_coroutine(basic_function&& b, handler_t eh) : base_t(std::move(b)), error_handler(std::move(eh)) { + basic_coroutine(basic_function&& b, handler_t eh) noexcept : base_t(std::move(b)), error_handler(std::move(eh)) { } - basic_coroutine(const stack_reference& r) + basic_coroutine(const stack_reference& r) noexcept : basic_coroutine(r.lua_state(), r.stack_index(), detail::get_default_handler::value>(r.lua_state())) { } - basic_coroutine(stack_reference&& r) + basic_coroutine(stack_reference&& r) noexcept : basic_coroutine(r.lua_state(), r.stack_index(), detail::get_default_handler::value>(r.lua_state())) { } - basic_coroutine(const stack_reference& r, handler_t eh) : basic_coroutine(r.lua_state(), r.stack_index(), std::move(eh)) { + basic_coroutine(const stack_reference& r, handler_t eh) noexcept : basic_coroutine(r.lua_state(), r.stack_index(), std::move(eh)) { } - basic_coroutine(stack_reference&& r, handler_t eh) : basic_coroutine(r.lua_state(), r.stack_index(), std::move(eh)) { + basic_coroutine(stack_reference&& r, handler_t eh) noexcept : basic_coroutine(r.lua_state(), r.stack_index(), std::move(eh)) { } template @@ -144,7 +155,7 @@ namespace sol { } template >> = meta::enabler> - basic_coroutine(lua_State* L, T&& r) + basic_coroutine(lua_State* L, T&& r) noexcept : basic_coroutine(L, std::forward(r), detail::get_default_handler::value>(L)) { } template >> = meta::enabler> diff --git a/include/sol/demangle.hpp b/include/sol/demangle.hpp index 246b9696..9970611a 100644 --- a/include/sol/demangle.hpp +++ b/include/sol/demangle.hpp @@ -47,7 +47,7 @@ namespace sol { namespace detail { "`anonymous namespace'" } }; -#if SOL_IS_ON(SOL_COMPILER_GCC_I_) || SOL_IS_ON(SOL_COMPILER_CLANG_I_) +#if SOL_IS_ON(SOL_COMPILER_GCC_I_) || SOL_IS_ON(SOL_COMPILER_CLANG_I_) || SOL_IS_ON(SOL_COMPILER_VCXX_CLANG_I_) inline std::string ctti_get_type_name_from_sig(std::string name) { // cardinal sins from MINGW using namespace std; diff --git a/include/sol/ebco.hpp b/include/sol/ebco.hpp index a0b91ab8..1764c5a3 100644 --- a/include/sol/ebco.hpp +++ b/include/sol/ebco.hpp @@ -38,8 +38,8 @@ namespace sol { namespace detail { ebco(ebco&&) = default; ebco& operator=(const ebco&) = default; ebco& operator=(ebco&&) = default; - ebco(const T& v) : value_(v){}; - ebco(T&& v) : value_(std::move(v)){}; + ebco(const T& v) : value_(v) {}; + ebco(T&& v) : value_(std::move(v)) {}; ebco& operator=(const T& v) { value_ = v; return *this; @@ -49,15 +49,16 @@ namespace sol { namespace detail { return *this; }; template >, - ebco> && !std::is_same_v>, T>>> - ebco(Arg&& arg, Args&&... args) : T(std::forward(arg), std::forward(args)...){} + typename = std::enable_if_t>, + ebco> && !std::is_same_v>, T>>> + ebco(Arg&& arg, Args&&... args) : value_(std::forward(arg), std::forward(args)...) { + } T& value() & { return value_; } - T const& value() const & { + T const& value() const& { return value_; } @@ -71,8 +72,8 @@ namespace sol { namespace detail { ebco() = default; ebco(const ebco&) = default; ebco(ebco&&) = default; - ebco(const T& v) : T(v){}; - ebco(T&& v) : T(std::move(v)){}; + ebco(const T& v) : T(v) {}; + ebco(T&& v) : T(std::move(v)) {}; template >, ebco> && !std::is_same_v>, T>>> @@ -94,7 +95,7 @@ namespace sol { namespace detail { return static_cast(*this); } - T const& value() const & { + T const& value() const& { return static_cast(*this); } @@ -110,7 +111,7 @@ namespace sol { namespace detail { ebco() = default; ebco(const ebco&) = default; ebco(ebco&&) = default; - ebco(T& v) : ref(v){}; + ebco(T& v) : ref(v) {}; ebco& operator=(const ebco&) = default; ebco& operator=(ebco&&) = default; @@ -131,7 +132,7 @@ namespace sol { namespace detail { ebco() = default; ebco(const ebco&) = default; ebco(ebco&&) = default; - ebco(T&& v) : ref(v){}; + ebco(T&& v) : ref(v) {}; ebco& operator=(const ebco&) = default; ebco& operator=(ebco&&) = default; @@ -144,7 +145,7 @@ namespace sol { namespace detail { return ref; } - const T& value() const & { + const T& value() const& { return ref; } diff --git a/include/sol/function_types.hpp b/include/sol/function_types.hpp index 279a92ce..b9f62ffc 100644 --- a/include/sol/function_types.hpp +++ b/include/sol/function_types.hpp @@ -359,7 +359,7 @@ namespace sol { }; template - struct unqualified_pusher::value>> { + struct unqualified_pusher>> { template static int push(lua_State* L, Args&&... args) { function_detail::select(L, std::forward(args)...); diff --git a/include/sol/property.hpp b/include/sol/property.hpp index e4b8c078..a5c9d609 100644 --- a/include/sol/property.hpp +++ b/include/sol/property.hpp @@ -1,4 +1,4 @@ -// sol3 +// sol3 // The MIT License (MIT) @@ -31,8 +31,8 @@ namespace sol { namespace detail { - struct no_prop {}; - } + struct no_prop { }; + } // namespace detail template struct property_wrapper : detail::ebco, detail::ebco { @@ -42,8 +42,7 @@ namespace sol { public: template - property_wrapper(Rx&& r, Wx&& w) - : read_base_t(std::forward(r)), write_base_t(std::forward(w)) { + property_wrapper(Rx&& r, Wx&& w) : read_base_t(std::forward(r)), write_base_t(std::forward(w)) { } W& write() { @@ -135,13 +134,16 @@ namespace sol { namespace meta { template - struct is_member_object : std::is_member_object_pointer {}; - - template - struct is_member_object> : std::true_type {}; + using is_member_object = std::integral_constant || is_specialization_of_v>; template inline constexpr bool is_member_object_v = is_member_object::value; + + template + using is_member_object_or_function = std::integral_constant || std::is_member_pointer_v>; + + template + inline constexpr bool is_member_object_or_function_v = is_member_object_or_function::value; } // namespace meta } // namespace sol diff --git a/include/sol/protected_function.hpp b/include/sol/protected_function.hpp index e5ad43b0..82ca2060 100644 --- a/include/sol/protected_function.hpp +++ b/include/sol/protected_function.hpp @@ -1,4 +1,4 @@ -// sol3 +// sol3 // The MIT License (MIT) @@ -37,10 +37,11 @@ #include namespace sol { - + namespace detail { template - inline void handle_protected_exception(lua_State* L, optional maybe_ex, const char* error, detail::protected_handler& h) { + inline void handle_protected_exception( + lua_State* L, optional maybe_ex, const char* error, detail::protected_handler& h) { h.stackindex = 0; if (b) { h.target.push(); @@ -51,7 +52,7 @@ namespace sol { detail::call_exception_handler(L, maybe_ex, error); } } - } + } // namespace detail template class basic_protected_function : public basic_object { @@ -100,17 +101,14 @@ namespace sol { int firstreturn = 1; int returncount = 0; call_status code = call_status::ok; -#if !defined(SOL_NO_EXCEPTIONS) || !SOL_NO_EXCEPTIONS -#if (!defined(SOL_EXCEPTIONS_SAFE_PROPAGATION) || !SOL_NO_EXCEPTIONS_SAFE_PROPAGATION) || (defined(SOL_LUAJIT) && SOL_LUAJIT) +#if SOL_IS_ON(SOL_EXCEPTIONS_I_) && SOL_IS_OFF(SOL_PROPAGATE_EXCEPTIONS_I_) try { -#endif // Safe Exception Propagation #endif // No Exceptions firstreturn = (std::max)(1, static_cast(stacksize - n - static_cast(h.valid() && !is_stack_handler::value))); code = luacall(n, LUA_MULTRET, h); poststacksize = lua_gettop(lua_state()) - static_cast(h.valid() && !is_stack_handler::value); returncount = poststacksize - (firstreturn - 1); -#ifndef SOL_NO_EXCEPTIONS -#if (!defined(SOL_EXCEPTIONS_SAFE_PROPAGATION) || !SOL_NO_EXCEPTIONS_SAFE_PROPAGATION) || (defined(SOL_LUAJIT) && SOL_LUAJIT) +#if SOL_IS_ON(SOL_EXCEPTIONS_I_) && SOL_IS_OFF(SOL_PROPAGATE_EXCEPTIONS_I_) } // Handle C++ errors thrown from C++ functions bound inside of lua catch (const char* error) { @@ -128,19 +126,18 @@ namespace sol { firstreturn = lua_gettop(lua_state()); return protected_function_result(lua_state(), firstreturn, 0, 1, call_status::runtime); } -#if (!defined(SOL_EXCEPTIONS_SAFE_PROPAGATION) || !SOL_NO_EXCEPTIONS_SAFE_PROPAGATION) +#if SOL_IS_ON(SOL_EXCEPTIONS_CATCH_ALL_I_) // LuaJIT cannot have the catchall when the safe propagation is on - // but LuaJIT will swallow all C++ errors + // but LuaJIT will swallow all C++ errors // if we don't at least catch std::exception ones catch (...) { detail::handle_protected_exception(lua_state(), optional(nullopt), detail::protected_function_error, h); firstreturn = lua_gettop(lua_state()); return protected_function_result(lua_state(), firstreturn, 0, 1, call_status::runtime); } -#endif // LuaJIT +#endif // Always catch edge case #else // do not handle exceptions: they can be propogated into C++ and keep all type information / rich information -#endif // Safe Exception Propagation #endif // Exceptions vs. No Exceptions return protected_function_result(lua_state(), firstreturn, returncount, returncount, code); } @@ -151,13 +148,15 @@ namespace sol { handler_t error_handler; basic_protected_function() = default; - template , basic_protected_function>>, meta::neg>>, meta::neg>, meta::neg>>, is_lua_reference>> = meta::enabler> - basic_protected_function(T&& r) noexcept - : base_t(std::forward(r)), error_handler(get_default_handler(r.lua_state())) { + template , basic_protected_function>>, + meta::neg>>, meta::neg>, + meta::neg>>, is_lua_reference>> = meta::enabler> + basic_protected_function(T&& r) noexcept : base_t(std::forward(r)), error_handler(get_default_handler(r.lua_state())) { #if SOL_IS_ON(SOL_SAFE_REFERENCES_I_) if (!is_function>::value) { auto pp = stack::push_pop(*this); - constructor_handler handler{}; + constructor_handler handler {}; stack::check(lua_state(), -1, handler); } #endif // Safety @@ -166,100 +165,79 @@ namespace sol { basic_protected_function& operator=(const basic_protected_function&) = default; basic_protected_function(basic_protected_function&&) = default; basic_protected_function& operator=(basic_protected_function&&) = default; - basic_protected_function(const basic_function& b) - : basic_protected_function(b, get_default_handler(b.lua_state())) { + basic_protected_function(const basic_function& b) : basic_protected_function(b, get_default_handler(b.lua_state())) { } - basic_protected_function(basic_function&& b) - : basic_protected_function(std::move(b), get_default_handler(b.lua_state())) { + basic_protected_function(basic_function&& b) : basic_protected_function(std::move(b), get_default_handler(b.lua_state())) { } - basic_protected_function(const basic_function& b, handler_t eh) - : base_t(b), error_handler(std::move(eh)) { + basic_protected_function(const basic_function& b, handler_t eh) : base_t(b), error_handler(std::move(eh)) { } - basic_protected_function(basic_function&& b, handler_t eh) - : base_t(std::move(b)), error_handler(std::move(eh)) { + basic_protected_function(basic_function&& b, handler_t eh) : base_t(std::move(b)), error_handler(std::move(eh)) { } - basic_protected_function(const stack_reference& r) - : basic_protected_function(r.lua_state(), r.stack_index(), get_default_handler(r.lua_state())) { + basic_protected_function(const stack_reference& r) : basic_protected_function(r.lua_state(), r.stack_index(), get_default_handler(r.lua_state())) { } - basic_protected_function(stack_reference&& r) - : basic_protected_function(r.lua_state(), r.stack_index(), get_default_handler(r.lua_state())) { + basic_protected_function(stack_reference&& r) : basic_protected_function(r.lua_state(), r.stack_index(), get_default_handler(r.lua_state())) { } - basic_protected_function(const stack_reference& r, handler_t eh) - : basic_protected_function(r.lua_state(), r.stack_index(), std::move(eh)) { + basic_protected_function(const stack_reference& r, handler_t eh) : basic_protected_function(r.lua_state(), r.stack_index(), std::move(eh)) { } - basic_protected_function(stack_reference&& r, handler_t eh) - : basic_protected_function(r.lua_state(), r.stack_index(), std::move(eh)) { + basic_protected_function(stack_reference&& r, handler_t eh) : basic_protected_function(r.lua_state(), r.stack_index(), std::move(eh)) { } template - basic_protected_function(const proxy_base& p) - : basic_protected_function(p, get_default_handler(p.lua_state())) { + basic_protected_function(const proxy_base& p) : basic_protected_function(p, get_default_handler(p.lua_state())) { } template - basic_protected_function(proxy_base&& p) - : basic_protected_function(std::move(p), get_default_handler(p.lua_state())) { + basic_protected_function(proxy_base&& p) : basic_protected_function(std::move(p), get_default_handler(p.lua_state())) { } - template >, meta::neg>>> = meta::enabler> - basic_protected_function(Proxy&& p, Handler&& eh) - : basic_protected_function(detail::force_cast(p), std::forward(eh)) { + template >, meta::neg>>> = meta::enabler> + basic_protected_function(Proxy&& p, Handler&& eh) : basic_protected_function(detail::force_cast(p), std::forward(eh)) { } template >> = meta::enabler> - basic_protected_function(lua_State* L, T&& r) - : basic_protected_function(L, std::forward(r), get_default_handler(L)) { + basic_protected_function(lua_State* L, T&& r) : basic_protected_function(L, std::forward(r), get_default_handler(L)) { } template >> = meta::enabler> - basic_protected_function(lua_State* L, T&& r, handler_t eh) - : base_t(L, std::forward(r)), error_handler(std::move(eh)) { + basic_protected_function(lua_State* L, T&& r, handler_t eh) : base_t(L, std::forward(r)), error_handler(std::move(eh)) { #if SOL_IS_ON(SOL_SAFE_REFERENCES_I_) auto pp = stack::push_pop(*this); - constructor_handler handler{}; + constructor_handler handler {}; stack::check(lua_state(), -1, handler); #endif // Safety } - - basic_protected_function(lua_nil_t n) - : base_t(n), error_handler(n) { + + basic_protected_function(lua_nil_t n) : base_t(n), error_handler(n) { } - basic_protected_function(lua_State* L, int index = -1) - : basic_protected_function(L, index, get_default_handler(L)) { + basic_protected_function(lua_State* L, int index = -1) : basic_protected_function(L, index, get_default_handler(L)) { } - basic_protected_function(lua_State* L, int index, handler_t eh) - : base_t(L, index), error_handler(std::move(eh)) { + basic_protected_function(lua_State* L, int index, handler_t eh) : base_t(L, index), error_handler(std::move(eh)) { #if SOL_IS_ON(SOL_SAFE_REFERENCES_I_) - constructor_handler handler{}; + constructor_handler handler {}; stack::check(L, index, handler); #endif // Safety } - basic_protected_function(lua_State* L, absolute_index index) - : basic_protected_function(L, index, get_default_handler(L)) { + basic_protected_function(lua_State* L, absolute_index index) : basic_protected_function(L, index, get_default_handler(L)) { } - basic_protected_function(lua_State* L, absolute_index index, handler_t eh) - : base_t(L, index), error_handler(std::move(eh)) { + basic_protected_function(lua_State* L, absolute_index index, handler_t eh) : base_t(L, index), error_handler(std::move(eh)) { #if SOL_IS_ON(SOL_SAFE_REFERENCES_I_) - constructor_handler handler{}; + constructor_handler handler {}; stack::check(L, index, handler); #endif // Safety } - basic_protected_function(lua_State* L, raw_index index) - : basic_protected_function(L, index, get_default_handler(L)) { + basic_protected_function(lua_State* L, raw_index index) : basic_protected_function(L, index, get_default_handler(L)) { } - basic_protected_function(lua_State* L, raw_index index, handler_t eh) - : base_t(L, index), error_handler(std::move(eh)) { + basic_protected_function(lua_State* L, raw_index index, handler_t eh) : base_t(L, index), error_handler(std::move(eh)) { #if SOL_IS_ON(SOL_SAFE_REFERENCES_I_) - constructor_handler handler{}; + constructor_handler handler {}; stack::check(L, index, handler); #endif // Safety } - basic_protected_function(lua_State* L, ref_index index) - : basic_protected_function(L, index, get_default_handler(L)) { + basic_protected_function(lua_State* L, ref_index index) : basic_protected_function(L, index, get_default_handler(L)) { } - basic_protected_function(lua_State* L, ref_index index, handler_t eh) - : base_t(L, index), error_handler(std::move(eh)) { + basic_protected_function(lua_State* L, ref_index index, handler_t eh) : base_t(L, index), error_handler(std::move(eh)) { #if SOL_IS_ON(SOL_SAFE_REFERENCES_I_) auto pp = stack::push_pop(*this); - constructor_handler handler{}; + constructor_handler handler {}; stack::check(lua_state(), -1, handler); #endif // Safety } diff --git a/include/sol/proxy_base.hpp b/include/sol/proxy_base.hpp index 04748a89..45839ca0 100644 --- a/include/sol/proxy_base.hpp +++ b/include/sol/proxy_base.hpp @@ -1,4 +1,4 @@ -// sol3 +// sol3 // The MIT License (MIT) @@ -29,7 +29,7 @@ #include namespace sol { - struct proxy_base_tag {}; + struct proxy_base_tag { }; namespace detail { template @@ -37,30 +37,35 @@ namespace sol { std::tuple>, std::remove_reference_t&, meta::unqualified_t>>>; } +#define SOL_PROXY_BASE_IMPL_MSVC_IS_TRASH_I_(Super) \ + operator std::string() const { \ + const Super& super = *static_cast(static_cast(this)); \ + return super.template get(); \ + } \ + \ + template >, is_proxy_primitive>> = meta::enabler> \ + operator T() const { \ + const Super& super = *static_cast(static_cast(this)); \ + return super.template get(); \ + } \ + \ + template >, meta::neg>>> = meta::enabler> \ + operator T&() const { \ + const Super& super = *static_cast(static_cast(this)); \ + return super.template get(); \ + } \ + static_assert(true, "This is ridiculous and I hate MSVC.") + template - struct proxy_base : proxy_base_tag { - operator std::string() const { - const Super& super = *static_cast(static_cast(this)); - return super.template get(); - } - - template >, is_proxy_primitive>> = meta::enabler> - operator T() const { - const Super& super = *static_cast(static_cast(this)); - return super.template get(); - } - - template >, meta::neg>>> = meta::enabler> - operator T&() const { - const Super& super = *static_cast(static_cast(this)); - return super.template get(); - } - + struct proxy_base : public proxy_base_tag { lua_State* lua_state() const { const Super& super = *static_cast(static_cast(this)); return super.lua_state(); } + + SOL_PROXY_BASE_IMPL_MSVC_IS_TRASH_I_(Super); }; + } // namespace sol #endif // SOL_PROXY_BASE_HPP diff --git a/include/sol/resolve.hpp b/include/sol/resolve.hpp index 6453abcb..adc89001 100644 --- a/include/sol/resolve.hpp +++ b/include/sol/resolve.hpp @@ -48,13 +48,12 @@ namespace sol { template inline constexpr void resolve_f(std::false_type, F&&) { - static_assert( - meta::has_deducible_signature::value, "Cannot use no-template-parameter call with an overloaded functor: specify the signature"); + static_assert(meta::call_operator_deducible_v, "Cannot use no-template-parameter call with an overloaded functor: specify the signature"); } template > - inline constexpr auto resolve_i(types<>, F&& f) -> decltype(resolve_f(meta::has_deducible_signature(), std::forward(f))) { - return resolve_f(meta::has_deducible_signature {}, std::forward(f)); + inline constexpr auto resolve_i(types<>, F&& f) -> decltype(resolve_f(meta::call_operator_deducible(), std::forward(f))) { + return resolve_f(meta::call_operator_deducible {}, std::forward(f)); } template > @@ -118,13 +117,12 @@ namespace sol { template inline void resolve_f(std::false_type, F&&) { - static_assert( - meta::has_deducible_signature::value, "Cannot use no-template-parameter call with an overloaded functor: specify the signature"); + static_assert(meta::call_operator_deducible_v, "Cannot use no-template-parameter call with an overloaded functor: specify the signature"); } template > - inline auto resolve_i(types<>, F&& f) -> decltype(resolve_f(meta::has_deducible_signature(), std::forward(f))) { - return resolve_f(meta::has_deducible_signature {}, std::forward(f)); + inline auto resolve_i(types<>, F&& f) -> decltype(resolve_f(meta::call_operator_deducible(), std::forward(f))) { + return resolve_f(meta::call_operator_deducible {}, std::forward(f)); } template > diff --git a/include/sol/traits.hpp b/include/sol/traits.hpp index 9ec35d5c..d36fea12 100644 --- a/include/sol/traits.hpp +++ b/include/sol/traits.hpp @@ -57,7 +57,7 @@ namespace sol { namespace meta { using unwrapped_t = typename unwrapped::type; template - struct unwrap_unqualified : unwrapped> {}; + struct unwrap_unqualified : unwrapped> { }; template using unwrap_unqualified_t = typename unwrap_unqualified::type; @@ -79,16 +79,16 @@ namespace sol { namespace meta { using remove_member_pointer_t = remove_member_pointer; template - struct all_same : std::true_type {}; + struct all_same : std::true_type { }; template - struct all_same : std::integral_constant::value && all_same::value> {}; + struct all_same : std::integral_constant::value && all_same::value> { }; template - struct any_same : std::false_type {}; + struct any_same : std::false_type { }; template - struct any_same : std::integral_constant::value || any_same::value> {}; + struct any_same : std::integral_constant::value || any_same::value> { }; template constexpr inline bool any_same_v = any_same::value; @@ -106,16 +106,16 @@ namespace sol { namespace meta { constexpr inline bool neg_v = neg::value; template - struct all : boolean {}; + struct all : boolean { }; template - struct all : std::conditional_t, boolean> {}; + struct all : std::conditional_t, boolean> { }; template - struct any : boolean {}; + struct any : boolean { }; template - struct any : std::conditional_t, any> {}; + struct any : std::conditional_t, any> { }; template constexpr inline bool all_v = all::value; @@ -143,37 +143,37 @@ namespace sol { namespace meta { using disable_any = std::enable_if_t>::value, enable_t>; template - struct find_in_pack_v : boolean {}; + struct find_in_pack_v : boolean { }; template - struct find_in_pack_v : any, find_in_pack_v> {}; + struct find_in_pack_v : any, find_in_pack_v> { }; namespace meta_detail { template - struct index_in_pack : std::integral_constant {}; + struct index_in_pack : std::integral_constant { }; template struct index_in_pack - : conditional_t::value, std::integral_constant, index_in_pack> {}; + : conditional_t::value, std::integral_constant, index_in_pack> { }; } // namespace meta_detail template - struct index_in_pack : meta_detail::index_in_pack<0, T, Args...> {}; + struct index_in_pack : meta_detail::index_in_pack<0, T, Args...> { }; template - struct index_in : meta_detail::index_in_pack<0, T, List> {}; + struct index_in : meta_detail::index_in_pack<0, T, List> { }; template - struct index_in> : meta_detail::index_in_pack<0, T, Args...> {}; + struct index_in> : meta_detail::index_in_pack<0, T, Args...> { }; template - struct at_in_pack {}; + struct at_in_pack { }; template using at_in_pack_t = typename at_in_pack::type; template - struct at_in_pack : std::conditional> {}; + struct at_in_pack : std::conditional> { }; template struct at_in_pack<0, Arg, Args...> { @@ -191,17 +191,17 @@ namespace sol { namespace meta { using on_always = std::true_type; template