From d98155cd22904a21154493c1915fcd1fbfd4f037 Mon Sep 17 00:00:00 2001 From: ThePhD Date: Thu, 24 Aug 2017 14:57:28 -0400 Subject: [PATCH] update examples and documentation, proof typing for `user` --- docs/source/usertypes.rst | 2 ++ examples/pairs.cpp | 12 ++++-------- examples/pairs_with_raw_functions.cpp | 21 +++++--------------- examples/usertype_automatic_operators.cpp | 24 ++++++++++++++++------- single/sol/sol.hpp | 12 ++++++------ sol/types.hpp | 8 ++++---- 6 files changed, 38 insertions(+), 41 deletions(-) diff --git a/docs/source/usertypes.rst b/docs/source/usertypes.rst index 554ab911..5d322db8 100644 --- a/docs/source/usertypes.rst +++ b/docs/source/usertypes.rst @@ -19,6 +19,7 @@ The examples folder also has a number of really great examples for you to see. T - If you need dynamic callbacks or runtime overridable functions, have a ``std::function`` member variable and get/set it on the usertype object - ``std::function`` works as a member variable or in passing as an argument / returning as a value (you can even use it with ``sol::property``) - You can also create an entirely dynamic object: see the `dynamic_object example`_ for more details +* (Advanced) You can override the iteration function for Lua 5.2 and above (LuaJIT not included) `as shown in the pairs example`_ * You can use :doc:`filters` to control dependencies and streamline return values, as well as apply custom behavior to a functions return * Please note that the colon is necessary to "automatically" pass the ``this``/``self`` argument to Lua methods - ``obj:method_name()`` is how you call "member" methods in Lua @@ -52,3 +53,4 @@ The examples folder also has a number of really great examples for you to see. T .. _C++: https://github.com/ThePhD/sol2/blob/develop/examples/usertype_simple.cpp#L51 .. _Certain operators: https://github.com/ThePhD/sol2/blob/develop/examples/usertype_automatic_operators.cpp .. _dynamic_object example: https://github.com/ThePhD/sol2/blob/develop/examples/dynamic_object.cpp +.. _as shown in this example: https://github.com/ThePhD/sol2/blob/develop/examples/pairs.cpp diff --git a/examples/pairs.cpp b/examples/pairs.cpp index dc746e24..3625c19a 100644 --- a/examples/pairs.cpp +++ b/examples/pairs.cpp @@ -21,9 +21,8 @@ struct lua_iterator_state { typedef std::map::iterator it_t; it_t it; it_t last; - std::reference_wrapper source; - lua_iterator_state(my_thing& mt) : it(mt.m.begin()), last(mt.m.end()), source(mt) {} + lua_iterator_state(my_thing& mt) : it(mt.m.begin()), last(mt.m.end()) {} }; std::tuple my_next(sol::user user_it_state, sol::this_state l) { @@ -35,7 +34,6 @@ std::tuple my_next(sol::user user // the key value is argument 2, but we do not // care about the key value here lua_iterator_state& it_state = user_it_state; - my_thing& source = it_state.source; auto& it = it_state.it; if (it == it_state.last) { // return nil to signify that @@ -53,7 +51,7 @@ std::tuple my_next(sol::user user // the iterator must be moved forward one before we return std::advance(it, 1); return r; -}; +} auto my_pairs(my_thing& mt) { // pairs expects 3 returns: @@ -67,11 +65,9 @@ auto my_pairs(my_thing& mt) { // it's incompatible with regular usertypes and stores the type T directly in lua without any pretty setup // saves space allocation and a single dereference return std::make_tuple(&my_next, sol::user(std::move(it_state)), sol::lua_nil); -}; +} - - -int main(int argc, char* argv[]) { +int main(int, char*[]) { std::cout << "===== pairs (advanced) =====" << std::endl; sol::state lua; diff --git a/examples/pairs_with_raw_functions.cpp b/examples/pairs_with_raw_functions.cpp index d15a8bd9..8143d2fa 100644 --- a/examples/pairs_with_raw_functions.cpp +++ b/examples/pairs_with_raw_functions.cpp @@ -21,9 +21,8 @@ struct lua_iterator_state { typedef std::map::iterator it_t; it_t it; it_t last; - std::reference_wrapper source; - lua_iterator_state(my_thing& mt) : it(mt.m.begin()), last(mt.m.end()), source(mt) {} + lua_iterator_state(my_thing& mt) : it(mt.m.begin()), last(mt.m.end()) {} }; int my_next(lua_State* L) { @@ -34,7 +33,6 @@ int my_next(lua_State* L) { // the key value is argument 2 // we do not care about the key value here lua_iterator_state& it_state = sol::stack::get>(L, 1); - my_thing& source = it_state.source; auto& it = it_state.it; if (it == it_state.last) { return sol::stack::push(L, sol::lua_nil); @@ -47,16 +45,7 @@ int my_next(lua_State* L) { pushed += sol::stack::push_reference(L, itderef.second); std::advance(it, 1); return pushed; -}; - -auto my_pairs(my_thing& mt) { - // prepare our state - lua_iterator_state it_state(mt); - return std::make_tuple(&my_next, sol::user(std::move(it_state)), sol::lua_nil); - // sol::user above is a space/time optimization over regular usertypes, - // it's incompatible with regular usertypes and stores the type T directly in lua without any pretty setup - // saves space allocation and a single dereference -}; +} int my_pairs(lua_State* L) { my_thing& mt = sol::stack::get(L, 1); @@ -71,16 +60,16 @@ int my_pairs(lua_State* L) { pushed += sol::stack::push>(L, std::move(it_state)); pushed += sol::stack::push(L, sol::lua_nil); return pushed; -}; +} -int main(int argc, char* argv[]) { +int main(int, char*[]) { std::cout << "===== pairs (using raw Lua C functions) (advanced) =====" << std::endl; sol::state lua; lua.open_libraries(sol::lib::base); lua.new_usertype("my_thing", - sol::meta_function::pairs, my_pairs + sol::meta_function::pairs, &my_pairs ); lua.safe_script(R"( diff --git a/examples/usertype_automatic_operators.cpp b/examples/usertype_automatic_operators.cpp index 1b428630..2dc34042 100644 --- a/examples/usertype_automatic_operators.cpp +++ b/examples/usertype_automatic_operators.cpp @@ -79,10 +79,19 @@ print("obj1:", obj1) print("obj2:", obj2) print("obj3:", obj2) +print("#obj1:", #obj1) +print("#obj2:", #obj2) +print("#obj3:", #obj3) + obj1() obj1() obj1() obj1() obj1() obj1() obj2() obj2() obj2() obj3() obj3() obj3() +print("after modifications using obj() operator") +print("obj1:", obj1) +print("obj2:", obj2) +print("obj3:", obj2) + print("#obj1:", #obj1) print("#obj2:", #obj2) print("#obj3:", #obj3) @@ -100,14 +109,15 @@ end print("obj1 == obj2:", obj1 == obj2) print("obj1 < obj2:", obj1 < obj2) print("obj1 >= obj2:", obj1 >= obj2) +assert(obj1 ~= obj2) +assert(obj1 > obj2) +assert(obj1 >= obj2) -print("obj2 == obj3:", obj1 == obj2) -print("obj2 > obj3:", obj1 > obj2) -print("obj2 <= obj3:", obj1 <= obj2) - -print("obj1:", obj1) -print("obj2:", obj2) -print("obj3:", obj2) +print("obj2 == obj3:", obj2 == obj3) +print("obj2 > obj3:", obj2 > obj3) +print("obj2 <= obj3:", obj2 <= obj3) +assert(obj2 == obj3) +assert(obj2 <= obj3) )"); std::cout << std::endl; diff --git a/single/sol/sol.hpp b/single/sol/sol.hpp index 6df2ba69..8d049257 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 2017-08-24 18:37:55.297938 UTC -// This header was generated with sol v2.18.1 (revision a163ae7) +// Generated 2017-08-24 18:56:19.661582 UTC +// This header was generated with sol v2.18.0 (revision 92a6fb8) // https://github.com/ThePhD/sol2 #ifndef SOL_SINGLE_INCLUDE_HPP @@ -4225,10 +4225,10 @@ namespace sol { struct user { U value; - user(U x) : value(std::move(x)) {} - operator std::remove_reference_t* () { return std::addressof(value); } - operator U& () { return value; } - operator const U& () const { return value; } + user(U x) : value(std::forward(x)) {} + operator std::add_pointer_t> () { return std::addressof(value); } + operator std::add_lvalue_reference_t () { return value; } + operator std::add_const_t>& () const { return value; } }; template diff --git a/sol/types.hpp b/sol/types.hpp index bf9bcf5d..9c025f20 100644 --- a/sol/types.hpp +++ b/sol/types.hpp @@ -324,10 +324,10 @@ namespace sol { struct user { U value; - user(U x) : value(std::move(x)) {} - operator std::remove_reference_t* () { return std::addressof(value); } - operator U& () { return value; } - operator const U& () const { return value; } + user(U x) : value(std::forward(x)) {} + operator std::add_pointer_t> () { return std::addressof(value); } + operator std::add_lvalue_reference_t () { return value; } + operator std::add_const_t>& () const { return value; } }; template