From 8d62fbaf5dd9b3c87559ef6aaee35c043622523d Mon Sep 17 00:00:00 2001 From: ThePhD Date: Thu, 22 Feb 2018 12:26:46 -0500 Subject: [PATCH] add handle for potentially overloaded `size()` definitions (pray it works with noexcept anyhow). --- docs/source/api/usertype.rst | 17 +++++++++++++++++ docs/source/api/yielding.rst | 10 ++++++++++ docs/source/codecvt.rst | 5 +++++ docs/source/conf.py | 2 +- docs/source/errors.rst | 3 +++ sol/types.hpp | 3 +++ sol/usertype_core.hpp | 11 +++++++++-- tests/test_usertypes.cpp | 10 +++++----- 8 files changed, 53 insertions(+), 8 deletions(-) create mode 100644 docs/source/api/yielding.rst diff --git a/docs/source/api/usertype.rst b/docs/source/api/usertype.rst index a891a488..a5732b8d 100644 --- a/docs/source/api/usertype.rst +++ b/docs/source/api/usertype.rst @@ -208,6 +208,8 @@ If you don't specify anything at all and the type is `destructible`_, then a des You MUST specify ``sol::destructor`` around your destruction function, otherwise it will be ignored. +.. _automagical-registration: + usertype automatic meta functions +++++++++++++++++++++++++++++++++ @@ -380,6 +382,21 @@ Then, to register the base classes explicitly: Specify all base class member variables and member functions to avoid current implementation caveats regarding automatic base member lookup. Sol currently attempts to link base class methods and variables with their derived classes with an undocumented, unsupported feature, provided you specify ``sol::bases<...>``. Unfortunately, this can come at the cost of performance, depending on how "far" the base is from the derived class in the bases lookup list. If you do not want to suffer the performance degradation while we iron out the kinks in the implementation (and want it to stay performant forever), please specify all the base methods on the derived class in the method listing you write. In the future, we hope that with reflection we will not have to worry about this. +.. _automagical: + +automagical usertypes +--------------------- + +Usertypes automatically register special functions, whether or not they're bound using `new(_simple)_usertype`. You can turn this off by specializing the ``sol::is_automagical`` template trait: + +.. code-block:: cpp + + struct my_strange_nonconfirming_type { /* ... */ }; + + namespace sol { + template <> + struct is_automagical : std::false_type {}; + } inheritance + overloading ------------------------- diff --git a/docs/source/api/yielding.rst b/docs/source/api/yielding.rst new file mode 100644 index 00000000..ad124b15 --- /dev/null +++ b/docs/source/api/yielding.rst @@ -0,0 +1,10 @@ +yielding +======== +*telling a C++ function to yield its results into Lua* + +.. code-block:: cpp + + template + yield_wrapper yielding( F&& f ) + +``sol::yielding`` is useful for calling C++ functions which need to yield into a Lua coroutine. It is a wrapper around a single argument which is expected to be bound as a function. You can pass it anywhere a regular function can be bound, **except for in usertype definitions**. diff --git a/docs/source/codecvt.rst b/docs/source/codecvt.rst index 1a931504..5bcfeb5d 100644 --- a/docs/source/codecvt.rst +++ b/docs/source/codecvt.rst @@ -3,6 +3,11 @@ codecvt + std::(w/u16/u32)string support because this is surprisingly hard using standard C++ ---------------------------------------------------- +.. warning:: + + This header is no longer used and sol2 now converts utf8, utf16, and utf32 with internal routines. If you have a problem with the transcoding, please file an issue report. + + Individuals using Visual Studio 2015, or on Windows with the VC++ and MinGW compilers (possibly Clang++ on Windows as well) have ```` headers, and thusly Sol will attempt to include it. Individuals on GCC 4.9.x, Clang 3.5.x, Clang 3.6.x do not seem to have ```` shipped with the standard library that comes with installation of these compilers. If you want ``std::wstring``, ``std::u16string``, ``std::u32string`` automatic handling then you need to make sure you have those headers and then define ``SOL_CODECVT_SUPPORT`` on unsupported compilers. .. _codecvt-deprecation: diff --git a/docs/source/conf.py b/docs/source/conf.py index 94e4961d..3aae4b13 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -61,7 +61,7 @@ author = 'ThePhD' # The short X.Y version. version = '2.19' # The full version, including alpha/beta/rc tags. -release = '2.19.0' +release = '2.19.4' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/docs/source/errors.rst b/docs/source/errors.rst index 4d56ac20..980ed7b2 100644 --- a/docs/source/errors.rst +++ b/docs/source/errors.rst @@ -18,6 +18,7 @@ Compiler Errors / Warnings A myriad of compiler errors can occur when something goes wrong. Here is some basic advice about working with these types: * If there are a myriad of errors relating to ``std::index_sequence``, type traits, and other ``std::`` members, it is likely you have not turned on your C++14 switch for your compiler. Visual Studio 2015 turns these on by default, but g++ and clang++ do not have them as defaults and you should pass the flag ``--std=c++1y`` or ``--std=c++14``, or similar for your compiler. +* If you are pushing a non-primitive type into Lua, you may get strange errors about initializer lists or being unable to initializer a ``luaL_Reg``. This may be due to :ref:`automatic function and operator registration`. :ref:`Disabling it` may help. * Sometimes, a generated usertype can be very long if you are binding a lot of member functions. You may end up with a myriad of warnings about debug symbols being cut off or about ``__LINE_VAR`` exceeding maximum length. You can silence these warnings safely for some compilers. * Template depth errors may also be a problem on earlier versions of clang++ and g++. Use ``-ftemplate-depth`` compiler flag and specify really high number (something like 2048 or even double that amount) to let the compiler work freely. Also consider potentially using :doc:`simple usertypes` to save compilation speed. * When using usertype templates extensively, MSVC may invoke `compiler error C1128 `_ , which is solved by using the `/bigobj compilation flag `_. @@ -83,6 +84,8 @@ Destructors and Safety Another issue is that Lua is a C API. It uses ``setjmp`` and ``longjmp`` to jump out of code when an error occurs. This means it will ignore destructors in your code if you use the library or the underlying Lua VM improperly. To solve this issue, build Lua as C++. When a Lua VM error occurs and ``lua_error`` is triggered, it raises it as an exception which will provoke proper unwinding semantics. +Building Lua as C++ gets around this issue, and allows lua-thrown errors to properly stack unwind. + Protected Functions and Access ------------------------------ diff --git a/sol/types.hpp b/sol/types.hpp index c6d35d70..49bafa75 100644 --- a/sol/types.hpp +++ b/sol/types.hpp @@ -1231,6 +1231,9 @@ namespace sol { template struct is_environment : std::integral_constant::value || is_table::value> {}; + template + struct is_automagical : std::true_type {}; + template inline type type_of() { return lua_type_of>::value; diff --git a/sol/usertype_core.hpp b/sol/usertype_core.hpp index c558a83e..267c2a2f 100644 --- a/sol/usertype_core.hpp +++ b/sol/usertype_core.hpp @@ -151,8 +151,10 @@ namespace sol { template > = meta::enabler> inline void make_length_op(Regs& l, int& index) { + typedef decltype(std::declval().size()) R; + using sz_func = R(T::*)()const; const char* name = to_string(meta_function::length).c_str(); - l[index] = luaL_Reg{ name, &c_call }; + l[index] = luaL_Reg{ name, &c_call(&T::size)), static_cast(&T::size)> }; ++index; } @@ -181,7 +183,12 @@ namespace sol { } } - template + template > = meta::enabler> + void insert_default_registrations(Regs&, int&, Fx&&) { + // no-op + } + + template > = meta::enabler> void insert_default_registrations(Regs& l, int& index, Fx&& fx) { if (fx(meta_function::less_than)) { const char* name = to_string(meta_function::less_than).c_str(); diff --git a/tests/test_usertypes.cpp b/tests/test_usertypes.cpp index 587bb418..f99fb4f4 100644 --- a/tests/test_usertypes.cpp +++ b/tests/test_usertypes.cpp @@ -697,20 +697,20 @@ TEST_CASE("regressions/one", "issue number 48") { } TEST_CASE("usertype/get-set-references", "properly get and set with std::ref semantics. Note that to get, we must not use Unqualified on the type...") { - std::cout << "----- in 4" << std::endl; + std::cout << "----- in 4" << std::endl; sol::state lua; lua.new_usertype("vars", "boop", &vars::boop); vars var{}; vars rvar{}; - std::cout << "setting beep" << std::endl; + std::cout << "setting beep" << std::endl; lua.set("beep", var); - std::cout << "setting rbeep" << std::endl; + std::cout << "setting rbeep" << std::endl; lua.set("rbeep", std::ref(rvar)); - std::cout << "getting my_var" << std::endl; + std::cout << "getting my_var" << std::endl; auto& my_var = lua.get("beep"); - std::cout << "setting rbeep" << std::endl; + std::cout << "setting rbeep" << std::endl; auto& ref_var = lua.get>("rbeep"); vars& proxy_my_var = lua["beep"]; std::reference_wrapper proxy_ref_var = lua["rbeep"];