diff --git a/docs/source/api/protected_function.rst b/docs/source/api/protected_function.rst index 6dc23fda..97d4e09f 100644 --- a/docs/source/api/protected_function.rst +++ b/docs/source/api/protected_function.rst @@ -7,13 +7,7 @@ Lua function calls that trap errors and provide error handling class protected_function : public reference; -Inspired by a request from `starwing` in the old repository, this class provides the same interface as :doc:`function` but with heavy protection and a potential error handler for any Lua errors and C++ exceptions. Grab a function directly off the stack using the constructor: - -.. code-block:: cpp - :caption: constructor: protected_function - - protected_function(lua_State* L, int index = -1); - +Inspired by a request from `starwing` in the old repository, this class provides the same interface as :doc:`function` but with heavy protection and a potential error handler for any Lua errors and C++ exceptions. You can grab a function directly off the stack using the constructor, or pass to it 2 valid functions, which we'll demonstrate a little later. When called without the return types being specified by either a ``sol::types<...>`` list or a ``call( ... )`` template type list, it generates a :doc:`protected_function_result` class that gets implicitly converted to the requested return type. For example: @@ -34,6 +28,13 @@ When called without the return types being specified by either a ``sol::types<.. return (bark_energy * (bark_power / 4)) end + function woofers ( bark_energy ) + if bark_energy < 10 + error("*whine*") + end + return (bark_energy * (bark_power / 4)) + end + The following C++ code will call this function from this file and retrieve the return value, unless an error occurs, in which case you can bind an error handling function like so: .. code-block:: cpp @@ -86,7 +87,7 @@ Alternatively, with a bad or good function call, you can use ``sol::optional`` t problematicwoof.error_handler = lua["got_problems"]; sol::optional maybevalue = problematicwoof(19); - if (value) { + if (maybevalue) { // Have a value, use it double numwoof = maybevalue.value(); } @@ -94,11 +95,56 @@ Alternatively, with a bad or good function call, you can use ``sol::optional`` t // No value! } -That makes the code a bit more concise and easy to reason about if you don't want to bother with reading the error. Thankfully, unlike ``sol::function_result``, you can save ``sol::protected_function_result`` in a variable and push/pop things above it on the stack where its returned values are. This makes it a bit more flexible than the rigid, performant ``sol::function_result`` type that comes from calling :doc:`sol::function`. If you're confident the result succeeded, you can also just put the type you want (like ``double`` or ``std::string`` right there and it will get it. But, if it doesn't work out, sol can throw and/or panic if you have the :doc:`safety<../safety>` features turned on. +That makes the code a bit more concise and easy to reason about if you don't want to bother with reading the error. Thankfully, unlike ``sol::function_result``, you can save ``sol::protected_function_result`` in a variable and push/pop things above it on the stack where its returned values are. This makes it a bit more flexible than the rigid, performant ``sol::function_result`` type that comes from calling :doc:`sol::function`. + +If you're confident the result succeeded, you can also just put the type you want (like ``double`` or ``std::string`` right there and it will get it. But, if it doesn't work out, sol can throw and/or panic if you have the :doc:`safety<../safety>` features turned on: + +.. code-block:: cpp + :linenos: + + sol::state lua; + + lua.open_file( "pfunc_barks.lua" ); + + // construct with function + error handler + // shorter than old syntax + sol::protected_function problematicwoof(lua["woof"], lua["got_problems"]); + + // dangerous if things go wrong! + double value = problematicwoof(19); + + +Finally, it is *important* to note you can set a default handler. The function is described below: please use it to avoid having to constantly set error handlers: + +.. code-block:: cpp + :linenos: + + sol::state lua; + + lua.open_file( "pfunc_barks.lua" ); + // sets got_problems as the default + // handler for all protected_function errors + sol::protected_function::set_default_handler(lua["got_problems"]); + + sol::protected_function problematicwoof = lua["woof"]; + sol::protected_function problematicwoofers = lua["woofers"]; + + double value = problematicwoof(19); + double value2 = problematicwoof(9); + members ------- +.. code-block:: cpp + :caption: constructor: protected_function + + template + protected_function( T&& func, reference handler = sol::protected_function::get_default_handler() ); + protected_function( lua_State* L, int index = -1, reference handler = sol::protected_function::get_default_handler() ); + +Constructs a ``protected_function``. Use the 2-argument version to pass a custom error handling function more easily. You can also set the :ref:`member variable error_handler` after construction later. ``protected_function`` will always use the latest error handler set on the variable, which is either what you passed to it or the default *at the time of construction*. + .. code-block:: cpp :caption: function: call operator / protected function call diff --git a/docs/source/conf.py b/docs/source/conf.py index 9efe3da5..63733022 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -61,7 +61,7 @@ author = 'ThePhD' # The short X.Y version. version = '2.14' # The full version, including alpha/beta/rc tags. -release = '2.14.2' +release = '2.14.8' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/single/sol/sol.hpp b/single/sol/sol.hpp index 3254795a..890bdb4a 100644 --- a/single/sol/sol.hpp +++ b/single/sol/sol.hpp @@ -20,8 +20,8 @@ // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // This file was generated with a script. -// Generated 2016-09-30 05:42:33.802337 UTC -// This header was generated with sol v2.14.8 (revision 6c34a2a) +// Generated 2016-10-01 05:27:09.914197 UTC +// This header was generated with sol v2.14.8 (revision ca28f85) // https://github.com/ThePhD/sol2 #ifndef SOL_SINGLE_INCLUDE_HPP @@ -3558,10 +3558,26 @@ namespace sol { template struct is_table : std::false_type {}; - template struct is_table> : std::true_type {}; + template + struct is_function : std::false_type {}; + template + struct is_function> : std::true_type {}; + template + struct is_function> : std::true_type {}; + + template + struct is_lightuserdata : std::false_type {}; + template + struct is_lightuserdata> : std::true_type {}; + + template + struct is_userdata : std::false_type {}; + template + struct is_userdata> : std::true_type {}; + template inline type type_of() { return lua_type_of>::value; @@ -3792,6 +3808,15 @@ namespace sol { class basic_userdata : public base_t { public: basic_userdata() noexcept = default; + template , basic_userdata>>, meta::neg>, std::is_base_of>> = meta::enabler> + basic_userdata(T&& r) noexcept : base_t(std::forward(r)) { +#ifdef SOL_CHECK_ARGUMENTS + if (!is_userdata>::value) { + auto pp = stack::push_pop(*this); + type_assert(base_t::lua_state(), -1, type::userdata); + } +#endif // Safety + } basic_userdata(const basic_userdata&) = default; basic_userdata(basic_userdata&&) = default; basic_userdata& operator=(const basic_userdata&) = default; @@ -3809,6 +3834,15 @@ namespace sol { class basic_lightuserdata : public base_t { public: basic_lightuserdata() noexcept = default; + template , basic_lightuserdata>>, meta::neg>, std::is_base_of>> = meta::enabler> + basic_lightuserdata(T&& r) noexcept : base_t(std::forward(r)) { +#ifdef SOL_CHECK_ARGUMENTS + if (!is_userdata>::value) { + auto pp = stack::push_pop(*this); + type_assert(base_t::lua_state(), -1, type::lightuserdata); + } +#endif // Safety + } basic_lightuserdata(const basic_lightuserdata&) = default; basic_lightuserdata(basic_lightuserdata&&) = default; basic_lightuserdata& operator=(const basic_lightuserdata&) = default; @@ -8529,6 +8563,15 @@ namespace sol { public: basic_function() = default; + template , basic_function>>, meta::neg>, std::is_base_of>> = meta::enabler> + basic_function(T&& r) noexcept : base_t(std::forward(r)) { +#ifdef SOL_CHECK_ARGUMENTS + if (!is_function>::value) { + auto pp = stack::push_pop(*this); + stack::check(base_t::lua_state(), -1, type_panic); + } +#endif // Safety + } basic_function(const basic_function&) = default; basic_function& operator=(const basic_function&) = default; basic_function(basic_function&&) = default; @@ -8823,6 +8866,15 @@ namespace sol { reference error_handler; basic_protected_function() = default; + template , basic_protected_function>>, meta::neg>, std::is_base_of>> = meta::enabler> + basic_protected_function(T&& r) noexcept : base_t(std::forward(r)) { +#ifdef SOL_CHECK_ARGUMENTS + if (!is_function>::value) { + auto pp = stack::push_pop(*this); + stack::check(base_t::lua_state(), -1, type_panic); + } +#endif // Safety + } basic_protected_function(const basic_protected_function&) = default; basic_protected_function& operator=(const basic_protected_function&) = default; basic_protected_function(basic_protected_function&&) = default; @@ -8831,6 +8883,10 @@ namespace sol { basic_protected_function(basic_function&& b, reference eh = get_default_handler()) : base_t(std::move(b)), error_handler(std::move(eh)) {} basic_protected_function(const stack_reference& r, reference eh = get_default_handler()) : basic_protected_function(r.lua_state(), r.stack_index(), std::move(eh)) {} basic_protected_function(stack_reference&& r, reference eh = get_default_handler()) : basic_protected_function(r.lua_state(), r.stack_index(), std::move(eh)) {} + template + basic_protected_function(proxy_base&& p, reference eh = get_default_handler()) : basic_protected_function(p.operator basic_function(), std::move(eh)) {} + template + basic_protected_function(const proxy_base& p, reference eh = get_default_handler()) : basic_protected_function(static_cast>(p), std::move(eh)) {} basic_protected_function(lua_State* L, int index = -1, reference eh = get_default_handler()) : base_t(L, index), error_handler(std::move(eh)) { #ifdef SOL_CHECK_ARGUMENTS stack::check(L, index, type_panic); @@ -9222,21 +9278,15 @@ namespace sol { public: basic_object() noexcept = default; - template , basic_object>>, std::is_base_of>> = meta::enabler> + template , basic_object>>, meta::neg>, std::is_base_of>> = meta::enabler> basic_object(T&& r) : base_t(std::forward(r)) {} basic_object(nil_t r) : base_t(r) {} basic_object(const basic_object&) = default; basic_object(basic_object&&) = default; basic_object& operator=(const basic_object&) = default; basic_object& operator=(basic_object&&) = default; - basic_object& operator=(const base_t& b) { - base_t::operator=(b); - return *this; - } - basic_object& operator=(base_t&& b) { - base_t::operator=(std::move(b)); - return *this; - } + basic_object& operator=(const base_t& b) { base_t::operator=(b); return *this; } + basic_object& operator=(base_t&& b) { base_t::operator=(std::move(b)); return *this; } basic_object(const stack_reference& r) noexcept : basic_object(r.lua_state(), r.stack_index()) {} basic_object(stack_reference&& r) noexcept : basic_object(r.lua_state(), r.stack_index()) {} basic_object(lua_State* L, int index = -1) noexcept : base_t(L, index) {} @@ -11162,7 +11212,7 @@ namespace sol { typedef iterator const_iterator; basic_table_core() noexcept : base_t() { } - template , basic_table_core>>, std::is_base_of>> = meta::enabler> + template , basic_table_core>>, meta::neg>, std::is_base_of>> = meta::enabler> basic_table_core(T&& r) noexcept : base_t(std::forward(r)) { #ifdef SOL_CHECK_ARGUMENTS if (!is_table>::value) { diff --git a/sol/function.hpp b/sol/function.hpp index 4da237dd..e65226fe 100644 --- a/sol/function.hpp +++ b/sol/function.hpp @@ -66,6 +66,15 @@ namespace sol { public: basic_function() = default; + template , basic_function>>, meta::neg>, std::is_base_of>> = meta::enabler> + basic_function(T&& r) noexcept : base_t(std::forward(r)) { +#ifdef SOL_CHECK_ARGUMENTS + if (!is_function>::value) { + auto pp = stack::push_pop(*this); + stack::check(base_t::lua_state(), -1, type_panic); + } +#endif // Safety + } basic_function(const basic_function&) = default; basic_function& operator=(const basic_function&) = default; basic_function(basic_function&&) = default; diff --git a/sol/object.hpp b/sol/object.hpp index 56dab3c6..460faa31 100644 --- a/sol/object.hpp +++ b/sol/object.hpp @@ -84,21 +84,15 @@ namespace sol { public: basic_object() noexcept = default; - template , basic_object>>, std::is_base_of>> = meta::enabler> + template , basic_object>>, meta::neg>, std::is_base_of>> = meta::enabler> basic_object(T&& r) : base_t(std::forward(r)) {} basic_object(nil_t r) : base_t(r) {} basic_object(const basic_object&) = default; basic_object(basic_object&&) = default; basic_object& operator=(const basic_object&) = default; basic_object& operator=(basic_object&&) = default; - basic_object& operator=(const base_t& b) { - base_t::operator=(b); - return *this; - } - basic_object& operator=(base_t&& b) { - base_t::operator=(std::move(b)); - return *this; - } + basic_object& operator=(const base_t& b) { base_t::operator=(b); return *this; } + basic_object& operator=(base_t&& b) { base_t::operator=(std::move(b)); return *this; } basic_object(const stack_reference& r) noexcept : basic_object(r.lua_state(), r.stack_index()) {} basic_object(stack_reference&& r) noexcept : basic_object(r.lua_state(), r.stack_index()) {} basic_object(lua_State* L, int index = -1) noexcept : base_t(L, index) {} diff --git a/sol/protected_function.hpp b/sol/protected_function.hpp index 0a8e534f..e7ea082e 100644 --- a/sol/protected_function.hpp +++ b/sol/protected_function.hpp @@ -140,6 +140,15 @@ namespace sol { reference error_handler; basic_protected_function() = default; + template , basic_protected_function>>, meta::neg>, std::is_base_of>> = meta::enabler> + basic_protected_function(T&& r) noexcept : base_t(std::forward(r)) { +#ifdef SOL_CHECK_ARGUMENTS + if (!is_function>::value) { + auto pp = stack::push_pop(*this); + stack::check(base_t::lua_state(), -1, type_panic); + } +#endif // Safety + } basic_protected_function(const basic_protected_function&) = default; basic_protected_function& operator=(const basic_protected_function&) = default; basic_protected_function(basic_protected_function&&) = default; @@ -148,6 +157,10 @@ namespace sol { basic_protected_function(basic_function&& b, reference eh = get_default_handler()) : base_t(std::move(b)), error_handler(std::move(eh)) {} basic_protected_function(const stack_reference& r, reference eh = get_default_handler()) : basic_protected_function(r.lua_state(), r.stack_index(), std::move(eh)) {} basic_protected_function(stack_reference&& r, reference eh = get_default_handler()) : basic_protected_function(r.lua_state(), r.stack_index(), std::move(eh)) {} + template + basic_protected_function(proxy_base&& p, reference eh = get_default_handler()) : basic_protected_function(p.operator basic_function(), std::move(eh)) {} + template + basic_protected_function(const proxy_base& p, reference eh = get_default_handler()) : basic_protected_function(static_cast>(p), std::move(eh)) {} basic_protected_function(lua_State* L, int index = -1, reference eh = get_default_handler()) : base_t(L, index), error_handler(std::move(eh)) { #ifdef SOL_CHECK_ARGUMENTS stack::check(L, index, type_panic); diff --git a/sol/table_core.hpp b/sol/table_core.hpp index a8800dae..918f3d4a 100644 --- a/sol/table_core.hpp +++ b/sol/table_core.hpp @@ -159,7 +159,7 @@ namespace sol { typedef iterator const_iterator; basic_table_core() noexcept : base_t() { } - template , basic_table_core>>, std::is_base_of>> = meta::enabler> + template , basic_table_core>>, meta::neg>, std::is_base_of>> = meta::enabler> basic_table_core(T&& r) noexcept : base_t(std::forward(r)) { #ifdef SOL_CHECK_ARGUMENTS if (!is_table>::value) { diff --git a/sol/types.hpp b/sol/types.hpp index 1c65fb13..e84bb345 100644 --- a/sol/types.hpp +++ b/sol/types.hpp @@ -727,10 +727,26 @@ namespace sol { template struct is_table : std::false_type {}; - template struct is_table> : std::true_type {}; + template + struct is_function : std::false_type {}; + template + struct is_function> : std::true_type {}; + template + struct is_function> : std::true_type {}; + + template + struct is_lightuserdata : std::false_type {}; + template + struct is_lightuserdata> : std::true_type {}; + + template + struct is_userdata : std::false_type {}; + template + struct is_userdata> : std::true_type {}; + template inline type type_of() { return lua_type_of>::value; diff --git a/sol/userdata.hpp b/sol/userdata.hpp index 8daab9f3..6a4098f1 100644 --- a/sol/userdata.hpp +++ b/sol/userdata.hpp @@ -29,6 +29,15 @@ namespace sol { class basic_userdata : public base_t { public: basic_userdata() noexcept = default; + template , basic_userdata>>, meta::neg>, std::is_base_of>> = meta::enabler> + basic_userdata(T&& r) noexcept : base_t(std::forward(r)) { +#ifdef SOL_CHECK_ARGUMENTS + if (!is_userdata>::value) { + auto pp = stack::push_pop(*this); + type_assert(base_t::lua_state(), -1, type::userdata); + } +#endif // Safety + } basic_userdata(const basic_userdata&) = default; basic_userdata(basic_userdata&&) = default; basic_userdata& operator=(const basic_userdata&) = default; @@ -46,6 +55,15 @@ namespace sol { class basic_lightuserdata : public base_t { public: basic_lightuserdata() noexcept = default; + template , basic_lightuserdata>>, meta::neg>, std::is_base_of>> = meta::enabler> + basic_lightuserdata(T&& r) noexcept : base_t(std::forward(r)) { +#ifdef SOL_CHECK_ARGUMENTS + if (!is_userdata>::value) { + auto pp = stack::push_pop(*this); + type_assert(base_t::lua_state(), -1, type::lightuserdata); + } +#endif // Safety + } basic_lightuserdata(const basic_lightuserdata&) = default; basic_lightuserdata(basic_lightuserdata&&) = default; basic_lightuserdata& operator=(const basic_lightuserdata&) = default; diff --git a/test_functions.cpp b/test_functions.cpp index 609341da..cb434c99 100644 --- a/test_functions.cpp +++ b/test_functions.cpp @@ -302,14 +302,13 @@ TEST_CASE("functions/function_result-protected_function_result", "Function resul lua.set("nontrampoline", c_nontrampolinefx); lua.set_function("bark", []() -> int {return 100; }); - sol::protected_function doom = lua["doom"]; - sol::protected_function luadoom = lua["luadoom"]; + sol::function luahandler = lua["luahandler"]; + sol::function cpphandler = lua["cpphandler"]; + sol::protected_function doom(lua["doom"], luahandler); + sol::protected_function luadoom(lua["luadoom"]); sol::protected_function nontrampoline = lua["nontrampoline"]; sol::protected_function justfine = lua["bark"]; sol::protected_function justfinewithhandler = lua["bark"]; - sol::function luahandler = lua["luahandler"]; - sol::function cpphandler = lua["cpphandler"]; - doom.error_handler = luahandler; luadoom.error_handler = cpphandler; nontrampoline.error_handler = cpphandler; justfinewithhandler.error_handler = luahandler;