summaryrefslogtreecommitdiffstatshomepage
path: root/3rdparty
diff options
context:
space:
mode:
author Miodrag Milanovic <mmicko@gmail.com>2016-11-06 10:05:36 +0100
committer Miodrag Milanovic <mmicko@gmail.com>2016-11-06 10:05:36 +0100
commitc2a75cb1799a31aa5687e576d1c0bdd50825fded (patch)
tree59144f444d666ae20ac8fb2bc4e4553d330945ca /3rdparty
parentfffd464d345a6368cda7d90945d3409151218a06 (diff)
Updated sol2, made lua console not crash for nil data (nw)
Diffstat (limited to '3rdparty')
-rw-r--r--3rdparty/sol2/.gitignore3
-rw-r--r--3rdparty/sol2/.gitmodules5
-rw-r--r--3rdparty/sol2/Optional/optional.hpp142
-rw-r--r--3rdparty/sol2/README.md13
-rw-r--r--3rdparty/sol2/docs/presentations/ThePhD - No Overhead C Abstraction - 2016.10.14.pdfbin0 -> 1269746 bytes
-rw-r--r--3rdparty/sol2/docs/source/api/api-top.rst1
-rw-r--r--3rdparty/sol2/docs/source/api/as_table.rst6
-rw-r--r--3rdparty/sol2/docs/source/api/containers.rst93
-rw-r--r--3rdparty/sol2/docs/source/api/function.rst15
-rw-r--r--3rdparty/sol2/docs/source/api/protected_function.rst2
-rw-r--r--3rdparty/sol2/docs/source/api/readonly.rst61
-rw-r--r--3rdparty/sol2/docs/source/api/simple_usertype.rst25
-rw-r--r--3rdparty/sol2/docs/source/api/state.rst12
-rw-r--r--3rdparty/sol2/docs/source/api/usertype.rst2
-rw-r--r--3rdparty/sol2/docs/source/api/usertype_memory.rst6
-rw-r--r--3rdparty/sol2/docs/source/benchmarks.rst8
-rw-r--r--3rdparty/sol2/docs/source/conf.py4
-rw-r--r--3rdparty/sol2/docs/source/errors.rst35
-rw-r--r--3rdparty/sol2/docs/source/features.rst21
-rw-r--r--3rdparty/sol2/docs/source/index.rst14
-rw-r--r--3rdparty/sol2/docs/source/mentions.rst39
-rw-r--r--3rdparty/sol2/docs/source/performance.rst1
-rw-r--r--3rdparty/sol2/docs/source/traits.rst15
-rw-r--r--3rdparty/sol2/docs/source/tutorial/all-the-things.rst22
-rw-r--r--3rdparty/sol2/docs/source/tutorial/customization.rst3
-rw-r--r--3rdparty/sol2/docs/source/tutorial/functions.rst2
-rw-r--r--3rdparty/sol2/docs/source/tutorial/getting-started.rst7
-rw-r--r--3rdparty/sol2/docs/source/usertypes.rst26
-rw-r--r--3rdparty/sol2/single/sol/sol.hpp2969
-rw-r--r--3rdparty/sol2/sol/call.hpp57
-rw-r--r--3rdparty/sol2/sol/compatibility/5.1.0.h2
-rw-r--r--3rdparty/sol2/sol/compatibility/5.2.0.h43
-rw-r--r--3rdparty/sol2/sol/compatibility/5.x.x.inl1
-rw-r--r--3rdparty/sol2/sol/container_usertype_metatable.hpp259
-rw-r--r--3rdparty/sol2/sol/error.hpp1
-rw-r--r--3rdparty/sol2/sol/load_result.hpp2
-rw-r--r--3rdparty/sol2/sol/object.hpp2
-rw-r--r--3rdparty/sol2/sol/optional.hpp3
-rw-r--r--3rdparty/sol2/sol/optional_implementation.hpp1127
-rw-r--r--3rdparty/sol2/sol/proxy.hpp12
-rw-r--r--3rdparty/sol2/sol/simple_usertype_metatable.hpp163
-rw-r--r--3rdparty/sol2/sol/stack_check.hpp65
-rw-r--r--3rdparty/sol2/sol/stack_get.hpp38
-rw-r--r--3rdparty/sol2/sol/stack_push.hpp18
-rw-r--r--3rdparty/sol2/sol/state.hpp8
-rw-r--r--3rdparty/sol2/sol/state_view.hpp30
-rw-r--r--3rdparty/sol2/sol/table_core.hpp3
-rw-r--r--3rdparty/sol2/sol/types.hpp20
-rw-r--r--3rdparty/sol2/sol/usertype_metatable.hpp37
-rw-r--r--3rdparty/sol2/sol/usertype_traits.hpp44
-rw-r--r--3rdparty/sol2/test_containers.cpp51
-rw-r--r--3rdparty/sol2/test_simple_usertypes.cpp6
-rw-r--r--3rdparty/sol2/tests.cpp114
53 files changed, 3992 insertions, 1666 deletions
diff --git a/3rdparty/sol2/.gitignore b/3rdparty/sol2/.gitignore
index 242803c126c..158a742b4c4 100644
--- a/3rdparty/sol2/.gitignore
+++ b/3rdparty/sol2/.gitignore
@@ -66,6 +66,7 @@ lua53.dll
main.exe
main.o
lua-5.3.3/
-*.pdf
main.lua
LuaJIT-2.1.0/
+lua-5.3.3-cxx/
+lua-5.3.3.vcxproj-cxx.filters
diff --git a/3rdparty/sol2/.gitmodules b/3rdparty/sol2/.gitmodules
index f6ae162a2f3..570fde0f51f 100644
--- a/3rdparty/sol2/.gitmodules
+++ b/3rdparty/sol2/.gitmodules
@@ -1,6 +1,3 @@
[submodule "Catch"]
path = Catch
- url = https://github.com/philsquared/Catch.git
-[submodule "Optional"]
- path = Optional
- url = https://github.com/ThePhD/Optional.git
+ url = https://github.com/philsquared/Catch.git \ No newline at end of file
diff --git a/3rdparty/sol2/Optional/optional.hpp b/3rdparty/sol2/Optional/optional.hpp
index 55b8306d013..222320412c7 100644
--- a/3rdparty/sol2/Optional/optional.hpp
+++ b/3rdparty/sol2/Optional/optional.hpp
@@ -21,10 +21,7 @@
# define TR2_OPTIONAL_REQUIRES(...) typename ::std::enable_if<__VA_ARGS__::value, bool>::type = false
# if defined __GNUC__ // NOTE: GNUC is also defined for Clang
-# if (__GNUC__ >= 5)
-# define TR2_OPTIONAL_GCC_5_0_AND_HIGHER___
-# define TR2_OPTIONAL_GCC_4_8_AND_HIGHER___
-# elif (__GNUC__ == 4) && (__GNUC_MINOR__ >= 8)
+# if (__GNUC__ == 4) && (__GNUC_MINOR__ >= 8)
# define TR2_OPTIONAL_GCC_4_8_AND_HIGHER___
# elif (__GNUC__ > 4)
# define TR2_OPTIONAL_GCC_4_8_AND_HIGHER___
@@ -259,98 +256,79 @@ public:
template <class T>
+union storage_t
+{
+ unsigned char dummy_;
+ T value_;
+
+ constexpr storage_t( trivial_init_t ) noexcept : dummy_() {};
+
+ template <class... Args>
+ constexpr storage_t( Args&&... args ) : value_(constexpr_forward<Args>(args)...) {}
+
+ ~storage_t(){}
+};
+
+
+template <class T>
+union constexpr_storage_t
+{
+ unsigned char dummy_;
+ T value_;
+
+ constexpr constexpr_storage_t( trivial_init_t ) noexcept : dummy_() {};
+
+ template <class... Args>
+ constexpr constexpr_storage_t( Args&&... args ) : value_(constexpr_forward<Args>(args)...) {}
+
+ ~constexpr_storage_t() = default;
+};
+
+
+template <class T>
struct optional_base
{
bool init_;
- char storage_[sizeof(T)];
+ storage_t<T> storage_;
- constexpr optional_base() noexcept : init_(false), storage_() {};
+ constexpr optional_base() noexcept : init_(false), storage_(trivial_init) {};
- explicit optional_base(const T& v) : init_(true), storage_() {
- new (&storage())T(v);
- }
+ explicit constexpr optional_base(const T& v) : init_(true), storage_(v) {}
- explicit optional_base(T&& v) : init_(true), storage_() {
- new (&storage())T(constexpr_move(v));
- }
+ explicit constexpr optional_base(T&& v) : init_(true), storage_(constexpr_move(v)) {}
template <class... Args> explicit optional_base(in_place_t, Args&&... args)
- : init_(true), storage_() {
- new (&storage())T(constexpr_forward<Args>(args)...);
- }
+ : init_(true), storage_(constexpr_forward<Args>(args)...) {}
template <class U, class... Args, TR2_OPTIONAL_REQUIRES(::std::is_constructible<T, ::std::initializer_list<U>>)>
explicit optional_base(in_place_t, ::std::initializer_list<U> il, Args&&... args)
- : init_(true), storage_() {
- new (&storage())T(il, constexpr_forward<Args>(args)...);
- }
-#if defined __GNUC__
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wstrict-aliasing"
-#endif
- T& storage() {
- return *reinterpret_cast<T*>(&storage_[0]);
- }
-
- constexpr const T& storage() const {
- return *reinterpret_cast<T const*>(&storage_[0]);
- }
-#if defined __GNUC__
-#pragma GCC diagnostic pop
-#endif
+ : init_(true), storage_(il, ::std::forward<Args>(args)...) {}
- ~optional_base() { if (init_) { storage().T::~T(); } }
+ ~optional_base() { if (init_) storage_.value_.T::~T(); }
};
-#if defined __GNUC__ && !defined TR2_OPTIONAL_GCC_5_0_AND_HIGHER___
-// Sorry, GCC 4.x; you're just a piece of shit
-template <typename T>
-using constexpr_optional_base = optional_base<T>;
-#else
+
template <class T>
struct constexpr_optional_base
{
- bool init_;
- char storage_[sizeof(T)];
- constexpr constexpr_optional_base() noexcept : init_(false), storage_() {}
+ bool init_;
+ constexpr_storage_t<T> storage_;
- explicit constexpr constexpr_optional_base(const T& v) : init_(true), storage_() {
- new (&storage())T(v);
- }
+ constexpr constexpr_optional_base() noexcept : init_(false), storage_(trivial_init) {};
- explicit constexpr constexpr_optional_base(T&& v) : init_(true), storage_() {
- new (&storage())T(constexpr_move(v));
- }
+ explicit constexpr constexpr_optional_base(const T& v) : init_(true), storage_(v) {}
+
+ explicit constexpr constexpr_optional_base(T&& v) : init_(true), storage_(constexpr_move(v)) {}
template <class... Args> explicit constexpr constexpr_optional_base(in_place_t, Args&&... args)
- : init_(true), storage_() {
- new (&storage())T(constexpr_forward<Args>(args)...);
- }
+ : init_(true), storage_(constexpr_forward<Args>(args)...) {}
template <class U, class... Args, TR2_OPTIONAL_REQUIRES(::std::is_constructible<T, ::std::initializer_list<U>>)>
- OPTIONAL_CONSTEXPR_INIT_LIST explicit constexpr_optional_base(in_place_t, ::std::initializer_list<U> il, Args&&... args)
- : init_(true), storage_() {
- new (&storage())T(il, constexpr_forward<Args>(args)...);
- }
-
-#if defined __GNUC__
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wstrict-aliasing"
-#endif
- T& storage() {
- return (*reinterpret_cast<T*>(&storage_[0]));
- }
-
- constexpr const T& storage() const {
- return (*reinterpret_cast<T const*>(&storage_[0]));
- }
-#if defined __GNUC__
-#pragma GCC diagnostic pop
-#endif
+ OPTIONAL_CONSTEXPR_INIT_LIST explicit constexpr_optional_base(in_place_t, ::std::initializer_list<U> il, Args&&... args)
+ : init_(true), storage_(il, ::std::forward<Args>(args)...) {}
~constexpr_optional_base() = default;
};
-#endif
template <class T>
using OptionalBase = typename ::std::conditional<
@@ -369,21 +347,21 @@ class optional : private OptionalBase<T>
constexpr bool initialized() const noexcept { return OptionalBase<T>::init_; }
- typename ::std::remove_const<T>::type* dataptr() { return ::std::addressof(OptionalBase<T>::storage()); }
- constexpr const T* dataptr() const { return detail_::static_addressof(OptionalBase<T>::storage()); }
+ typename ::std::remove_const<T>::type* dataptr() { return ::std::addressof(OptionalBase<T>::storage_.value_); }
+ constexpr const T* dataptr() const { return detail_::static_addressof(OptionalBase<T>::storage_.value_); }
# if OPTIONAL_HAS_THIS_RVALUE_REFS == 1
- constexpr const T& contained_val() const& { return OptionalBase<T>::storage(); }
+ constexpr const T& contained_val() const& { return OptionalBase<T>::storage_.value_; }
# if OPTIONAL_HAS_MOVE_ACCESSORS == 1
- OPTIONAL_MUTABLE_CONSTEXPR T&& contained_val() && { return ::std::move(OptionalBase<T>::storage()); }
- OPTIONAL_MUTABLE_CONSTEXPR T& contained_val() & { return OptionalBase<T>::storage(); }
+ OPTIONAL_MUTABLE_CONSTEXPR T&& contained_val() && { return ::std::move(OptionalBase<T>::storage_.value_); }
+ OPTIONAL_MUTABLE_CONSTEXPR T& contained_val() & { return OptionalBase<T>::storage_.value_; }
# else
- T& contained_val() & { return OptionalBase<T>::storage(); }
- T&& contained_val() && { return ::std::move(OptionalBase<T>::storage()); }
+ T& contained_val() & { return OptionalBase<T>::storage_.value_; }
+ T&& contained_val() && { return ::std::move(OptionalBase<T>::storage_.value_); }
# endif
# else
- constexpr const T& contained_val() const { return OptionalBase<T>::storage(); }
- T& contained_val() { return OptionalBase<T>::storage(); }
+ constexpr const T& contained_val() const { return OptionalBase<T>::storage_.value_; }
+ T& contained_val() { return OptionalBase<T>::storage_.value_; }
# endif
void clear() noexcept {
@@ -715,10 +693,10 @@ public:
return ref != nullptr;
}
- template <typename V>
- constexpr T& value_or(V&& v) const
+ template <class V>
+ constexpr typename ::std::decay<T>::type value_or(V&& v) const
{
- return *this ? **this : detail_::convert<T&>(constexpr_forward<V>(v));
+ return *this ? **this : detail_::convert<typename ::std::decay<T>::type>(constexpr_forward<V>(v));
}
};
diff --git a/3rdparty/sol2/README.md b/3rdparty/sol2/README.md
index 3eb58f6d3de..198a7240a79 100644
--- a/3rdparty/sol2/README.md
+++ b/3rdparty/sol2/README.md
@@ -1,4 +1,6 @@
-## Sol 2.14
+## Sol 2.15
+
+[![Join the chat at https://gitter.im/chat-sol2/Lobby](https://badges.gitter.im/chat-sol2/Lobby.svg)](https://gitter.im/chat-sol2/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![Build Status](https://travis-ci.org/ThePhD/sol2.svg?branch=develop)](https://travis-ci.org/ThePhD/sol2)
[![Documentation Status](https://readthedocs.org/projects/sol2/badge/?version=latest)](http://sol2.readthedocs.io/en/latest/?badge=latest)
@@ -44,13 +46,20 @@ int main() {
More examples are given in the examples directory.
+## Presentations
+
+"A Sun For the Moon - A Zero-Overhead Lua Abstraction using C++"
+ThePhD
+Lua Workshop 2016 - Mashape, San Francisco, CA
+[Deck](https://github.com/ThePhD/sol2/blob/develop/docs/presentations/ThePhD%20-%20No%20Overhead%20C%20Abstraction%20-%202016.10.14.pdf)
+
## Creating a single header
You can grab a single header out of the library [here](https://github.com/ThePhD/sol2/tree/develop/single/sol). For stable version, check the releases tab on github for a provided single header file for maximum ease of use. A script called `single.py` is provided in the repository if there's some bleeding edge change that hasn't been published on the releases page. You can run this script to create a single file version of the library so you can only include that part of it. Check `single.py --help` for more info.
## Features
-- [Fastest in the land](http://sol2.readthedocs.io/en/latest/benchmarks.html) (see: sol2 graph and table entries).
+- [Fastest in the land](http://sol2.readthedocs.io/en/latest/benchmarks.html) (see: sol bar in graph).
- Supports retrieval and setting of multiple types including `std::string` and `std::map/unordered_map`.
- Lambda, function, and member function bindings are supported.
- Intermediate type for checking if a variable exists.
diff --git a/3rdparty/sol2/docs/presentations/ThePhD - No Overhead C Abstraction - 2016.10.14.pdf b/3rdparty/sol2/docs/presentations/ThePhD - No Overhead C Abstraction - 2016.10.14.pdf
new file mode 100644
index 00000000000..51c674b91eb
--- /dev/null
+++ b/3rdparty/sol2/docs/presentations/ThePhD - No Overhead C Abstraction - 2016.10.14.pdf
Binary files differ
diff --git a/3rdparty/sol2/docs/source/api/api-top.rst b/3rdparty/sol2/docs/source/api/api-top.rst
index f9b0378b30e..4dac922becf 100644
--- a/3rdparty/sol2/docs/source/api/api-top.rst
+++ b/3rdparty/sol2/docs/source/api/api-top.rst
@@ -12,6 +12,7 @@ Browse the various function and classes :doc:`Sol<../index>` utilizes to make yo
state
table
proxy
+ containers
as_table
usertype
simple_usertype
diff --git a/3rdparty/sol2/docs/source/api/as_table.rst b/3rdparty/sol2/docs/source/api/as_table.rst
index 58870fa770f..e5b58b49fa4 100644
--- a/3rdparty/sol2/docs/source/api/as_table.rst
+++ b/3rdparty/sol2/docs/source/api/as_table.rst
@@ -21,4 +21,8 @@ This function serves the purpose of ensuring that an object is pushed -- if poss
lua.script("for k, v in ipairs(my_table) do print(k, v) assert(k == v) end");
-Note that any caveats with Lua tables apply the moment it is serialized, and the data cannot be gotten out back out in C++ as a vector without explicitly using the ``as_table_t`` marker for your get and conversion operations using Sol. \ No newline at end of file
+Note that any caveats with Lua tables apply the moment it is serialized, and the data cannot be gotten out back out in C++ as a C++ type without explicitly using the ``as_table_t`` marker for your get and conversion operations using Sol.
+
+If you need this functionality with a member variable, use a :doc:`property on a getter function<property>` that returns the result of ``sol::as_table``.
+
+This marker does NOT apply to :doc:`usertypes<usertype>`. \ No newline at end of file
diff --git a/3rdparty/sol2/docs/source/api/containers.rst b/3rdparty/sol2/docs/source/api/containers.rst
new file mode 100644
index 00000000000..dba03df8a58
--- /dev/null
+++ b/3rdparty/sol2/docs/source/api/containers.rst
@@ -0,0 +1,93 @@
+containers
+==========
+for handling ``std::vector/map/set`` and others
+-----------------------------------------------
+
+Sol2 automatically converts containers (detected using the ``sol::is_container<T>`` type trait, which simply looks for begin / end) to be a special kind of userdata with metatable on it. For Lua 5.2 and 5.3, this is extremely helpful as you can make typical containers behave like Lua tables without losing the actual container that they came from, as well as a small amount of indexing and other operations that behave properly given the table type.
+
+
+a complete example
+------------------
+
+Here's a complete working example of it working for Lua 5.3 and Lua 5.2, and how you can retrieve out the container in all versions:
+
+.. code-block:: cpp
+ :caption: containers.cpp
+
+ #define SOL_CHECK_ARGUMENTS
+ #include <sol.hpp>
+
+ int main() {
+ sol::state lua;
+ lua.open_libraries();
+
+ lua.script(R"(
+ function f (x)
+ print('--- Calling f ---')
+ for k, v in pairs(x) do
+ print(k, v)
+ end
+ end
+ )");
+
+ // Have the function we
+ // just defined in Lua
+ sol::function f = lua["f"];
+
+ // Set a global variable called
+ // "arr" to be a vector of 5 lements
+ lua["arr"] = std::vector<int>{ 2, 4, 6, 8, 10 };
+
+ // Call it, see 5 elements
+ // printed out
+ f(lua["arr"]);
+
+ // Mess with it in C++
+ std::vector<int>& reference_to_arr = lua["arr"];
+ reference_to_arr.push_back(12);
+
+ // Call it, see *6* elements
+ // printed out
+ f(lua["arr"]);
+
+ return 0;
+ }
+
+Note that this will not work well in 5.1, as it has explicit table checks and does not check metamethods, even when ``pairs`` or ``ipairs`` is passed a table. In that case, you will need to use a more manual iteration scheme or you will have to convert it to a table. In C++, you can use :doc:`sol::as_table<as_table>` when passing something to the library to get a table out of it.
+
+
+additional functions
+--------------------
+
+Based on the type pushed, a few additional functions are added as "member functions" (``self`` functions called with ``obj:func()`` or ``obj.func(obj)`` syntax) within a Lua script:
+
+* ``my_container:clear()``: This will call the underlying containers ``clear`` function.
+* ``my_container:add( key, value )`` or ``my_container:add( value )``: this will add to the end of the container, or if it is an associative or ordered container, simply put in an expected key-value pair into it.
+* ``my_contaner:insert( where, value )`` or ``my_contaner:insert( key, value )``: similar to add, but it only takes two arguments. In the case of ``std::vector`` and the like, the first argument is a ``where`` integer index. The second argument is the value. For associative containers, a key and value argument are expected.
+
+
+.. _container-detection:
+
+too-eager container detection?
+------------------------------
+
+
+If you have a type that has ``begin`` or ``end`` member functions but don't provide iterators, you can specialize ``sol::is_container<T>`` to be ``std::false_type``, and that will treat the type as a regular usertype and push it as a regular userdata:
+
+.. code-block:: cpp
+ :caption: specialization.hpp
+
+ struct not_container {
+ void begin() {
+
+ }
+
+ void end() {
+
+ }
+ };
+
+ namespace sol {
+ template <>
+ struct is_container<not_container> : std::false_type {};
+ } \ No newline at end of file
diff --git a/3rdparty/sol2/docs/source/api/function.rst b/3rdparty/sol2/docs/source/api/function.rst
index 27946117a8c..93adedabe49 100644
--- a/3rdparty/sol2/docs/source/api/function.rst
+++ b/3rdparty/sol2/docs/source/api/function.rst
@@ -3,6 +3,10 @@ function
calling functions bound to Lua
------------------------------
+.. note::
+
+ This abstraction assumes the function runs safely. If you expect your code to have errors (e.g., you don't always have explicit control over it or are trying to debug errors), please use :doc:`sol::protected_function<protected_function>`.
+
.. code-block:: cpp
class function : public reference;
@@ -83,6 +87,17 @@ Calls the function. The second ``operator()`` lets you specify the templated ret
All arguments are forwarded. Unlike :doc:`get/set/operator[] on sol::state<state>` or :doc:`sol::table<table>`, value semantics are not used here. It is forwarding reference semantics, which do not copy/move unless it is specifically done by the receiving functions / specifically done by the user.
+.. _function-argument-handling:
+
+.. note::
+
+ This also means that you should pass and receive arguments in certain ways to maximize efficiency. For example, ``sol::table``, ``sol::object``, ``sol::userdata`` and friends are fairly cheap to copy, and should simply by taken as values. This includes primitive types like ``int`` and ``double``. However, C++ types -- if you do not want copies -- should be taken as ``const type&`` or ``type&``, to save on copies if it's important. Note that taking references from Lua also means you can modify the data inside of Lua directly, so be careful. Lua by default deals with things mostly by reference (save for primitive types).
+
+ You can get even more speed out of ``sol::object`` style of types by taking a ``sol::stack_object`` (or ``sol::stack_...``, where ``...`` is ``userdata``, ``reference``, ``table``, etc.). These reference a stack position directly rather than cheaply/safely the internal Lua reference to make sure it can't be swept out from under you. Note that if you manipulate the stack out from under these objects, they may misbehave, so please do not blow up your Lua stack when working with these types.
+
+ ``std::string`` (and ``std::wstring``) are special. Lua stores strings as ``const char*`` null-terminated strings. ``std::string`` will copy, so taking a ``std::string`` by value or by const reference still invokes a copy operation. You can take a ``const char*``, but that will mean you're exposed to what happens on the Lua stack (if you change it and start chopping off function arguments from it in your function calls and such, as warned about previously).
+
+
function call safety
--------------------
diff --git a/3rdparty/sol2/docs/source/api/protected_function.rst b/3rdparty/sol2/docs/source/api/protected_function.rst
index 97d4e09f14f..c9fb9b4f425 100644
--- a/3rdparty/sol2/docs/source/api/protected_function.rst
+++ b/3rdparty/sol2/docs/source/api/protected_function.rst
@@ -183,3 +183,5 @@ The error-handler that is called should a runtime error that Lua can detect occu
.. note::
``protected_function_result`` safely pops its values off the stack when its destructor is called, keeping track of the index and number of arguments that were supposed to be returned. If you remove items below it using ``lua_remove``, for example, it will not behave as expected. Please do not perform fundamentally stack-rearranging operations until the destructor is called (pushing/popping above it is just fine).
+
+To know more about how function arguments are handled, see :ref:`this note<function-argument-handling>`.
diff --git a/3rdparty/sol2/docs/source/api/readonly.rst b/3rdparty/sol2/docs/source/api/readonly.rst
index 3a9517f1058..e36db3358ff 100644
--- a/3rdparty/sol2/docs/source/api/readonly.rst
+++ b/3rdparty/sol2/docs/source/api/readonly.rst
@@ -1,6 +1,6 @@
readonly
========
-Routine to mark a member variable as read-only
+routine to mark a member variable as read-only
----------------------------------------------
.. code-block:: cpp
@@ -8,4 +8,61 @@ Routine to mark a member variable as read-only
template <typename T>
auto readonly( T&& value );
-The goal of read-only is to protect a variable set on a usertype or a function. Simply wrap it around a member variable, e.g. ``sol::readonly( &my_class::my_member_variable )`` in the appropriate place to use it. If someone tries to set it, it will throw an error.
+The goal of read-only is to protect a variable set on a usertype or a function. Simply wrap it around a member variable, e.g. ``sol::readonly( &my_class::my_member_variable )`` in the appropriate place to use it. If someone tries to set it, it will throw an error. This can ONLY work on :doc:`usertypes<usertype>` and when you specifically set a member variable as a function and wrap it with this. It will NOT work anywhere else: doing so will invoke compiler errors.
+
+If you are looking to make a read-only table, you need to go through a bit of a complicated song and dance by overriding the ``__index`` metamethod. Here's a complete example on the way to do that using ``sol``:
+
+
+.. code-block:: cpp
+ :caption: read-only.cpp
+
+ #define SOL_CHECK_ARGUMENTS
+ #include <sol.hpp>
+
+ #include <iostream>
+
+ struct object {
+ void my_func() {
+ std::cout << "hello\n";
+ }
+ };
+
+ int deny(lua_State* L) {
+ return luaL_error(L, "HAH! Deniiiiied!");
+ }
+
+ int main() {
+ sol::state lua;
+ lua.open_libraries(sol::lib::base);
+
+ object my_obj;
+
+ sol::table obj_table = lua.create_named_table("object");
+
+ sol::table obj_metatable = lua.create_table_with();
+ obj_metatable.set_function("my_func", &object::my_func, &my_obj);
+ // Set whatever else you need to
+ // on the obj_metatable,
+ // not on the obj_table itself!
+
+ // Properly self-index metatable to block things
+ obj_metatable[sol::meta_function::new_index] = deny;
+ obj_metatable[sol::meta_function::index] = obj_metatable;
+
+ // Set it on the actual table
+ obj_table[sol::metatable_key] = obj_metatable;
+
+ try {
+ lua.script(R"(
+ print(object.my_func)
+ object["my_func"] = 24
+ print(object.my_func)
+ )");
+ }
+ catch (const std::exception& e) {
+ std::cout << e.what() << std::endl;
+ }
+ return 0;
+ }
+
+It is a verbose example, but it explains everything. Because the process is a bit involved and can have unexpected consequences for users that make their own tables, making read-only tables is something that we ask the users to do themselves with the above code, as getting the semantics right for the dozens of use cases would be tremendously difficult.
diff --git a/3rdparty/sol2/docs/source/api/simple_usertype.rst b/3rdparty/sol2/docs/source/api/simple_usertype.rst
index e030ed92985..0502e6b24ed 100644
--- a/3rdparty/sol2/docs/source/api/simple_usertype.rst
+++ b/3rdparty/sol2/docs/source/api/simple_usertype.rst
@@ -1,4 +1,4 @@
-simple_usertype
+simple_usertype<T>
==================
structures and classes from C++ made available to Lua code (simpler)
--------------------------------------------------------------------
@@ -6,11 +6,28 @@ structures and classes from C++ made available to Lua code (simpler)
This type is no different from :doc:`regular usertype<usertype>`, but allows much of its work to be done at runtime instead of compile-time. You can reduce compilation times from a plain `usertype` when you have an exceedingly bulky registration listing.
-You can set functions incrementally to reduce compile-time burden with ``simple_usertype`` as well, as shown in `this example`_.
+You can set functions incrementally to reduce compile-time burden with ``simple_usertype`` as well, as shown in `this example`_. This means both adding incrementally during registration, and afterwards by adding items to the metatable at runtime.
+
+Some developers used ``simple_usertype`` in older versions to have variables automatically be functions. To achieve this behavior, wrap the desired variable into :doc:`sol::as_function<as_function>`.
+
+The performance `seems to be good enough`_ (see below graphs as well) to not warn about any implications of having to serialize things at runtime. You do run the risk of using (slightly?) more memory, since variables and functions need to be stored differently and separately from the metatable data itself like with a regular ``usertype``. The goal here was to avoid compiler complaints about too-large usertypes (some individuals needed to register 190+ functions, and the compiler choked from the templated implementation of ``usertype``). As of Sol 2.14, this implementation has been heavily refactored to allow for all the same syntax and uses of usertype to apply here, with no caveats/exceptions.
+
+
+.. image:: https://raw.githubusercontent.com/ThePhD/lua-bench/master/lua%20-%20results/lua%20bench%20graph%20-%20member%20function%20calls%20(simple).png
+ :target: https://raw.githubusercontent.com/ThePhD/lua-bench/master/lua%20-%20results/lua%20bench%20graph%20-%20member%20function%20calls%20(simple).png
+ :alt: bind several member functions to an object and call them in Lua code
+
+
+.. image:: https://raw.githubusercontent.com/ThePhD/lua-bench/master/lua%20-%20results/lua%20bench%20graph%20-%20userdata%20variable%20access%20(simple).png
+ :target: https://raw.githubusercontent.com/ThePhD/lua-bench/master/lua%20-%20results/lua%20bench%20graph%20-%20userdata%20variable%20access%20(simple).png
+ :alt: bind a member variable to an object and modify it with Lua code
+
+
+.. image:: https://raw.githubusercontent.com/ThePhD/lua-bench/master/lua%20-%20results/lua%20bench%20graph%20-%20many%20userdata%20variables%20access%2C%20last%20registered%20(simple).png
+ :target: https://raw.githubusercontent.com/ThePhD/lua-bench/master/lua%20-%20results/lua%20bench%20graph%20-%20many%20userdata%20variables%20access%2C%20last%20registered%20(simple).png
+ :alt: bind MANY member variables to an object and modify it with Lua code
-Some developers used ``simple_usertype`` to have variables automatically be functions. To achieve this behavior, wrap the desired variable into :doc:`sol::as_function<as_function>`.
-The performance `seems to be good enough`_ to not warn about any implications of having to serialize things at runtime. You do run the risk of using (slightly?) more memory, however, since variables and functions need to be stored differently and separately from the metatable data itself like with a regular ``usertype``. The goal here was to avoid compiler complaints about too-large usertypes (some individuals needed to register 190+ functions, and the compiler choked from the templated implementation of ``usertype``). As of Sol 2.14, this implementation has been heavily refactored to allow for all the same syntax and uses of usertype to apply here, with no caveats/exceptions.
.. _seems to be good enough: https://github.com/ThePhD/sol2/issues/202#issuecomment-246767629
.. _this example: https://github.com/ThePhD/sol2/blob/develop/examples/usertype_simple.cpp \ No newline at end of file
diff --git a/3rdparty/sol2/docs/source/api/state.rst b/3rdparty/sol2/docs/source/api/state.rst
index b593d5cc810..a0838fbf110 100644
--- a/3rdparty/sol2/docs/source/api/state.rst
+++ b/3rdparty/sol2/docs/source/api/state.rst
@@ -53,6 +53,7 @@ This function takes a number of :ref:`sol::lib<lib-enum>` as arguments and opens
.. code-block:: cpp
:caption: function: script / script_file
+ :name: state-script-function
sol::function_result script(const std::string& code);
sol::function_result script_file(const std::string& filename);
@@ -83,6 +84,15 @@ Thanks to `Eric (EToreo) for the suggestion on this one`_!
These functions *load* the desired blob of either code that is in a string, or code that comes from a filename, on the ``lua_State*``. It will not run: it returns a ``load_result`` proxy that can be called to actually run the code, turned into a ``sol::function``, a ``sol::protected_function``, or some other abstraction. If it is called, it will run on the object's current ``lua_State*``: it is not isolated. If you need isolation, consider creating a new state or traditional Lua sandboxing techniques.
.. code-block:: cpp
+ :caption: function: do_string / do_file
+ :name: state-do-code
+
+ sol::protected_function_result do_string(const std::string& code);
+ sol::protected_function_result do_file(const std::string& filename);
+
+These functions *loads and performs* the desired blob of either code that is in a string, or code that comes from a filename, on the ``lua_State*``. It *will* run, and then return a ``protected_function_result`` proxy that can be examined for either an error or the return value.
+
+.. code-block:: cpp
:caption: function: global table / registry table
sol::global_table globals() const;
@@ -97,7 +107,7 @@ Get either the global table or the Lua registry as a :doc:`sol::table<table>`, w
void set_panic(lua_CFunction panic);
-Overrides the panic function Lua calls when something unrecoverable or unexpected happens in the Lua VM. Must be a function of the that matches the ``int(*)(lua_State*)`` function signature.
+Overrides the panic function Lua calls when something unrecoverable or unexpected happens in the Lua VM. Must be a function of the that matches the ``int(lua_State*)`` function signature.
.. code-block:: cpp
:caption: function: make a table
diff --git a/3rdparty/sol2/docs/source/api/usertype.rst b/3rdparty/sol2/docs/source/api/usertype.rst
index d3282cd5c64..2fa73a320a2 100644
--- a/3rdparty/sol2/docs/source/api/usertype.rst
+++ b/3rdparty/sol2/docs/source/api/usertype.rst
@@ -5,7 +5,7 @@ structures and classes from C++ made available to Lua code
*Note: ``T`` refers to the type being turned into a usertype.*
-While other frameworks extend lua's syntax or create Data Structure Languages (DSLs) to create classes in lua, :doc:`sol<../index>` instead offers the ability to generate easy bindings. These use metatables and userdata in lua for their implementation. Given this C++ class:
+While other frameworks extend lua's syntax or create Data Structure Languages (DSLs) to create classes in lua, :doc:`Sol<../index>` instead offers the ability to generate easy bindings. These use metatables and userdata in lua for their implementation. If you need a usertype that is also extensible at runtime and has less compiler crunch to it, try the :doc:`simple version of this after reading these docs<simple_usertype>` Given this C++ class:
.. code-block:: cpp
:linenos:
diff --git a/3rdparty/sol2/docs/source/api/usertype_memory.rst b/3rdparty/sol2/docs/source/api/usertype_memory.rst
index 55734f7e543..e3a82ed120e 100644
--- a/3rdparty/sol2/docs/source/api/usertype_memory.rst
+++ b/3rdparty/sol2/docs/source/api/usertype_memory.rst
@@ -5,7 +5,7 @@ usertype memory
Sol does not take ownership of raw pointers, returned from functions or set through the ``set`` functions. Return a value, a ``std::unique_ptr``, a ``std::shared_ptr`` of some kind, or hook up the :doc:`unique usertypes traits<unique_usertype_traits>` to work for some specific handle structure you use (AKA, for ``boost::shared_ptr``).
-The userdata generated by Sol has a specific layout, depending on how Sol recognizes userdata passed into it. All of the referred to metatable names are generated from :ref:`usertype_traits\<T><usertype-traits>`
+The userdata generated by Sol has a specific layout, depending on how Sol recognizes userdata passed into it. All of the referred to metatable names are generated from :ref:`usertype_traits\<T><usertype-traits>`. Note that we use 1 metatable per the 3 styles listed below, plus 1 additional metatable that is used for the actual table that you bind with the name when calling ``table::new/set_(simple_)usertype``.
In general, we always insert a T* in the first `sizeof(T*)` bytes, so the any framework that pulls out those first bytes expecting a pointer will work. The rest of the data has some different alignments and contents based on what it's used for and how it's used.
@@ -37,11 +37,11 @@ That is it. No destruction semantics need to be called.
For ``std::unique_ptr<T, D>`` and ``std::shared_ptr<T>``
--------------------------------------------------------
-These are classified as :ref:`"unique usertypes"<unique-usertype>`, and have a special metatable for them as well. The special metatable is either generated when you add the usertype to Lua using :ref:`set_usertype<set-usertype>` or when you first push one of these special types. In addition to the data, a deleter function that understands the following layout is injected into the usertype.
+These are classified as :ref:`"unique usertypes"<unique-usertype>`, and have a special metatable for them as well. The special metatable is either generated when you add the usertype to Lua using :ref:`set_usertype<set-usertype>` or when you first push one of these special types. In addition to the data, a deleter function that understands the following layout is injected into the userdata layout.
The data layout for these kinds of types is as follows::
| T* | void(*)(void*) function_pointer | T |
^-sizeof(T*) bytes-^-sizeof(void(*)(void*)) bytes, deleter-^- sizeof(T) bytes, actal data -^
-Note that we put a special deleter function before the actual data. This is because the custom deleter must know where the offset to the data is, not the rest of the library. Sol just needs to know about ``T*`` and the userdata (and userdata metatable) to work, everything else is for preserving construction / destruction semantics. \ No newline at end of file
+Note that we put a special deleter function before the actual data. This is because the custom deleter must know where the offset to the data is and where the special deleter is. In other words, fixed-size-fields come before any variably-sized data (T can be known at compile time, but when serialized into Lua in this manner it becomes a runtime entity). Sol just needs to know about ``T*`` and the userdata (and userdata metatable) to work, everything else is for preserving construction / destruction semantics. \ No newline at end of file
diff --git a/3rdparty/sol2/docs/source/benchmarks.rst b/3rdparty/sol2/docs/source/benchmarks.rst
index f85277b6df1..6fa3224ffda 100644
--- a/3rdparty/sol2/docs/source/benchmarks.rst
+++ b/3rdparty/sol2/docs/source/benchmarks.rst
@@ -21,12 +21,12 @@ Bars go up to the average execution time. Lower is better. Reported times are fo
:target: https://raw.githubusercontent.com/ThePhD/lua-bench/master/lua%20-%20results/lua%20bench%20graph%20-%20member%20function%20calls.png
:alt: bind several member functions to an object and call them in Lua code
-.. image:: https://raw.githubusercontent.com/ThePhD/lua-bench/master/lua%20-%20results/lua%20bench%20graph%20-%20member%20variable.png
- :target: https://raw.githubusercontent.com/ThePhD/lua-bench/master/lua%20-%20results/lua%20bench%20graph%20-%20member%20variable.png
+.. image:: https://raw.githubusercontent.com/ThePhD/lua-bench/master/lua%20-%20results/lua%20bench%20graph%20-%20userdata%20variable%20access.png
+ :target: https://raw.githubusercontent.com/ThePhD/lua-bench/master/lua%20-%20results/lua%20bench%20graph%20-%20userdata%20variable%20access.png
:alt: bind a variable to an object and call it in Lua code
-.. image:: https://raw.githubusercontent.com/ThePhD/lua-bench/master/lua%20-%20results/lua%20bench%20graph%20-%20member%20variable.png
- :target: https://raw.githubusercontent.com/ThePhD/lua-bench/master/lua%20-%20results/lua%20bench%20graph%20-%20many%20member%20variables.png
+.. image:: https://raw.githubusercontent.com/ThePhD/lua-bench/master/lua%20-%20results/lua%20bench%20graph%20-%20many%20userdata%20variables%20access.png
+ :target: https://raw.githubusercontent.com/ThePhD/lua-bench/master/lua%20-%20results/lua%20bench%20graph%20-%20many%20userdata%20variables%20access.png
:alt: bind MANY variables to an object and call it in Lua code
.. image:: https://raw.githubusercontent.com/ThePhD/lua-bench/master/lua%20-%20results/lua%20bench%20graph%20-%20c%20function%20through%20lua.png
diff --git a/3rdparty/sol2/docs/source/conf.py b/3rdparty/sol2/docs/source/conf.py
index 63733022b90..9b78b5d59b6 100644
--- a/3rdparty/sol2/docs/source/conf.py
+++ b/3rdparty/sol2/docs/source/conf.py
@@ -59,9 +59,9 @@ author = 'ThePhD'
# built documents.
#
# The short X.Y version.
-version = '2.14'
+version = '2.15'
# The full version, including alpha/beta/rc tags.
-release = '2.14.8'
+release = '2.15.0'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
diff --git a/3rdparty/sol2/docs/source/errors.rst b/3rdparty/sol2/docs/source/errors.rst
new file mode 100644
index 00000000000..f017daad328
--- /dev/null
+++ b/3rdparty/sol2/docs/source/errors.rst
@@ -0,0 +1,35 @@
+errors
+======
+how to handle exceptions or other errors
+----------------------------------------
+
+Here is some advice and some tricks to use when dealing with thrown exceptions, error conditions and the like in Sol.
+
+Catch and CRASH!
+----------------
+
+By default, Sol will add a ``default_at_panic`` handler. If exceptions are not turned off, this handler will throw to allow the user a chance to recover. However, in almost all cases, when Lua calls ``lua_atpanic`` and hits this function, it means that something *irreversibly wrong* occured in your code or the Lua code and the VM is in an unpredictable or dead state. Catching an error thrown from the default handler and then proceeding as if things are cleaned up or okay is NOT the best idea. Unexpected bugs in optimized and release mode builds can result, among other serious issues.
+
+
+It is preferred if you catch an error that you log what happened, terminate the Lua VM as soon as possible, and then crash if your application cannot handle spinning up a new Lua state. Catching can be done, but you should understand the risks of what you're doing when you do it.
+
+
+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.
+
+
+Protected Functions and Access
+------------------------------
+
+By default, :doc:`sol::function<api/function>` assumes the code ran just fine and there are no problems. :ref:`sol::state(_view)::script(_file)<state-script-function>` also assumes that code ran just fine. Use :doc:`sol::protected_function<api/protected_function>` to have function access where you can check if things worked out. Use :doc:`sol::optional<api/optional>` to get a value safely from Lua. Use :ref:`sol::state(_view)::do_string/do_file/load/load_file<state-do-code>` to safely load and get results from a script. The defaults are provided to be simple and fast with thrown exceptions to violently crash the VM in case things go wrong.
+
+Raw Functions
+-------------
+
+When you push a function into Lua using Sol using any methods and that function exactly matches the signature ``int( lua_State* );``, it will be treated as a *raw C function*. This means that the usual exception trampoline Sol wraps your other function calls in will not be present. You will be responsible for catching exceptions and handling them before they explode into the C API (and potentially destroy your code). Sol in all other cases adds an exception-handling trampoline that turns exceptions into Lua errors that can be caught by the above-mentioned protected functions and accessors.
+
+.. warning::
+
+ Do NOT assume that building Lua as C++ will allow you to throw directly from a raw function. If an exception is raised and it bubbles into the Lua framework, even if you compile as C++, Lua does not recognize exceptions other than the ones that it uses with ``lua_error``. In other words, it will return some completely bogus result, potentially leave your Lua stack thrashed, and the rest of your VM *can* be in a semi-trashed state. Please avoid this!
diff --git a/3rdparty/sol2/docs/source/features.rst b/3rdparty/sol2/docs/source/features.rst
index 527398af374..6d52e317eeb 100644
--- a/3rdparty/sol2/docs/source/features.rst
+++ b/3rdparty/sol2/docs/source/features.rst
@@ -78,7 +78,7 @@ Explanations for a few categories are below (rest are self-explanatory).
* arbitrary keys: Letting C++ code use userdata, other tables, integers, etc. as keys for into a table.
* user-defined types (udts): C++ types given form and function in Lua code.
* udts - member functions: C++ member functions on a type, usually callable with ``my_object:foo(1)`` or similar in Lua.
-* udts - variables: C++ member variables, manipulated by ``my_object.var = 24`` and friends
+* udts - table variables: C++ member variables/properties, manipulated by ``my_object.var = 24`` and in Lua
* function binding: Support for binding all types of functions. Lambdas, member functions, free functions, in different contexts, etc...
* protected function: Use of ``lua_pcall`` to call a function, which offers error-handling and trampolining (as well as the ability to opt-in / opt-out of this behavior)
* multi-return: returning multiple values from and to Lua (generally through ``std::tuple<...>`` or in some other way)
@@ -104,7 +104,7 @@ Explanations for a few categories are below (rest are self-explanatory).
+---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+--------+
| udts: member functions | ~ | ✔ | ✔ | ✔ | ✔ | ✔ | ~ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
+---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+--------+
-| udts: variables | ~ | ~ | ~ | ~ | ~ | ✔ | ~ | ~ | ~ | ✗ | ✔ | ✗ | ~ |
+| udts: table variables | ~ | ~ | ~ | ~ | ~ | ✔ | ~ | ~ | ~ | ✗ | ✔ | ✗ | ~ |
+---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+--------+
| stack abstractions | ~ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ~ | ✗ | ~ | ✔ |
+---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+--------+
@@ -138,7 +138,7 @@ Explanations for a few categories are below (rest are self-explanatory).
+---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+--------+
| luajit | ✔ | ✔ | ✔ | ✔ | ~ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✗ | ✔ |
+---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+--------+
-| distribution | compile | header | both | compile | header | header | compile | compile | header | compile | generated | compile | header |
+| distribution | compile | header | both | compile | header | header | compile | compile | header | compile | generated | compile | header |
+---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+--------+
@@ -153,7 +153,7 @@ Plain C -
kaguya -
-* member variables are automatically turned into ``obj:x( value )`` to set and ``obj:x()`` to get
+* Table variables / member variables are automatically turned into ``obj:x( value )`` to set and ``obj:x()`` to get
* Has optional support
* Inspired coroutine support for Sol
* Library author (satoren) is a nice guy!
@@ -177,12 +177,12 @@ lua-intf -
* Macro-based registration (strange pseudo-language)
* Fairly fast in most regards
* Registering classes/"modules" in using C++ code is extremely verbose
-* In order to chain lookups, one has to do ``mykey.mykey2`` on the ``operator[]`` lookup (e.g., you can't nest them arbitrarily, you have to pre-compose the proper lookup string) (fails miserably for non-string lookups!).
+* In order to chain lookups, one has to glue the keys together (e.g. ``"mykey.mykey2"``) on the ``operator[]`` lookup (e.g., you can't nest them arbitrarily, you have to pre-compose the proper lookup string) (fails miserably for non-string lookups!).
* Not too shabby!
Selene -
-* member variables are automatically turned into ``obj:set_x( value )`` to set and ``obj:x()`` to get
+* Table variables / member variables are automatically turned into ``obj:set_x( value )`` to set and ``obj:x()`` to get
* Registering classes/"modules" using C++ code is extremely verbose, similar to lua-intf's style
* Eats crap when it comes to performance, most of the time (see :doc:`benchmarks<benchmarks>`)
* Lots of users (blogpost etc. made it popular), but the Repository is kinda stagnant...
@@ -204,7 +204,7 @@ SWIG (3.0) -
luacppinterface -
* The branch that fixes VC++ warnings and introduces some new work has type checker issues, so use the stable branch only
-* No member variable support
+* No table variable support
* Actually has tables (but no operator[])
* Does not support arbitrary keys
@@ -238,13 +238,13 @@ SLB3 -
oolua -
-* The syntax for this library is thicker than a brick. No, seriously. `Go read the docs`_
+* The syntax for this library. `Go read the docs`_
* The worst in terms of how to use it: may have docs, but the DSL is extraordinarily crappy with thick, hard-to-debug/hard-to-error-check macros
- Same problem as lua-api-pp: cannot have the declaration macros anywhere but the toplevel namespace because of template declaration macro
* Supports not having exceptions or rtti turned on (shiny!)
* Poor RAII support: default-construct-and-get style (requires some form of initalization to perform a ``get`` of an object, and it's hard to extend)
- The library author has informed me that he does personally advises individuals do not use the ``Table`` abstraction in OOLua... Do I likewise tell people to consider its table abstractions defunct?
-* Member variables are turned into function calls (``get_x`` and ``set_x`` by default)
+* Table variables / member variables from C++ are turned into function calls (``get_x`` and ``set_x`` by default)
luwra -
@@ -253,6 +253,7 @@ luwra -
* Doesn't understand ``std::function`` conversions and the like (but with some extra code can get it to work)
* Recently improved by a lot: can chain tables and such, even if performance is a bit sad for that use case
* When you do manage to set function calls with the macros they are fast (can a template solution do just as good? Sol is going to find out!)
-* No member variable support - get turned into getter/setter functions, similar to kaguya
+* No table variable support - get turned into getter/setter functions, similar to kaguya
+* Table variables become class statics (surprising)
.. _Go read the docs: https://oolua.org/docs/index.html
diff --git a/3rdparty/sol2/docs/source/index.rst b/3rdparty/sol2/docs/source/index.rst
index b1ec3a4f276..ca5233398c7 100644
--- a/3rdparty/sol2/docs/source/index.rst
+++ b/3rdparty/sol2/docs/source/index.rst
@@ -7,8 +7,8 @@
:target: https://github.com/ThePhD/sol2
:alt: sol2 repository
-Sol 2.14
-========
+Sol |version|
+=============
a fast, simple C++ and Lua Binding
----------------------------------
@@ -18,6 +18,11 @@ When you need to hit the ground running with Lua and C++, `Sol`_ is the go-to fr
:target: https://travis-ci.org/ThePhD/sol2
:alt: build status
+.. image:: https://badges.gitter.im/chat-sol2/Lobby.svg
+ :target: https://gitter.im/chat-sol2/Lobby
+ :alt: chat about sol2 on gitter
+
+
get going:
----------
@@ -27,7 +32,10 @@ get going:
tutorial/all-the-things
tutorial/tutorial-top
+ errors
features
+ usertypes
+ traits
api/api-top
mentions
benchmarks
@@ -43,7 +51,7 @@ get going:
"I need feature X, maybe you have it?"
--------------------------------------
-Take a look at the :doc:`Features<features>` page: it links to much of the API. You can also just straight up browse the :doc:`api<api/api-top>` or ease in with the :doc:`tutorials<tutorial/tutorial-top>`. Don't see a feature you want? Send inquiries for support for a particular abstraction to the `issues`_ tracker.
+Take a look at the :doc:`Features<features>` page: it links to much of the API. You can also just straight up browse the :doc:`api<api/api-top>` or ease in with the :doc:`tutorials<tutorial/tutorial-top>`. To know more about the implementation for usertypes, see :doc:`here<usertypes>` To know how function arguments are handled, see :ref:`this note<function-argument-handling>`. Don't see a feature you want? Send inquiries for support for a particular abstraction to the `issues`_ tracker.
the basics:
diff --git a/3rdparty/sol2/docs/source/mentions.rst b/3rdparty/sol2/docs/source/mentions.rst
index 7b920150181..72330a8a5a9 100644
--- a/3rdparty/sol2/docs/source/mentions.rst
+++ b/3rdparty/sol2/docs/source/mentions.rst
@@ -3,6 +3,8 @@ mentions
so does anyone cool use this thing...?
--------------------------------------
+First off, feel free to `tell me about your uses!`_
+
Okay, so the features don't convince you, the documentation doesn't convince you, you want to see what *other* people think about Sol? Well, aside from the well-wishes that come through in the issue tracker, here's a few things floating around about sol2 that I occasionally get pinged about:
`eevee`_ demonstrating the sheer code reduction by using sol2:
@@ -24,27 +26,34 @@ Okay, so the features don't convince you, the documentation doesn't convince you
* (CppNow) sol2 was mentioned in a comparison to other scripting languages by ChaiScript developer, Jason Turner (@lefticus), at a conference!
- - https://github.com/lefticus/presentations/blob/master/HowAndWhyToAddScripting.md
+ - `Jason Turner's presentation`_
* (CppCast) Showed up in CppCast with Elias Daler!
- - https://eliasdaler.github.io/cppcast#read-more
- - http://cppcast.com/2016/07/elias-daler/
+ - `Elias Daler's blog`_
+ - `CppCast`_
* (Eevee) A really nice and neat developer/artist/howaretheysotalented person is attempting to use it for zdoom!
- - https://eev.ee/dev/2016/08/07/weekly-roundup-three-big-things/
+ - `eevee's blog`_
* (Twitter) Twitter has some people that link it:
- - https://twitter.com/eevee/status/762039984085798913
- - https://twitter.com/thephantomderp/status/762043162835709952
- - https://twitter.com/EliasDaler/status/739082026679173120
- - https://twitter.com/racodslair/status/754031870640267264
+ - The image above, `tweeted out by eevee`_
+ - Eevee: `"I heartily recommend sol2"`_
+ - Elias Daler: `"sol2 saved my life."`_
+ - Racod's Lair: `"from outdated LuaBridge to superior #sol2"`_
* (Reddit) Posts on reddit about it!
- - https://www.reddit.com/r/cpp/comments/4a8gy7/sol2_lua_c_binding_framework/
- - https://www.reddit.com/r/cpp/comments/4x82hd/plain_c_versus_lua_libraries_benchmarking_speed/
+ - `sol2's initial reddit release`_
+ - `Benchmarking Discussing`_
* Somehow landed on a Torque3D thread...
- http://forums.torque3d.org/viewtopic.php?f=32&t=629&p=5246&sid=8e759990ab1ce38a48e896fc9fd62653#p5241
-
-`Tell me about your uses!`_
-
Are you using sol2 for something neat? Want it to be featured here or think it's unfair that ThePhD hasn't found it yet? Well, drop an issue in the repo or send an e-mail!
-.. _Tell me about your uses!: https://github.com/ThePhD/sol2/issues/189
-.. _eevee: https://twitter.com/eevee \ No newline at end of file
+.. _tell me about your uses!: https://github.com/ThePhD/sol2/issues/189
+.. _eevee: https://twitter.com/eevee
+.. _eevee's blog: https://eev.ee/dev/2016/08/07/weekly-roundup-three-big-things/
+.. _Jason Turner's presentation: https://github.com/lefticus/presentations/blob/master/HowAndWhyToAddScripting.md
+.. _Elias Daler's blog: https://eliasdaler.github.io/cppcast#read-more
+.. _CppCast: http://cppcast.com/2016/07/elias-daler/
+.. _tweeted out by eevee: https://twitter.com/eevee/status/762039984085798913
+.. _"I heartily recommend sol2": https://twitter.com/eevee/status/762040086540144644
+.. _"from outdated LuaBridge to superior #sol2": https://twitter.com/racodslair/status/754031870640267264
+.. _sol2's initial reddit release: https://www.reddit.com/r/cpp/comments/4a8gy7/sol2_lua_c_binding_framework/
+.. _Benchmarking Discussing: https://www.reddit.com/r/cpp/comments/4x82hd/plain_c_versus_lua_libraries_benchmarking_speed/
+.. _"sol2 saved my life.": https://twitter.com/EliasDaler/status/739215685264494593
diff --git a/3rdparty/sol2/docs/source/performance.rst b/3rdparty/sol2/docs/source/performance.rst
index cdfaa9614e6..534ab7e5a3e 100644
--- a/3rdparty/sol2/docs/source/performance.rst
+++ b/3rdparty/sol2/docs/source/performance.rst
@@ -7,6 +7,7 @@ things to make Sol as fast as possible
As shown by the :doc:`benchmarks<benchmarks>`, Sol is very performant with its abstractions. However, in the case where you need every last drop of performance from Sol, a number of tips and API usage tricks will be documented here. PLEASE benchmark / profile your code before you start invoking these, as some of them trade in readability / clarity for performance.
* If you have a bound function call / bound member function that you are going to call in a very tight, performance-heavy loop, considering using :doc:`sol::c_call<api/c_call>`
+* Be wary of passing by value / reference, and what it means by reading :ref:`this note<function-argument-handling>`.
* It is currently undocumented that usertypes will "inherit" member function / member variables from bound classes, mostly because the semantics are unclear and it is not the most performant (although it is flexible: you can register base classes after / whenever you want in relation to the derived class, provided that derived class has its bases listed). Specifying all member functions / member variables for the usertype constructor / ``new_usertype`` function call and not relying on base lookup will boost performance of member lookup
* Specifying base classes can make getting the usertype out of Sol a bit slower since we have to check and cast; if you know the exact type wherever you're retrieving it, considering not specifying the bases, retrieving the exact type from Sol, and then casting to a base type yourself
* Member variables can sometimes cost an extra lookup to occur within the Lua system (as mentioned :doc:`bottom of the usertype page<api/usertype>`); until we find out a safe way around this, member variables will always incur that extra lookup cost
diff --git a/3rdparty/sol2/docs/source/traits.rst b/3rdparty/sol2/docs/source/traits.rst
new file mode 100644
index 00000000000..b064223be08
--- /dev/null
+++ b/3rdparty/sol2/docs/source/traits.rst
@@ -0,0 +1,15 @@
+customization traits
+====================
+
+These are customization points within the library to help you make sol2 work for the types in your framework and types.
+
+To learn more about various customizable traits, visit:
+
+* :ref:`containers detection trait<container-detection>`
+ - This is how to work with containers when you have an compiler error when serializing a type that has ``begin`` and ``end`` functions but isn't exactly a container.
+* :doc:`unique usertype (custom pointer) traits<api/unique_usertype_traits>`
+ - This is how to deal with unique usertypes, e.g. ``boost::shared_ptr``, reference-counted pointers, etc.
+ - Useful for custom pointers from all sorts of frameworks or handle types that employ very specific kinds of destruction semantics and access.
+* :doc:`customization point tutorial<tutorial/customization>`
+ - This is how to customize a type to work with sol2.
+ - Can be used for specializations to push strings and other class types that are not natively ``std::string`` or ``const char*``.
diff --git a/3rdparty/sol2/docs/source/tutorial/all-the-things.rst b/3rdparty/sol2/docs/source/tutorial/all-the-things.rst
index fa9e73ac6c0..3695ac77fe2 100644
--- a/3rdparty/sol2/docs/source/tutorial/all-the-things.rst
+++ b/3rdparty/sol2/docs/source/tutorial/all-the-things.rst
@@ -47,6 +47,10 @@ running lua code
int value = lua.script("return 54");
// value == 54
+To check the success of a loading operation:
+
+.. code-block:: cpp
+
// load file without execute
sol::load_result script1 = lua.load_file("path/to/luascript.lua");
script1(); //execute
@@ -59,6 +63,24 @@ running lua code
// value2 == 24
+To check whether a script was successfully run or not (after loading is assumed to be successful):
+
+.. code-block:: cpp
+
+ // execute and return result
+ sol::protected_function_result result1 = lua.do_string("return 24");
+ if (result1.valid()) {
+ int value = result1;
+ // value == 24
+ // yay!
+ }
+ else {
+ // ahhh :c
+ }
+
+
+There is also ``lua.do_file("path/to/luascript.lua");``.
+
set and get variables
---------------------
diff --git a/3rdparty/sol2/docs/source/tutorial/customization.rst b/3rdparty/sol2/docs/source/tutorial/customization.rst
index 31fcad46568..5479c804115 100644
--- a/3rdparty/sol2/docs/source/tutorial/customization.rst
+++ b/3rdparty/sol2/docs/source/tutorial/customization.rst
@@ -108,6 +108,9 @@ A few things of note about the implementation: First, there's an auxiliary param
You can make something pushable into Lua, but not get-able in the same way if you only specialize one part of the system. If you need to retrieve it (as a return using one or multiple values from Lua), you should specialize the ``sol::stack::getter`` template class and the ``sol::stack::checker`` template class. If you need to push it into Lua at some point, then you'll want to specialize the ``sol::stack::pusher`` template class. The ``sol::lua_size`` template class trait needs to be specialized for both cases, unless it only pushes 1 item, in which case the default implementation will assume 1.
+.. note::
+
+ It is important to note here that the ``getter``, ``pusher`` and ``checker`` differentiate between a type ``T`` and a pointer to a type ``T*``. This means that if you want to work purely with, say, a ``T*`` handle that does not have the same semantics as just ``T``, you may need to specify checkers/getters/pushers for both ``T*`` and ``T``. The checkers for ``T*`` forward to the checkers for ``T``, but the getter for ``T*`` does not forward to the getter for ``T`` (e.g., because of ``int*`` not being quite the same as ``int``).
In general, this is fine since most getters/checkers only use 1 stack point. But, if you're doing more complex nested classes, it would be useful to use ``tracking.last`` to understand how many stack indices the last getter/checker operation did and increment it by ``index + tracking.last`` after using a ``stack::check<..>( L, index, tracking)`` call.
diff --git a/3rdparty/sol2/docs/source/tutorial/functions.rst b/3rdparty/sol2/docs/source/tutorial/functions.rst
index 2b2f0e3ba61..5fa8d823fd3 100644
--- a/3rdparty/sol2/docs/source/tutorial/functions.rst
+++ b/3rdparty/sol2/docs/source/tutorial/functions.rst
@@ -338,4 +338,4 @@ It can be used like so, inconjunction with ``sol::this_state``:
}
-This covers almost everything you need to know about Functions and how they interact with Sol. For some advanced tricks and neat things, check out :doc:`sol::this_state<../api/this_state>` and :doc:`sol::variadic_args<../api/variadic_args>`. The next stop in this tutorial is about :doc:`C++ types (usertypes) in Lua<cxx-in-lua>`! \ No newline at end of file
+This covers almost everything you need to know about Functions and how they interact with Sol. For some advanced tricks and neat things, check out :doc:`sol::this_state<../api/this_state>` and :doc:`sol::variadic_args<../api/variadic_args>`. The next stop in this tutorial is about :doc:`C++ types (usertypes) in Lua<cxx-in-lua>`! If you need a bit more information about functions in the C++ side and how to best utilize arguments from C++, see :ref:`this note<function-argument-handling>`. \ No newline at end of file
diff --git a/3rdparty/sol2/docs/source/tutorial/getting-started.rst b/3rdparty/sol2/docs/source/tutorial/getting-started.rst
index fd83e4fcb93..02fc2daadf0 100644
--- a/3rdparty/sol2/docs/source/tutorial/getting-started.rst
+++ b/3rdparty/sol2/docs/source/tutorial/getting-started.rst
@@ -5,14 +5,9 @@ Let's get you going with Sol! To start, you'll need to use a lua distribution of
If you need help getting or building Lua, check out the `Lua page on getting started`_. Note that for Visual Studio, one can simply download the sources, include all the Lua library files in that project, and then build for debug/release, x86/x64/ARM rather easily and with minimal interference. Just make sure to adjust the Project Property page to build as a static library (or a DLL with the proper define set in the ``Preprocessor`` step).
-After that, make sure you grab either the `single header file release`_, or just perform a clone of the `github repository here`_ and set your include paths up so that you can get at ``sol.hpp`` somehow. Note that we also have the latest version of the single header file with all dependencies included kept in the `repository as well`_. We recommend the single-header-file release, since it's easier to move around, manage and update if you commit it with some form of version control. If you use the github clone method and do not point to the `single/sol/sol.hpp`_ on your include files, you *must* update submodules in order to make sure Optional is present in the repository. Clone with:
+After that, make sure you grab either the `single header file release`_, or just perform a clone of the `github repository here`_ and set your include paths up so that you can get at ``sol.hpp`` somehow. Note that we also have the latest version of the single header file with all dependencies included kept in the `repository as well`_. We recommend the single-header-file release, since it's easier to move around, manage and update if you commit it with some form of version control. You can also clone/submodule the repository and then point at the `single/sol/sol.hpp`_ on your include files path. Clone with:
>>> git clone https://github.com/ThePhD/sol2.git
->>> git submodule update --init
-
-or, just run
-
->>> git clone --recursive https://github.com/ThePhD/sol2.git
When you're ready, try compiling this short snippet:
diff --git a/3rdparty/sol2/docs/source/usertypes.rst b/3rdparty/sol2/docs/source/usertypes.rst
new file mode 100644
index 00000000000..89bf1d36a86
--- /dev/null
+++ b/3rdparty/sol2/docs/source/usertypes.rst
@@ -0,0 +1,26 @@
+usertypes
+=========
+
+Perhaps the most powerful feature of sol2, ``usertypes`` are the way sol2 and C++ communicate your classes to the Lua runtime and bind things between both tables and to specific blocks of C++ memory, allowing you to treat Lua userdata and other things like classes.
+
+To learn more about usertypes, visit:
+
+* :doc:`the basic tutorial<tutorial/cxx-in-lua>`
+* :doc:`customization point tutorial<tutorial/customization>`
+* :doc:`api documentation<api/usertype>`
+* :doc:`memory documentation<api/usertype_memory>`
+
+The examples folder also has a number of really great examples for you to see. There are also some notes about guarantees you can find about usertypes, and their associated userdata, below:
+
+* You can push types classified as userdata before you register a usertype.
+ - You can register a usertype with the Lua runtime at any time sol2
+ - You can retrieve them from the Lua runtime as well through sol2
+ - Methods and properties will be added to the type only after you register it in the Lua runtime
+* Types either copy once or move once into the memory location, if it is a value type. If it is a pointer, we store only the reference.
+ - This means take arguments of class types (not primitive types like strings or integers) by ``T&`` or ``T*`` to modify the data in Lua directly, or by plain ``T`` to get a copy
+ - Return types and passing arguments to ``sol::function`` use perfect forwarding and reference semantics, which means no copies happen unless you specify a value explicitly. See :ref:`this note for details<function-argument-handling>`.
+* The first ``sizeof( void* )`` bytes is always a pointer to the typed C++ memory. What comes after is based on what you've pushed into the system according to :doc:`the memory specification for usertypes<api/usertype_memory>`. This is compatible with a number of systems.
+* Member methods, properties, variables and functions taking ``self&`` arguments modify data directly
+ - Work on a copy by taking or returning a copy by value.
+* The actual metatable associated with the usertype has a long name and is defined to be opaque by the Sol implementation.
+* Containers get pushed as special usertypes, but can be disabled if problems arising as detailed :doc:`here<api/containers>`. \ No newline at end of file
diff --git a/3rdparty/sol2/single/sol/sol.hpp b/3rdparty/sol2/single/sol/sol.hpp
index c2c8a328bc3..4b1acbdabf3 100644
--- a/3rdparty/sol2/single/sol/sol.hpp
+++ b/3rdparty/sol2/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-10-06 00:53:22.017715 UTC
-// This header was generated with sol v2.14.9 (revision 0ba4650)
+// Generated 2016-11-06 03:40:31.664320 UTC
+// This header was generated with sol v2.14.12 (revision 1c73fb0)
// https://github.com/ThePhD/sol2
#ifndef SOL_SINGLE_INCLUDE_HPP
@@ -48,6 +48,7 @@ namespace sol {
std::string w;
public:
error(const std::string& str) : error(detail::direct_error, "lua: error: " + str) {}
+ error(std::string&& str) : error(detail::direct_error, "lua: error: " + std::move(str)) {}
error(detail::direct_error_tag, const std::string& str) : std::runtime_error(""), w(str) {}
error(detail::direct_error_tag, std::string&& str) : std::runtime_error(""), w(std::move(str)) {}
@@ -754,1071 +755,12 @@ namespace sol {
// beginning of sol/object.hpp
-// beginning of sol/optional.hpp
-
-// beginning of sol/in_place.hpp
-
-namespace sol {
-
- namespace detail {
- struct in_place_of {};
- template <std::size_t I>
- struct in_place_of_i {};
- template <typename T>
- struct in_place_of_t {};
- } // detail
-
- struct in_place_tag { struct init {}; constexpr in_place_tag(init) {} in_place_tag() = delete; };
- constexpr inline in_place_tag in_place(detail::in_place_of) { return in_place_tag(in_place_tag::init()); }
- template <typename T>
- constexpr inline in_place_tag in_place(detail::in_place_of_t<T>) { return in_place_tag(in_place_tag::init()); }
- template <std::size_t I>
- constexpr inline in_place_tag in_place(detail::in_place_of_i<I>) { return in_place_tag(in_place_tag::init()); }
-
- using in_place_t = in_place_tag(&)(detail::in_place_of);
- template <typename T>
- using in_place_type_t = in_place_tag(&)(detail::in_place_of_t<T>);
- template <std::size_t I>
- using in_place_index_t = in_place_tag(&)(detail::in_place_of_i<I>);
-
-} // sol
-
-// end of sol/in_place.hpp
-
-#if defined(SOL_USE_BOOST)
-#include <boost/optional.hpp>
-#else
-// beginning of Optional/optional.hpp
-
-# ifndef ___SOL_OPTIONAL_HPP___
-# define ___SOL_OPTIONAL_HPP___
-
-# include <utility>
-# include <type_traits>
-# include <initializer_list>
-# include <cassert>
-# include <functional>
-# include <string>
-# include <stdexcept>
-
-# define TR2_OPTIONAL_REQUIRES(...) typename ::std::enable_if<__VA_ARGS__::value, bool>::type = false
-
-# if defined __GNUC__ // NOTE: GNUC is also defined for Clang
-# if (__GNUC__ >= 5)
-# define TR2_OPTIONAL_GCC_5_0_AND_HIGHER___
-# define TR2_OPTIONAL_GCC_4_8_AND_HIGHER___
-# elif (__GNUC__ == 4) && (__GNUC_MINOR__ >= 8)
-# define TR2_OPTIONAL_GCC_4_8_AND_HIGHER___
-# elif (__GNUC__ > 4)
-# define TR2_OPTIONAL_GCC_4_8_AND_HIGHER___
-# endif
-#
-# if (__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)
-# define TR2_OPTIONAL_GCC_4_7_AND_HIGHER___
-# elif (__GNUC__ > 4)
-# define TR2_OPTIONAL_GCC_4_7_AND_HIGHER___
-# endif
-#
-# if (__GNUC__ == 4) && (__GNUC_MINOR__ == 8) && (__GNUC_PATCHLEVEL__ >= 1)
-# define TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___
-# elif (__GNUC__ == 4) && (__GNUC_MINOR__ >= 9)
-# define TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___
-# elif (__GNUC__ > 4)
-# define TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___
-# endif
-# endif
-#
-# if defined __clang_major__
-# if (__clang_major__ == 3 && __clang_minor__ >= 5)
-# define TR2_OPTIONAL_CLANG_3_5_AND_HIGHTER_
-# elif (__clang_major__ > 3)
-# define TR2_OPTIONAL_CLANG_3_5_AND_HIGHTER_
-# endif
-# if defined TR2_OPTIONAL_CLANG_3_5_AND_HIGHTER_
-# define TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_
-# elif (__clang_major__ == 3 && __clang_minor__ == 4 && __clang_patchlevel__ >= 2)
-# define TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_
-# endif
-# endif
-#
-# if defined _MSC_VER
-# if (_MSC_VER >= 1900)
-# define TR2_OPTIONAL_MSVC_2015_AND_HIGHER___
-# endif
-# endif
-
-# if defined __clang__
-# if (__clang_major__ > 2) || (__clang_major__ == 2) && (__clang_minor__ >= 9)
-# define OPTIONAL_HAS_THIS_RVALUE_REFS 1
-# else
-# define OPTIONAL_HAS_THIS_RVALUE_REFS 0
-# endif
-# elif defined TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___
-# define OPTIONAL_HAS_THIS_RVALUE_REFS 1
-# elif defined TR2_OPTIONAL_MSVC_2015_AND_HIGHER___
-# define OPTIONAL_HAS_THIS_RVALUE_REFS 1
-# else
-# define OPTIONAL_HAS_THIS_RVALUE_REFS 0
-# endif
-
-# if defined TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___
-# define OPTIONAL_HAS_CONSTEXPR_INIT_LIST 1
-# define OPTIONAL_CONSTEXPR_INIT_LIST constexpr
-# else
-# define OPTIONAL_HAS_CONSTEXPR_INIT_LIST 0
-# define OPTIONAL_CONSTEXPR_INIT_LIST
-# endif
-
-# if defined TR2_OPTIONAL_CLANG_3_5_AND_HIGHTER_ && (defined __cplusplus) && (__cplusplus != 201103L)
-# define OPTIONAL_HAS_MOVE_ACCESSORS 1
-# else
-# define OPTIONAL_HAS_MOVE_ACCESSORS 0
-# endif
-
-# // In C++11 constexpr implies const, so we need to make non-const members also non-constexpr
-# if (defined __cplusplus) && (__cplusplus == 201103L)
-# define OPTIONAL_MUTABLE_CONSTEXPR
-# else
-# define OPTIONAL_MUTABLE_CONSTEXPR constexpr
-# endif
-
-namespace sol{
-
-# if defined TR2_OPTIONAL_GCC_4_8_AND_HIGHER___
- // leave it: it is already there
-# elif defined TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_
- // leave it: it is already there
-# elif defined TR2_OPTIONAL_MSVC_2015_AND_HIGHER___
- // leave it: it is already there
-# elif defined TR2_OPTIONAL_DISABLE_EMULATION_OF_TYPE_TRAITS
- // leave it: the user doesn't want it
-# else
- template <typename T>
- using is_trivially_destructible = ::std::has_trivial_destructor<T>;
-# endif
-
-# if (defined TR2_OPTIONAL_GCC_4_7_AND_HIGHER___)
- // leave it; our metafunctions are already defined.
-# elif defined TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_
- // leave it; our metafunctions are already defined.
-# elif defined TR2_OPTIONAL_MSVC_2015_AND_HIGHER___
- // leave it: it is already there
-# elif defined TR2_OPTIONAL_DISABLE_EMULATION_OF_TYPE_TRAITS
- // leave it: the user doesn't want it
-# else
-
-template <class T>
-struct is_nothrow_move_constructible
-{
- constexpr static bool value = ::std::is_nothrow_constructible<T, T&&>::value;
-};
-
-template <class T, class U>
-struct is_assignable
-{
- template <class X, class Y>
- constexpr static bool has_assign(...) { return false; }
-
- template <class X, class Y, size_t S = sizeof((::std::declval<X>() = ::std::declval<Y>(), true)) >
- // the comma operator is necessary for the cases where operator= returns void
- constexpr static bool has_assign(bool) { return true; }
-
- constexpr static bool value = has_assign<T, U>(true);
-};
-
-template <class T>
-struct is_nothrow_move_assignable
-{
- template <class X, bool has_any_move_assign>
- struct has_nothrow_move_assign {
- constexpr static bool value = false;
- };
-
- template <class X>
- struct has_nothrow_move_assign<X, true> {
- constexpr static bool value = noexcept( ::std::declval<X&>() = ::std::declval<X&&>() );
- };
-
- constexpr static bool value = has_nothrow_move_assign<T, is_assignable<T&, T&&>::value>::value;
-};
-
-# endif
-
-template <class T> class optional;
-
-template <class T> class optional<T&>;
-
-template <class T> inline constexpr T&& constexpr_forward(typename ::std::remove_reference<T>::type& t) noexcept
-{
- return static_cast<T&&>(t);
-}
-
-template <class T> inline constexpr T&& constexpr_forward(typename ::std::remove_reference<T>::type&& t) noexcept
-{
- static_assert(!::std::is_lvalue_reference<T>::value, "!!");
- return static_cast<T&&>(t);
-}
-
-template <class T> inline constexpr typename ::std::remove_reference<T>::type&& constexpr_move(T&& t) noexcept
-{
- return static_cast<typename ::std::remove_reference<T>::type&&>(t);
-}
-
-#if defined NDEBUG
-# define TR2_OPTIONAL_ASSERTED_EXPRESSION(CHECK, EXPR) (EXPR)
-#else
-# define TR2_OPTIONAL_ASSERTED_EXPRESSION(CHECK, EXPR) ((CHECK) ? (EXPR) : ([]{assert(!#CHECK);}(), (EXPR)))
-#endif
-
-namespace detail_
-{
-
-template <typename T>
-struct has_overloaded_addressof
-{
- template <class X>
- constexpr static bool has_overload(...) { return false; }
-
- template <class X, size_t S = sizeof(::std::declval<X&>().operator&()) >
- constexpr static bool has_overload(bool) { return true; }
-
- constexpr static bool value = has_overload<T>(true);
-};
-
-template <typename T, TR2_OPTIONAL_REQUIRES(!has_overloaded_addressof<T>)>
-constexpr T* static_addressof(T& ref)
-{
- return &ref;
-}
-
-template <typename T, TR2_OPTIONAL_REQUIRES(has_overloaded_addressof<T>)>
-T* static_addressof(T& ref)
-{
- return ::std::addressof(ref);
-}
-
-template <class U>
-constexpr U convert(U v) { return v; }
-
-} // namespace detail_
-
-constexpr struct trivial_init_t {} trivial_init{};
-
-struct nullopt_t
-{
- struct init{};
- constexpr explicit nullopt_t(init){}
-};
-constexpr nullopt_t nullopt{nullopt_t::init()};
-
-class bad_optional_access : public ::std::logic_error {
-public:
- explicit bad_optional_access(const ::std::string& what_arg) : ::std::logic_error{what_arg} {}
- explicit bad_optional_access(const char* what_arg) : ::std::logic_error{what_arg} {}
-};
-
-template <class T>
-struct optional_base
-{
- bool init_;
- char storage_[sizeof(T)];
-
- constexpr optional_base() noexcept : init_(false), storage_() {};
-
- explicit optional_base(const T& v) : init_(true), storage_() {
- new (&storage())T(v);
- }
-
- explicit optional_base(T&& v) : init_(true), storage_() {
- new (&storage())T(constexpr_move(v));
- }
-
- template <class... Args> explicit optional_base(in_place_t, Args&&... args)
- : init_(true), storage_() {
- new (&storage())T(constexpr_forward<Args>(args)...);
- }
-
- template <class U, class... Args, TR2_OPTIONAL_REQUIRES(::std::is_constructible<T, ::std::initializer_list<U>>)>
- explicit optional_base(in_place_t, ::std::initializer_list<U> il, Args&&... args)
- : init_(true), storage_() {
- new (&storage())T(il, constexpr_forward<Args>(args)...);
- }
-#if defined __GNUC__
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wstrict-aliasing"
-#endif
- T& storage() {
- return *reinterpret_cast<T*>(&storage_[0]);
- }
-
- constexpr const T& storage() const {
- return *reinterpret_cast<T const*>(&storage_[0]);
- }
-#if defined __GNUC__
-#pragma GCC diagnostic pop
-#endif
-
- ~optional_base() { if (init_) { storage().T::~T(); } }
-};
-
-#if defined __GNUC__ && !defined TR2_OPTIONAL_GCC_5_0_AND_HIGHER___
-template <typename T>
-using constexpr_optional_base = optional_base<T>;
-#else
-template <class T>
-struct constexpr_optional_base
-{
- bool init_;
- char storage_[sizeof(T)];
- constexpr constexpr_optional_base() noexcept : init_(false), storage_() {}
-
- explicit constexpr constexpr_optional_base(const T& v) : init_(true), storage_() {
- new (&storage())T(v);
- }
-
- explicit constexpr constexpr_optional_base(T&& v) : init_(true), storage_() {
- new (&storage())T(constexpr_move(v));
- }
-
- template <class... Args> explicit constexpr constexpr_optional_base(in_place_t, Args&&... args)
- : init_(true), storage_() {
- new (&storage())T(constexpr_forward<Args>(args)...);
- }
-
- template <class U, class... Args, TR2_OPTIONAL_REQUIRES(::std::is_constructible<T, ::std::initializer_list<U>>)>
- OPTIONAL_CONSTEXPR_INIT_LIST explicit constexpr_optional_base(in_place_t, ::std::initializer_list<U> il, Args&&... args)
- : init_(true), storage_() {
- new (&storage())T(il, constexpr_forward<Args>(args)...);
- }
-
-#if defined __GNUC__
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wstrict-aliasing"
-#endif
- T& storage() {
- return (*reinterpret_cast<T*>(&storage_[0]));
- }
-
- constexpr const T& storage() const {
- return (*reinterpret_cast<T const*>(&storage_[0]));
- }
-#if defined __GNUC__
-#pragma GCC diagnostic pop
-#endif
-
- ~constexpr_optional_base() = default;
-};
-#endif
-
-template <class T>
-using OptionalBase = typename ::std::conditional<
- ::std::is_trivially_destructible<T>::value,
- constexpr_optional_base<typename ::std::remove_const<T>::type>,
- optional_base<typename ::std::remove_const<T>::type>
->::type;
-
-template <class T>
-class optional : private OptionalBase<T>
-{
- static_assert( !::std::is_same<typename ::std::decay<T>::type, nullopt_t>::value, "bad T" );
- static_assert( !::std::is_same<typename ::std::decay<T>::type, in_place_t>::value, "bad T" );
-
- constexpr bool initialized() const noexcept { return OptionalBase<T>::init_; }
- typename ::std::remove_const<T>::type* dataptr() { return ::std::addressof(OptionalBase<T>::storage()); }
- constexpr const T* dataptr() const { return detail_::static_addressof(OptionalBase<T>::storage()); }
-
-# if OPTIONAL_HAS_THIS_RVALUE_REFS == 1
- constexpr const T& contained_val() const& { return OptionalBase<T>::storage(); }
-# if OPTIONAL_HAS_MOVE_ACCESSORS == 1
- OPTIONAL_MUTABLE_CONSTEXPR T&& contained_val() && { return ::std::move(OptionalBase<T>::storage()); }
- OPTIONAL_MUTABLE_CONSTEXPR T& contained_val() & { return OptionalBase<T>::storage(); }
-# else
- T& contained_val() & { return OptionalBase<T>::storage(); }
- T&& contained_val() && { return ::std::move(OptionalBase<T>::storage()); }
-# endif
-# else
- constexpr const T& contained_val() const { return OptionalBase<T>::storage(); }
- T& contained_val() { return OptionalBase<T>::storage(); }
-# endif
-
- void clear() noexcept {
- if (initialized()) dataptr()->T::~T();
- OptionalBase<T>::init_ = false;
- }
-
- template <class... Args>
- void initialize(Args&&... args) noexcept(noexcept(T(::std::forward<Args>(args)...)))
- {
- assert(!OptionalBase<T>::init_);
- ::new (static_cast<void*>(dataptr())) T(::std::forward<Args>(args)...);
- OptionalBase<T>::init_ = true;
- }
-
- template <class U, class... Args>
- void initialize(::std::initializer_list<U> il, Args&&... args) noexcept(noexcept(T(il, ::std::forward<Args>(args)...)))
- {
- assert(!OptionalBase<T>::init_);
- ::new (static_cast<void*>(dataptr())) T(il, ::std::forward<Args>(args)...);
- OptionalBase<T>::init_ = true;
- }
-
-public:
- typedef T value_type;
-
- // 20.5.5.1, constructors
- constexpr optional() noexcept : OptionalBase<T>() {};
- constexpr optional(nullopt_t) noexcept : OptionalBase<T>() {};
-
- optional(const optional& rhs)
- : OptionalBase<T>()
- {
- if (rhs.initialized()) {
- ::new (static_cast<void*>(dataptr())) T(*rhs);
- OptionalBase<T>::init_ = true;
- }
- }
-
- optional(const optional<T&>& rhs) : optional()
- {
- if (rhs) {
- ::new (static_cast<void*>(dataptr())) T(*rhs);
- OptionalBase<T>::init_ = true;
- }
- }
-
- optional(optional&& rhs) noexcept(::std::is_nothrow_move_constructible<T>::value)
- : OptionalBase<T>()
- {
- if (rhs.initialized()) {
- ::new (static_cast<void*>(dataptr())) T(::std::move(*rhs));
- OptionalBase<T>::init_ = true;
- }
- }
-
- constexpr optional(const T& v) : OptionalBase<T>(v) {}
-
- constexpr optional(T&& v) : OptionalBase<T>(constexpr_move(v)) {}
-
- template <class... Args>
- explicit constexpr optional(in_place_t, Args&&... args)
- : OptionalBase<T>(in_place, constexpr_forward<Args>(args)...) {}
-
- template <class U, class... Args, TR2_OPTIONAL_REQUIRES(::std::is_constructible<T, ::std::initializer_list<U>>)>
- OPTIONAL_CONSTEXPR_INIT_LIST explicit optional(in_place_t, ::std::initializer_list<U> il, Args&&... args)
- : OptionalBase<T>(in_place, il, constexpr_forward<Args>(args)...) {}
-
- // 20.5.4.2, Destructor
- ~optional() = default;
-
- // 20.5.4.3, assignment
- optional& operator=(nullopt_t) noexcept
- {
- clear();
- return *this;
- }
-
- optional& operator=(const optional& rhs)
- {
- if (initialized() == true && rhs.initialized() == false) clear();
- else if (initialized() == false && rhs.initialized() == true) initialize(*rhs);
- else if (initialized() == true && rhs.initialized() == true) contained_val() = *rhs;
- return *this;
- }
-
- optional& operator=(optional&& rhs)
- noexcept(::std::is_nothrow_move_assignable<T>::value && ::std::is_nothrow_move_constructible<T>::value)
- {
- if (initialized() == true && rhs.initialized() == false) clear();
- else if (initialized() == false && rhs.initialized() == true) initialize(::std::move(*rhs));
- else if (initialized() == true && rhs.initialized() == true) contained_val() = ::std::move(*rhs);
- return *this;
- }
-
- template <class U>
- auto operator=(U&& v)
- -> typename ::std::enable_if
- <
- ::std::is_same<typename ::std::decay<U>::type, T>::value,
- optional&
- >::type
- {
- if (initialized()) { contained_val() = ::std::forward<U>(v); }
- else { initialize(::std::forward<U>(v)); }
- return *this;
- }
-
- template <class... Args>
- void emplace(Args&&... args)
- {
- clear();
- initialize(::std::forward<Args>(args)...);
- }
-
- template <class U, class... Args>
- void emplace(::std::initializer_list<U> il, Args&&... args)
- {
- clear();
- initialize<U, Args...>(il, ::std::forward<Args>(args)...);
- }
-
- // 20.5.4.4, Swap
- void swap(optional<T>& rhs) noexcept(::std::is_nothrow_move_constructible<T>::value && noexcept(swap(::std::declval<T&>(), ::std::declval<T&>())))
- {
- if (initialized() == true && rhs.initialized() == false) { rhs.initialize(::std::move(**this)); clear(); }
- else if (initialized() == false && rhs.initialized() == true) { initialize(::std::move(*rhs)); rhs.clear(); }
- else if (initialized() == true && rhs.initialized() == true) { using ::std::swap; swap(**this, *rhs); }
- }
-
- // 20.5.4.5, Observers
-
- explicit constexpr operator bool() const noexcept { return initialized(); }
-
- constexpr T const* operator ->() const {
- return TR2_OPTIONAL_ASSERTED_EXPRESSION(initialized(), dataptr());
- }
-
-# if OPTIONAL_HAS_MOVE_ACCESSORS == 1
-
- OPTIONAL_MUTABLE_CONSTEXPR T* operator ->() {
- assert (initialized());
- return dataptr();
- }
-
- constexpr T const& operator *() const& {
- return TR2_OPTIONAL_ASSERTED_EXPRESSION(initialized(), contained_val());
- }
-
- OPTIONAL_MUTABLE_CONSTEXPR T& operator *() & {
- assert (initialized());
- return contained_val();
- }
-
- OPTIONAL_MUTABLE_CONSTEXPR T&& operator *() && {
- assert (initialized());
- return constexpr_move(contained_val());
- }
-
- constexpr T const& value() const& {
- return initialized() ? contained_val() : (throw bad_optional_access("bad optional access"), contained_val());
- }
-
- OPTIONAL_MUTABLE_CONSTEXPR T& value() & {
- return initialized() ? contained_val() : (throw bad_optional_access("bad optional access"), contained_val());
- }
-
- OPTIONAL_MUTABLE_CONSTEXPR T&& value() && {
- if (!initialized()) throw bad_optional_access("bad optional access");
- return ::std::move(contained_val());
- }
-
-# else
-
- T* operator ->() {
- assert (initialized());
- return dataptr();
- }
-
- constexpr T const& operator *() const {
- return TR2_OPTIONAL_ASSERTED_EXPRESSION(initialized(), contained_val());
- }
-
- T& operator *() {
- assert (initialized());
- return contained_val();
- }
-
- constexpr T const& value() const {
- return initialized() ? contained_val() : (throw bad_optional_access("bad optional access"), contained_val());
- }
-
- T& value() {
- return initialized() ? contained_val() : (throw bad_optional_access("bad optional access"), contained_val());
- }
-
-# endif
-
-# if OPTIONAL_HAS_THIS_RVALUE_REFS == 1
-
- template <class V>
- constexpr T value_or(V&& v) const&
- {
- return *this ? **this : detail_::convert<T>(constexpr_forward<V>(v));
- }
-
-# if OPTIONAL_HAS_MOVE_ACCESSORS == 1
-
- template <class V>
- OPTIONAL_MUTABLE_CONSTEXPR T value_or(V&& v) &&
- {
- return *this ? constexpr_move(const_cast<optional<T>&>(*this).contained_val()) : detail_::convert<T>(constexpr_forward<V>(v));
- }
-
-# else
-
- template <class V>
- T value_or(V&& v) &&
- {
- return *this ? constexpr_move(const_cast<optional<T>&>(*this).contained_val()) : detail_::convert<T>(constexpr_forward<V>(v));
- }
-
-# endif
-
-# else
-
- template <class V>
- constexpr T value_or(V&& v) const
- {
- return *this ? **this : detail_::convert<T>(constexpr_forward<V>(v));
- }
-
-# endif
-
-};
-
-template <class T>
-class optional<T&>
-{
- static_assert( !::std::is_same<T, nullopt_t>::value, "bad T" );
- static_assert( !::std::is_same<T, in_place_t>::value, "bad T" );
- T* ref;
-
-public:
-
- // 20.5.5.1, construction/destruction
- constexpr optional() noexcept : ref(nullptr) {}
-
- constexpr optional(nullopt_t) noexcept : ref(nullptr) {}
-
- constexpr optional(T& v) noexcept : ref(detail_::static_addressof(v)) {}
-
- optional(T&&) = delete;
-
- constexpr optional(const optional& rhs) noexcept : ref(rhs.ref) {}
-
- explicit constexpr optional(in_place_t, T& v) noexcept : ref(detail_::static_addressof(v)) {}
-
- explicit optional(in_place_t, T&&) = delete;
-
- ~optional() = default;
-
- // 20.5.5.2, mutation
- optional& operator=(nullopt_t) noexcept {
- ref = nullptr;
- return *this;
- }
-
- // optional& operator=(const optional& rhs) noexcept {
- // ref = rhs.ref;
- // return *this;
- // }
-
- // optional& operator=(optional&& rhs) noexcept {
- // ref = rhs.ref;
- // return *this;
- // }
-
- template <typename U>
- auto operator=(U&& rhs) noexcept
- -> typename ::std::enable_if
- <
- ::std::is_same<typename ::std::decay<U>::type, optional<T&>>::value,
- optional&
- >::type
- {
- ref = rhs.ref;
- return *this;
- }
-
- template <typename U>
- auto operator=(U&& rhs) noexcept
- -> typename ::std::enable_if
- <
- !::std::is_same<typename ::std::decay<U>::type, optional<T&>>::value,
- optional&
- >::type
- = delete;
-
- void emplace(T& v) noexcept {
- ref = detail_::static_addressof(v);
- }
-
- void emplace(T&&) = delete;
-
- void swap(optional<T&>& rhs) noexcept
- {
- ::std::swap(ref, rhs.ref);
- }
-
- // 20.5.5.3, observers
- constexpr T* operator->() const {
- return TR2_OPTIONAL_ASSERTED_EXPRESSION(ref, ref);
- }
-
- constexpr T& operator*() const {
- return TR2_OPTIONAL_ASSERTED_EXPRESSION(ref, *ref);
- }
-
- constexpr T& value() const {
- return ref ? *ref : (throw bad_optional_access("bad optional access"), *ref);
- }
-
- explicit constexpr operator bool() const noexcept {
- return ref != nullptr;
- }
-
- template <typename V>
- constexpr T& value_or(V&& v) const
- {
- return *this ? **this : detail_::convert<T&>(constexpr_forward<V>(v));
- }
-};
-
-template <class T>
-class optional<T&&>
-{
- static_assert( sizeof(T) == 0, "optional rvalue references disallowed" );
-};
-
-template <class T> constexpr bool operator==(const optional<T>& x, const optional<T>& y)
-{
- return bool(x) != bool(y) ? false : bool(x) == false ? true : *x == *y;
-}
-
-template <class T> constexpr bool operator!=(const optional<T>& x, const optional<T>& y)
-{
- return !(x == y);
-}
-
-template <class T> constexpr bool operator<(const optional<T>& x, const optional<T>& y)
-{
- return (!y) ? false : (!x) ? true : *x < *y;
-}
-
-template <class T> constexpr bool operator>(const optional<T>& x, const optional<T>& y)
-{
- return (y < x);
-}
-
-template <class T> constexpr bool operator<=(const optional<T>& x, const optional<T>& y)
-{
- return !(y < x);
-}
-
-template <class T> constexpr bool operator>=(const optional<T>& x, const optional<T>& y)
-{
- return !(x < y);
-}
-
-template <class T> constexpr bool operator==(const optional<T>& x, nullopt_t) noexcept
-{
- return (!x);
-}
-
-template <class T> constexpr bool operator==(nullopt_t, const optional<T>& x) noexcept
-{
- return (!x);
-}
-
-template <class T> constexpr bool operator!=(const optional<T>& x, nullopt_t) noexcept
-{
- return bool(x);
-}
-
-template <class T> constexpr bool operator!=(nullopt_t, const optional<T>& x) noexcept
-{
- return bool(x);
-}
-
-template <class T> constexpr bool operator<(const optional<T>&, nullopt_t) noexcept
-{
- return false;
-}
-
-template <class T> constexpr bool operator<(nullopt_t, const optional<T>& x) noexcept
-{
- return bool(x);
-}
-
-template <class T> constexpr bool operator<=(const optional<T>& x, nullopt_t) noexcept
-{
- return (!x);
-}
-
-template <class T> constexpr bool operator<=(nullopt_t, const optional<T>&) noexcept
-{
- return true;
-}
-
-template <class T> constexpr bool operator>(const optional<T>& x, nullopt_t) noexcept
-{
- return bool(x);
-}
-
-template <class T> constexpr bool operator>(nullopt_t, const optional<T>&) noexcept
-{
- return false;
-}
-
-template <class T> constexpr bool operator>=(const optional<T>&, nullopt_t) noexcept
-{
- return true;
-}
-
-template <class T> constexpr bool operator>=(nullopt_t, const optional<T>& x) noexcept
-{
- return (!x);
-}
-
-template <class T> constexpr bool operator==(const optional<T>& x, const T& v)
-{
- return bool(x) ? *x == v : false;
-}
-
-template <class T> constexpr bool operator==(const T& v, const optional<T>& x)
-{
- return bool(x) ? v == *x : false;
-}
-
-template <class T> constexpr bool operator!=(const optional<T>& x, const T& v)
-{
- return bool(x) ? *x != v : true;
-}
-
-template <class T> constexpr bool operator!=(const T& v, const optional<T>& x)
-{
- return bool(x) ? v != *x : true;
-}
-
-template <class T> constexpr bool operator<(const optional<T>& x, const T& v)
-{
- return bool(x) ? *x < v : true;
-}
-
-template <class T> constexpr bool operator>(const T& v, const optional<T>& x)
-{
- return bool(x) ? v > *x : true;
-}
-
-template <class T> constexpr bool operator>(const optional<T>& x, const T& v)
-{
- return bool(x) ? *x > v : false;
-}
-
-template <class T> constexpr bool operator<(const T& v, const optional<T>& x)
-{
- return bool(x) ? v < *x : false;
-}
-
-template <class T> constexpr bool operator>=(const optional<T>& x, const T& v)
-{
- return bool(x) ? *x >= v : false;
-}
-
-template <class T> constexpr bool operator<=(const T& v, const optional<T>& x)
-{
- return bool(x) ? v <= *x : false;
-}
-
-template <class T> constexpr bool operator<=(const optional<T>& x, const T& v)
-{
- return bool(x) ? *x <= v : true;
-}
-
-template <class T> constexpr bool operator>=(const T& v, const optional<T>& x)
-{
- return bool(x) ? v >= *x : true;
-}
-
-template <class T> constexpr bool operator==(const optional<T&>& x, const T& v)
-{
- return bool(x) ? *x == v : false;
-}
-
-template <class T> constexpr bool operator==(const T& v, const optional<T&>& x)
-{
- return bool(x) ? v == *x : false;
-}
-
-template <class T> constexpr bool operator!=(const optional<T&>& x, const T& v)
-{
- return bool(x) ? *x != v : true;
-}
-
-template <class T> constexpr bool operator!=(const T& v, const optional<T&>& x)
-{
- return bool(x) ? v != *x : true;
-}
-
-template <class T> constexpr bool operator<(const optional<T&>& x, const T& v)
-{
- return bool(x) ? *x < v : true;
-}
-
-template <class T> constexpr bool operator>(const T& v, const optional<T&>& x)
-{
- return bool(x) ? v > *x : true;
-}
-
-template <class T> constexpr bool operator>(const optional<T&>& x, const T& v)
-{
- return bool(x) ? *x > v : false;
-}
-
-template <class T> constexpr bool operator<(const T& v, const optional<T&>& x)
-{
- return bool(x) ? v < *x : false;
-}
-
-template <class T> constexpr bool operator>=(const optional<T&>& x, const T& v)
-{
- return bool(x) ? *x >= v : false;
-}
-
-template <class T> constexpr bool operator<=(const T& v, const optional<T&>& x)
-{
- return bool(x) ? v <= *x : false;
-}
-
-template <class T> constexpr bool operator<=(const optional<T&>& x, const T& v)
-{
- return bool(x) ? *x <= v : true;
-}
-
-template <class T> constexpr bool operator>=(const T& v, const optional<T&>& x)
-{
- return bool(x) ? v >= *x : true;
-}
-
-template <class T> constexpr bool operator==(const optional<const T&>& x, const T& v)
-{
- return bool(x) ? *x == v : false;
-}
-
-template <class T> constexpr bool operator==(const T& v, const optional<const T&>& x)
-{
- return bool(x) ? v == *x : false;
-}
-
-template <class T> constexpr bool operator!=(const optional<const T&>& x, const T& v)
-{
- return bool(x) ? *x != v : true;
-}
-
-template <class T> constexpr bool operator!=(const T& v, const optional<const T&>& x)
-{
- return bool(x) ? v != *x : true;
-}
-
-template <class T> constexpr bool operator<(const optional<const T&>& x, const T& v)
-{
- return bool(x) ? *x < v : true;
-}
-
-template <class T> constexpr bool operator>(const T& v, const optional<const T&>& x)
-{
- return bool(x) ? v > *x : true;
-}
-
-template <class T> constexpr bool operator>(const optional<const T&>& x, const T& v)
-{
- return bool(x) ? *x > v : false;
-}
-
-template <class T> constexpr bool operator<(const T& v, const optional<const T&>& x)
-{
- return bool(x) ? v < *x : false;
-}
-
-template <class T> constexpr bool operator>=(const optional<const T&>& x, const T& v)
-{
- return bool(x) ? *x >= v : false;
-}
-
-template <class T> constexpr bool operator<=(const T& v, const optional<const T&>& x)
-{
- return bool(x) ? v <= *x : false;
-}
-
-template <class T> constexpr bool operator<=(const optional<const T&>& x, const T& v)
-{
- return bool(x) ? *x <= v : true;
-}
-
-template <class T> constexpr bool operator>=(const T& v, const optional<const T&>& x)
-{
- return bool(x) ? v >= *x : true;
-}
-
-template <class T>
-void swap(optional<T>& x, optional<T>& y) noexcept(noexcept(x.swap(y)))
-{
- x.swap(y);
-}
-
-template <class T>
-constexpr optional<typename ::std::decay<T>::type> make_optional(T&& v)
-{
- return optional<typename ::std::decay<T>::type>(constexpr_forward<T>(v));
-}
-
-template <class X>
-constexpr optional<X&> make_optional(::std::reference_wrapper<X> v)
-{
- return optional<X&>(v.get());
-}
-
-} // namespace
-
-namespace std
-{
- template <typename T>
- struct hash<sol::optional<T>>
- {
- typedef typename hash<T>::result_type result_type;
- typedef sol::optional<T> argument_type;
-
- constexpr result_type operator()(argument_type const& arg) const {
- return arg ? ::std::hash<T>{}(*arg) : result_type{};
- }
- };
-
- template <typename T>
- struct hash<sol::optional<T&>>
- {
- typedef typename hash<T>::result_type result_type;
- typedef sol::optional<T&> argument_type;
-
- constexpr result_type operator()(argument_type const& arg) const {
- return arg ? ::std::hash<T>{}(*arg) : result_type{};
- }
- };
-}
-
-# undef TR2_OPTIONAL_REQUIRES
-# undef TR2_OPTIONAL_ASSERTED_EXPRESSION
-
-# endif //___SOL_OPTIONAL_HPP___
-// end of Optional/optional.hpp
-
-#endif // Boost vs. Better optional
-
-namespace sol {
-
-#if defined(SOL_USE_BOOST)
- template <typename T>
- using optional = boost::optional<T>;
- using nullopt_t = boost::none_t;
- const nullopt_t nullopt = boost::none;
-#endif // Boost vs. Better optional
-
-} // sol
-
-// end of sol/optional.hpp
-
// beginning of sol/reference.hpp
// beginning of sol/types.hpp
+// beginning of sol/optional.hpp
+
// beginning of sol/compatibility.hpp
// beginning of sol/compatibility/version.hpp
@@ -2055,7 +997,7 @@ inline const char* kepler_lua_compat_get_string(lua_State* L, void* ud, size_t*
return ls->s;
}
-#if !defined(SOL_LUAJIT) || ((SOL_LUAJIT_VERSION - 020100) <= 0)
+#if !defined(SOL_LUAJIT) || ((SOL_LUAJIT_VERSION - 20100) <= 0)
inline int luaL_loadbufferx(lua_State* L, const char* buff, size_t size, const char* name, const char*) {
kepler_lua_compat_get_string_view ls;
@@ -2138,6 +1080,31 @@ int luaL_fileresult(lua_State *L, int stat, const char *fname);
#ifndef SOL_5_X_X_INL
#define SOL_5_X_X_INL
+// beginning of sol/compatibility/5.2.0.h
+
+#ifndef SOL_5_2_0_H
+#define SOL_5_2_0_H
+
+#if SOL_LUA_VERSION < 503
+
+inline int lua_isinteger(lua_State* L, int idx) {
+ if (lua_type(L, idx) != LUA_TNUMBER)
+ return 0;
+ // This is a very slipshod way to do the testing
+ // but lua_totingerx doesn't play ball nicely
+ // on older versions...
+ lua_Number n = lua_tonumber(L, idx);
+ lua_Integer i = lua_tointeger(L, idx);
+ if (i != n)
+ return 0;
+ // it's DEFINITELY an integer
+ return 1;
+}
+
+#endif // SOL_LUA_VERSION == 502
+#endif // SOL_5_2_0_H
+// end of sol/compatibility/5.2.0.h
+
#if !defined(LUA_VERSION_NUM) || LUA_VERSION_NUM == 501
#include <errno.h>
@@ -2818,6 +1785,1124 @@ inline void luaL_pushresult(luaL_Buffer_52 *B) {
// end of sol/compatibility.hpp
+// beginning of sol/in_place.hpp
+
+namespace sol {
+
+ namespace detail {
+ struct in_place_of {};
+ template <std::size_t I>
+ struct in_place_of_i {};
+ template <typename T>
+ struct in_place_of_t {};
+ } // detail
+
+ struct in_place_tag { struct init {}; constexpr in_place_tag(init) {} in_place_tag() = delete; };
+ constexpr inline in_place_tag in_place(detail::in_place_of) { return in_place_tag(in_place_tag::init()); }
+ template <typename T>
+ constexpr inline in_place_tag in_place(detail::in_place_of_t<T>) { return in_place_tag(in_place_tag::init()); }
+ template <std::size_t I>
+ constexpr inline in_place_tag in_place(detail::in_place_of_i<I>) { return in_place_tag(in_place_tag::init()); }
+
+ using in_place_t = in_place_tag(&)(detail::in_place_of);
+ template <typename T>
+ using in_place_type_t = in_place_tag(&)(detail::in_place_of_t<T>);
+ template <std::size_t I>
+ using in_place_index_t = in_place_tag(&)(detail::in_place_of_i<I>);
+
+} // sol
+
+// end of sol/in_place.hpp
+
+#if defined(SOL_USE_BOOST)
+#include <boost/optional.hpp>
+#else
+// beginning of sol/optional_implementation.hpp
+
+# ifndef SOL_OPTIONAL_IMPLEMENTATION_HPP
+# define SOL_OPTIONAL_IMPLEMENTATION_HPP
+
+# include <utility>
+# include <type_traits>
+# include <initializer_list>
+# include <cassert>
+# include <functional>
+# include <string>
+# include <stdexcept>
+#ifdef SOL_NO_EXCEPTIONS
+#include <cstdlib>
+#endif // Exceptions
+
+# define TR2_OPTIONAL_REQUIRES(...) typename ::std::enable_if<__VA_ARGS__::value, bool>::type = false
+
+# if defined __GNUC__ // NOTE: GNUC is also defined for Clang
+# if (__GNUC__ >= 5)
+# define TR2_OPTIONAL_GCC_5_0_AND_HIGHER___
+# define TR2_OPTIONAL_GCC_4_8_AND_HIGHER___
+# elif (__GNUC__ == 4) && (__GNUC_MINOR__ >= 8)
+# define TR2_OPTIONAL_GCC_4_8_AND_HIGHER___
+# elif (__GNUC__ > 4)
+# define TR2_OPTIONAL_GCC_4_8_AND_HIGHER___
+# endif
+#
+# if (__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)
+# define TR2_OPTIONAL_GCC_4_7_AND_HIGHER___
+# elif (__GNUC__ > 4)
+# define TR2_OPTIONAL_GCC_4_7_AND_HIGHER___
+# endif
+#
+# if (__GNUC__ == 4) && (__GNUC_MINOR__ == 8) && (__GNUC_PATCHLEVEL__ >= 1)
+# define TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___
+# elif (__GNUC__ == 4) && (__GNUC_MINOR__ >= 9)
+# define TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___
+# elif (__GNUC__ > 4)
+# define TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___
+# endif
+# endif
+#
+# if defined __clang_major__
+# if (__clang_major__ == 3 && __clang_minor__ >= 5)
+# define TR2_OPTIONAL_CLANG_3_5_AND_HIGHTER_
+# elif (__clang_major__ > 3)
+# define TR2_OPTIONAL_CLANG_3_5_AND_HIGHTER_
+# endif
+# if defined TR2_OPTIONAL_CLANG_3_5_AND_HIGHTER_
+# define TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_
+# elif (__clang_major__ == 3 && __clang_minor__ == 4 && __clang_patchlevel__ >= 2)
+# define TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_
+# endif
+# endif
+#
+# if defined _MSC_VER
+# if (_MSC_VER >= 1900)
+# define TR2_OPTIONAL_MSVC_2015_AND_HIGHER___
+# endif
+# endif
+
+# if defined __clang__
+# if (__clang_major__ > 2) || (__clang_major__ == 2) && (__clang_minor__ >= 9)
+# define OPTIONAL_HAS_THIS_RVALUE_REFS 1
+# else
+# define OPTIONAL_HAS_THIS_RVALUE_REFS 0
+# endif
+# elif defined TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___
+# define OPTIONAL_HAS_THIS_RVALUE_REFS 1
+# elif defined TR2_OPTIONAL_MSVC_2015_AND_HIGHER___
+# define OPTIONAL_HAS_THIS_RVALUE_REFS 1
+# else
+# define OPTIONAL_HAS_THIS_RVALUE_REFS 0
+# endif
+
+# if defined TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___
+# define OPTIONAL_HAS_CONSTEXPR_INIT_LIST 1
+# define OPTIONAL_CONSTEXPR_INIT_LIST constexpr
+# else
+# define OPTIONAL_HAS_CONSTEXPR_INIT_LIST 0
+# define OPTIONAL_CONSTEXPR_INIT_LIST
+# endif
+
+# if defined TR2_OPTIONAL_CLANG_3_5_AND_HIGHTER_ && (defined __cplusplus) && (__cplusplus != 201103L)
+# define OPTIONAL_HAS_MOVE_ACCESSORS 1
+# else
+# define OPTIONAL_HAS_MOVE_ACCESSORS 0
+# endif
+
+# // In C++11 constexpr implies const, so we need to make non-const members also non-constexpr
+# if (defined __cplusplus) && (__cplusplus == 201103L)
+# define OPTIONAL_MUTABLE_CONSTEXPR
+# else
+# define OPTIONAL_MUTABLE_CONSTEXPR constexpr
+# endif
+
+namespace sol {
+
+ // BEGIN workaround for missing is_trivially_destructible
+# if defined TR2_OPTIONAL_GCC_4_8_AND_HIGHER___
+ // leave it: it is already there
+# elif defined TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_
+ // leave it: it is already there
+# elif defined TR2_OPTIONAL_MSVC_2015_AND_HIGHER___
+ // leave it: it is already there
+# elif defined TR2_OPTIONAL_DISABLE_EMULATION_OF_TYPE_TRAITS
+ // leave it: the user doesn't want it
+# else
+ template <typename T>
+ using is_trivially_destructible = ::std::has_trivial_destructor<T>;
+# endif
+ // END workaround for missing is_trivially_destructible
+
+# if (defined TR2_OPTIONAL_GCC_4_7_AND_HIGHER___)
+ // leave it; our metafunctions are already defined.
+# elif defined TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_
+ // leave it; our metafunctions are already defined.
+# elif defined TR2_OPTIONAL_MSVC_2015_AND_HIGHER___
+ // leave it: it is already there
+# elif defined TR2_OPTIONAL_DISABLE_EMULATION_OF_TYPE_TRAITS
+ // leave it: the user doesn't want it
+# else
+
+ template <class T>
+ struct is_nothrow_move_constructible
+ {
+ constexpr static bool value = ::std::is_nothrow_constructible<T, T&&>::value;
+ };
+
+ template <class T, class U>
+ struct is_assignable
+ {
+ template <class X, class Y>
+ constexpr static bool has_assign(...) { return false; }
+
+ template <class X, class Y, size_t S = sizeof((::std::declval<X>() = ::std::declval<Y>(), true)) >
+ // the comma operator is necessary for the cases where operator= returns void
+ constexpr static bool has_assign(bool) { return true; }
+
+ constexpr static bool value = has_assign<T, U>(true);
+ };
+
+ template <class T>
+ struct is_nothrow_move_assignable
+ {
+ template <class X, bool has_any_move_assign>
+ struct has_nothrow_move_assign {
+ constexpr static bool value = false;
+ };
+
+ template <class X>
+ struct has_nothrow_move_assign<X, true> {
+ constexpr static bool value = noexcept(::std::declval<X&>() = ::std::declval<X&&>());
+ };
+
+ constexpr static bool value = has_nothrow_move_assign<T, is_assignable<T&, T&&>::value>::value;
+ };
+ // end workaround
+
+# endif
+
+ template <class T> class optional;
+
+ // 20.5.5, optional for lvalue reference types
+ template <class T> class optional<T&>;
+
+ // workaround: std utility functions aren't constexpr yet
+ template <class T> inline constexpr T&& constexpr_forward(typename ::std::remove_reference<T>::type& t) noexcept
+ {
+ return static_cast<T&&>(t);
+ }
+
+ template <class T> inline constexpr T&& constexpr_forward(typename ::std::remove_reference<T>::type&& t) noexcept
+ {
+ static_assert(!::std::is_lvalue_reference<T>::value, "!!");
+ return static_cast<T&&>(t);
+ }
+
+ template <class T> inline constexpr typename ::std::remove_reference<T>::type&& constexpr_move(T&& t) noexcept
+ {
+ return static_cast<typename ::std::remove_reference<T>::type&&>(t);
+ }
+
+#if defined NDEBUG
+# define TR2_OPTIONAL_ASSERTED_EXPRESSION(CHECK, EXPR) (EXPR)
+#else
+# define TR2_OPTIONAL_ASSERTED_EXPRESSION(CHECK, EXPR) ((CHECK) ? (EXPR) : ([]{assert(!#CHECK);}(), (EXPR)))
+#endif
+
+ namespace detail_
+ {
+
+ // static_addressof: a constexpr version of addressof
+ template <typename T>
+ struct has_overloaded_addressof
+ {
+ template <class X>
+ constexpr static bool has_overload(...) { return false; }
+
+ template <class X, size_t S = sizeof(::std::declval<X&>().operator&()) >
+ constexpr static bool has_overload(bool) { return true; }
+
+ constexpr static bool value = has_overload<T>(true);
+ };
+
+ template <typename T, TR2_OPTIONAL_REQUIRES(!has_overloaded_addressof<T>)>
+ constexpr T* static_addressof(T& ref)
+ {
+ return &ref;
+ }
+
+ template <typename T, TR2_OPTIONAL_REQUIRES(has_overloaded_addressof<T>)>
+ T* static_addressof(T& ref)
+ {
+ return ::std::addressof(ref);
+ }
+
+ // the call to convert<A>(b) has return type A and converts b to type A iff b decltype(b) is implicitly convertible to A
+ template <class U>
+ constexpr U convert(U v) { return v; }
+
+ } // namespace detail_
+
+ constexpr struct trivial_init_t {} trivial_init{};
+
+ // 20.5.7, Disengaged state indicator
+ struct nullopt_t
+ {
+ struct init {};
+ constexpr explicit nullopt_t(init) {}
+ };
+ constexpr nullopt_t nullopt{ nullopt_t::init() };
+
+ // 20.5.8, class bad_optional_access
+ class bad_optional_access : public ::std::logic_error {
+ public:
+ explicit bad_optional_access(const ::std::string& what_arg) : ::std::logic_error{ what_arg } {}
+ explicit bad_optional_access(const char* what_arg) : ::std::logic_error{ what_arg } {}
+ };
+
+ template <class T>
+ struct optional_base
+ {
+ bool init_;
+ char storage_[sizeof(T)];
+
+ constexpr optional_base() noexcept : init_(false), storage_() {};
+
+ explicit optional_base(const T& v) : init_(true), storage_() {
+ new (&storage())T(v);
+ }
+
+ explicit optional_base(T&& v) : init_(true), storage_() {
+ new (&storage())T(constexpr_move(v));
+ }
+
+ template <class... Args> explicit optional_base(in_place_t, Args&&... args)
+ : init_(true), storage_() {
+ new (&storage())T(constexpr_forward<Args>(args)...);
+ }
+
+ template <class U, class... Args, TR2_OPTIONAL_REQUIRES(::std::is_constructible<T, ::std::initializer_list<U>>)>
+ explicit optional_base(in_place_t, ::std::initializer_list<U> il, Args&&... args)
+ : init_(true), storage_() {
+ new (&storage())T(il, constexpr_forward<Args>(args)...);
+ }
+#if defined __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wstrict-aliasing"
+#endif
+ T& storage() {
+ return *reinterpret_cast<T*>(&storage_[0]);
+ }
+
+ constexpr const T& storage() const {
+ return *reinterpret_cast<T const*>(&storage_[0]);
+ }
+#if defined __GNUC__
+#pragma GCC diagnostic pop
+#endif
+
+ ~optional_base() { if (init_) { storage().T::~T(); } }
+ };
+
+#if defined __GNUC__ && !defined TR2_OPTIONAL_GCC_5_0_AND_HIGHER___
+ // Sorry, GCC 4.x; you're just a piece of shit
+ template <typename T>
+ using constexpr_optional_base = optional_base<T>;
+#else
+ template <class T>
+ struct constexpr_optional_base
+ {
+ bool init_;
+ char storage_[sizeof(T)];
+ constexpr constexpr_optional_base() noexcept : init_(false), storage_() {}
+
+ explicit constexpr constexpr_optional_base(const T& v) : init_(true), storage_() {
+ new (&storage())T(v);
+ }
+
+ explicit constexpr constexpr_optional_base(T&& v) : init_(true), storage_() {
+ new (&storage())T(constexpr_move(v));
+ }
+
+ template <class... Args> explicit constexpr constexpr_optional_base(in_place_t, Args&&... args)
+ : init_(true), storage_() {
+ new (&storage())T(constexpr_forward<Args>(args)...);
+ }
+
+ template <class U, class... Args, TR2_OPTIONAL_REQUIRES(::std::is_constructible<T, ::std::initializer_list<U>>)>
+ OPTIONAL_CONSTEXPR_INIT_LIST explicit constexpr_optional_base(in_place_t, ::std::initializer_list<U> il, Args&&... args)
+ : init_(true), storage_() {
+ new (&storage())T(il, constexpr_forward<Args>(args)...);
+ }
+
+#if defined __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wstrict-aliasing"
+#endif
+ T& storage() {
+ return (*reinterpret_cast<T*>(&storage_[0]));
+ }
+
+ constexpr const T& storage() const {
+ return (*reinterpret_cast<T const*>(&storage_[0]));
+ }
+#if defined __GNUC__
+#pragma GCC diagnostic pop
+#endif
+
+ ~constexpr_optional_base() = default;
+ };
+#endif
+
+ template <class T>
+ using OptionalBase = typename ::std::conditional<
+ ::std::is_trivially_destructible<T>::value,
+ constexpr_optional_base<typename ::std::remove_const<T>::type>,
+ optional_base<typename ::std::remove_const<T>::type>
+ >::type;
+
+ template <class T>
+ class optional : private OptionalBase<T>
+ {
+ static_assert(!::std::is_same<typename ::std::decay<T>::type, nullopt_t>::value, "bad T");
+ static_assert(!::std::is_same<typename ::std::decay<T>::type, in_place_t>::value, "bad T");
+
+ constexpr bool initialized() const noexcept { return OptionalBase<T>::init_; }
+ typename ::std::remove_const<T>::type* dataptr() { return ::std::addressof(OptionalBase<T>::storage()); }
+ constexpr const T* dataptr() const { return detail_::static_addressof(OptionalBase<T>::storage()); }
+
+# if OPTIONAL_HAS_THIS_RVALUE_REFS == 1
+ constexpr const T& contained_val() const& { return OptionalBase<T>::storage(); }
+# if OPTIONAL_HAS_MOVE_ACCESSORS == 1
+ OPTIONAL_MUTABLE_CONSTEXPR T&& contained_val() && { return ::std::move(OptionalBase<T>::storage()); }
+ OPTIONAL_MUTABLE_CONSTEXPR T& contained_val() & { return OptionalBase<T>::storage(); }
+# else
+ T& contained_val() & { return OptionalBase<T>::storage(); }
+ T&& contained_val() && { return ::std::move(OptionalBase<T>::storage()); }
+# endif
+# else
+ constexpr const T& contained_val() const { return OptionalBase<T>::storage(); }
+ T& contained_val() { return OptionalBase<T>::storage(); }
+# endif
+
+ void clear() noexcept {
+ if (initialized()) dataptr()->T::~T();
+ OptionalBase<T>::init_ = false;
+ }
+
+ template <class... Args>
+ void initialize(Args&&... args) noexcept(noexcept(T(::std::forward<Args>(args)...)))
+ {
+ assert(!OptionalBase<T>::init_);
+ ::new (static_cast<void*>(dataptr())) T(::std::forward<Args>(args)...);
+ OptionalBase<T>::init_ = true;
+ }
+
+ template <class U, class... Args>
+ void initialize(::std::initializer_list<U> il, Args&&... args) noexcept(noexcept(T(il, ::std::forward<Args>(args)...)))
+ {
+ assert(!OptionalBase<T>::init_);
+ ::new (static_cast<void*>(dataptr())) T(il, ::std::forward<Args>(args)...);
+ OptionalBase<T>::init_ = true;
+ }
+
+ public:
+ typedef T value_type;
+
+ // 20.5.5.1, constructors
+ constexpr optional() noexcept : OptionalBase<T>() {};
+ constexpr optional(nullopt_t) noexcept : OptionalBase<T>() {};
+
+ optional(const optional& rhs)
+ : OptionalBase<T>()
+ {
+ if (rhs.initialized()) {
+ ::new (static_cast<void*>(dataptr())) T(*rhs);
+ OptionalBase<T>::init_ = true;
+ }
+ }
+
+ optional(const optional<T&>& rhs) : optional()
+ {
+ if (rhs) {
+ ::new (static_cast<void*>(dataptr())) T(*rhs);
+ OptionalBase<T>::init_ = true;
+ }
+ }
+
+ optional(optional&& rhs) noexcept(::std::is_nothrow_move_constructible<T>::value)
+ : OptionalBase<T>()
+ {
+ if (rhs.initialized()) {
+ ::new (static_cast<void*>(dataptr())) T(::std::move(*rhs));
+ OptionalBase<T>::init_ = true;
+ }
+ }
+
+ constexpr optional(const T& v) : OptionalBase<T>(v) {}
+
+ constexpr optional(T&& v) : OptionalBase<T>(constexpr_move(v)) {}
+
+ template <class... Args>
+ explicit constexpr optional(in_place_t, Args&&... args)
+ : OptionalBase<T>(in_place, constexpr_forward<Args>(args)...) {}
+
+ template <class U, class... Args, TR2_OPTIONAL_REQUIRES(::std::is_constructible<T, ::std::initializer_list<U>>)>
+ OPTIONAL_CONSTEXPR_INIT_LIST explicit optional(in_place_t, ::std::initializer_list<U> il, Args&&... args)
+ : OptionalBase<T>(in_place, il, constexpr_forward<Args>(args)...) {}
+
+ // 20.5.4.2, Destructor
+ ~optional() = default;
+
+ // 20.5.4.3, assignment
+ optional& operator=(nullopt_t) noexcept
+ {
+ clear();
+ return *this;
+ }
+
+ optional& operator=(const optional& rhs)
+ {
+ if (initialized() == true && rhs.initialized() == false) clear();
+ else if (initialized() == false && rhs.initialized() == true) initialize(*rhs);
+ else if (initialized() == true && rhs.initialized() == true) contained_val() = *rhs;
+ return *this;
+ }
+
+ optional& operator=(optional&& rhs)
+ noexcept(::std::is_nothrow_move_assignable<T>::value && ::std::is_nothrow_move_constructible<T>::value)
+ {
+ if (initialized() == true && rhs.initialized() == false) clear();
+ else if (initialized() == false && rhs.initialized() == true) initialize(::std::move(*rhs));
+ else if (initialized() == true && rhs.initialized() == true) contained_val() = ::std::move(*rhs);
+ return *this;
+ }
+
+ template <class U>
+ auto operator=(U&& v)
+ -> typename ::std::enable_if
+ <
+ ::std::is_same<typename ::std::decay<U>::type, T>::value,
+ optional&
+ >::type
+ {
+ if (initialized()) { contained_val() = ::std::forward<U>(v); }
+ else { initialize(::std::forward<U>(v)); }
+ return *this;
+ }
+
+ template <class... Args>
+ void emplace(Args&&... args)
+ {
+ clear();
+ initialize(::std::forward<Args>(args)...);
+ }
+
+ template <class U, class... Args>
+ void emplace(::std::initializer_list<U> il, Args&&... args)
+ {
+ clear();
+ initialize<U, Args...>(il, ::std::forward<Args>(args)...);
+ }
+
+ // 20.5.4.4, Swap
+ void swap(optional<T>& rhs) noexcept(::std::is_nothrow_move_constructible<T>::value && noexcept(swap(::std::declval<T&>(), ::std::declval<T&>())))
+ {
+ if (initialized() == true && rhs.initialized() == false) { rhs.initialize(::std::move(**this)); clear(); }
+ else if (initialized() == false && rhs.initialized() == true) { initialize(::std::move(*rhs)); rhs.clear(); }
+ else if (initialized() == true && rhs.initialized() == true) { using ::std::swap; swap(**this, *rhs); }
+ }
+
+ // 20.5.4.5, Observers
+
+ explicit constexpr operator bool() const noexcept { return initialized(); }
+
+ constexpr T const* operator ->() const {
+ return TR2_OPTIONAL_ASSERTED_EXPRESSION(initialized(), dataptr());
+ }
+
+# if OPTIONAL_HAS_MOVE_ACCESSORS == 1
+
+ OPTIONAL_MUTABLE_CONSTEXPR T* operator ->() {
+ assert(initialized());
+ return dataptr();
+ }
+
+ constexpr T const& operator *() const& {
+ return TR2_OPTIONAL_ASSERTED_EXPRESSION(initialized(), contained_val());
+ }
+
+ OPTIONAL_MUTABLE_CONSTEXPR T& operator *() & {
+ assert(initialized());
+ return contained_val();
+ }
+
+ OPTIONAL_MUTABLE_CONSTEXPR T&& operator *() && {
+ assert(initialized());
+ return constexpr_move(contained_val());
+ }
+
+ constexpr T const& value() const& {
+ return initialized() ?
+ contained_val()
+#ifdef SOL_NO_EXCEPTIONS
+ // we can't abort here
+ // because there's no constexpr abort
+ : *(T*)nullptr;
+#else
+ : (throw bad_optional_access("bad optional access"), contained_val());
+#endif
+ }
+
+ OPTIONAL_MUTABLE_CONSTEXPR T& value() & {
+ return initialized() ?
+ contained_val()
+#ifdef SOL_NO_EXCEPTIONS
+ : *(T*)nullptr;
+#else
+ : (throw bad_optional_access("bad optional access"), contained_val());
+#endif
+ }
+
+ OPTIONAL_MUTABLE_CONSTEXPR T&& value() && {
+ return initialized() ?
+ contained_val()
+#ifdef SOL_NO_EXCEPTIONS
+ // we can't abort here
+ // because there's no constexpr abort
+ : std::move(*(T*)nullptr);
+#else
+ : (throw bad_optional_access("bad optional access"), contained_val());
+#endif
+ }
+
+# else
+
+ T* operator ->() {
+ assert(initialized());
+ return dataptr();
+ }
+
+ constexpr T const& operator *() const {
+ return TR2_OPTIONAL_ASSERTED_EXPRESSION(initialized(), contained_val());
+ }
+
+ T& operator *() {
+ assert(initialized());
+ return contained_val();
+ }
+
+ constexpr T const& value() const {
+ return initialized() ?
+ contained_val()
+#ifdef SOL_NO_EXCEPTIONS
+ // we can't abort here
+ // because there's no constexpr abort
+ : *(T*)nullptr;
+#else
+ : (throw bad_optional_access("bad optional access"), contained_val());
+#endif
+ }
+
+ T& value() {
+ return initialized() ?
+ contained_val()
+#ifdef SOL_NO_EXCEPTIONS
+ // we can abort here
+ // but the others are constexpr, so we can't...
+ : (std::abort(), *(T*)nullptr)
+#else
+ : (throw bad_optional_access("bad optional access"), contained_val());
+#endif
+ }
+
+# endif
+
+# if OPTIONAL_HAS_THIS_RVALUE_REFS == 1
+
+ template <class V>
+ constexpr T value_or(V&& v) const&
+ {
+ return *this ? **this : detail_::convert<T>(constexpr_forward<V>(v));
+ }
+
+# if OPTIONAL_HAS_MOVE_ACCESSORS == 1
+
+ template <class V>
+ OPTIONAL_MUTABLE_CONSTEXPR T value_or(V&& v) &&
+ {
+ return *this ? constexpr_move(const_cast<optional<T>&>(*this).contained_val()) : detail_::convert<T>(constexpr_forward<V>(v));
+ }
+
+# else
+
+ template <class V>
+ T value_or(V&& v) &&
+ {
+ return *this ? constexpr_move(const_cast<optional<T>&>(*this).contained_val()) : detail_::convert<T>(constexpr_forward<V>(v));
+ }
+
+# endif
+
+# else
+
+ template <class V>
+ constexpr T value_or(V&& v) const
+ {
+ return *this ? **this : detail_::convert<T>(constexpr_forward<V>(v));
+ }
+
+# endif
+
+ };
+
+ template <class T>
+ class optional<T&>
+ {
+ static_assert(!::std::is_same<T, nullopt_t>::value, "bad T");
+ static_assert(!::std::is_same<T, in_place_t>::value, "bad T");
+ T* ref;
+
+ public:
+
+ // 20.5.5.1, construction/destruction
+ constexpr optional() noexcept : ref(nullptr) {}
+
+ constexpr optional(nullopt_t) noexcept : ref(nullptr) {}
+
+ constexpr optional(T& v) noexcept : ref(detail_::static_addressof(v)) {}
+
+ optional(T&&) = delete;
+
+ constexpr optional(const optional& rhs) noexcept : ref(rhs.ref) {}
+
+ explicit constexpr optional(in_place_t, T& v) noexcept : ref(detail_::static_addressof(v)) {}
+
+ explicit optional(in_place_t, T&&) = delete;
+
+ ~optional() = default;
+
+ // 20.5.5.2, mutation
+ optional& operator=(nullopt_t) noexcept {
+ ref = nullptr;
+ return *this;
+ }
+
+ // optional& operator=(const optional& rhs) noexcept {
+ // ref = rhs.ref;
+ // return *this;
+ // }
+
+ // optional& operator=(optional&& rhs) noexcept {
+ // ref = rhs.ref;
+ // return *this;
+ // }
+
+ template <typename U>
+ auto operator=(U&& rhs) noexcept
+ -> typename ::std::enable_if
+ <
+ ::std::is_same<typename ::std::decay<U>::type, optional<T&>>::value,
+ optional&
+ >::type
+ {
+ ref = rhs.ref;
+ return *this;
+ }
+
+ template <typename U>
+ auto operator=(U&& rhs) noexcept
+ -> typename ::std::enable_if
+ <
+ !::std::is_same<typename ::std::decay<U>::type, optional<T&>>::value,
+ optional&
+ >::type
+ = delete;
+
+ void emplace(T& v) noexcept {
+ ref = detail_::static_addressof(v);
+ }
+
+ void emplace(T&&) = delete;
+
+ void swap(optional<T&>& rhs) noexcept
+ {
+ ::std::swap(ref, rhs.ref);
+ }
+
+ // 20.5.5.3, observers
+ constexpr T* operator->() const {
+ return TR2_OPTIONAL_ASSERTED_EXPRESSION(ref, ref);
+ }
+
+ constexpr T& operator*() const {
+ return TR2_OPTIONAL_ASSERTED_EXPRESSION(ref, *ref);
+ }
+
+ constexpr T& value() const {
+ return ref ?
+ *ref
+#ifdef SOL_NO_EXCEPTIONS
+ // we can't abort here
+ // because there's no constexpr abort
+ : *(T*)nullptr;
+#else
+ : throw bad_optional_access("bad optional access");
+#endif
+ }
+
+ explicit constexpr operator bool() const noexcept {
+ return ref != nullptr;
+ }
+
+ template <typename V>
+ constexpr T& value_or(V&& v) const
+ {
+ return *this ? **this : detail_::convert<T&>(constexpr_forward<V>(v));
+ }
+ };
+
+ template <class T>
+ class optional<T&&>
+ {
+ static_assert(sizeof(T) == 0, "optional rvalue references disallowed");
+ };
+
+ // 20.5.8, Relational operators
+ template <class T> constexpr bool operator==(const optional<T>& x, const optional<T>& y)
+ {
+ return bool(x) != bool(y) ? false : bool(x) == false ? true : *x == *y;
+ }
+
+ template <class T> constexpr bool operator!=(const optional<T>& x, const optional<T>& y)
+ {
+ return !(x == y);
+ }
+
+ template <class T> constexpr bool operator<(const optional<T>& x, const optional<T>& y)
+ {
+ return (!y) ? false : (!x) ? true : *x < *y;
+ }
+
+ template <class T> constexpr bool operator>(const optional<T>& x, const optional<T>& y)
+ {
+ return (y < x);
+ }
+
+ template <class T> constexpr bool operator<=(const optional<T>& x, const optional<T>& y)
+ {
+ return !(y < x);
+ }
+
+ template <class T> constexpr bool operator>=(const optional<T>& x, const optional<T>& y)
+ {
+ return !(x < y);
+ }
+
+ // 20.5.9, Comparison with nullopt
+ template <class T> constexpr bool operator==(const optional<T>& x, nullopt_t) noexcept
+ {
+ return (!x);
+ }
+
+ template <class T> constexpr bool operator==(nullopt_t, const optional<T>& x) noexcept
+ {
+ return (!x);
+ }
+
+ template <class T> constexpr bool operator!=(const optional<T>& x, nullopt_t) noexcept
+ {
+ return bool(x);
+ }
+
+ template <class T> constexpr bool operator!=(nullopt_t, const optional<T>& x) noexcept
+ {
+ return bool(x);
+ }
+
+ template <class T> constexpr bool operator<(const optional<T>&, nullopt_t) noexcept
+ {
+ return false;
+ }
+
+ template <class T> constexpr bool operator<(nullopt_t, const optional<T>& x) noexcept
+ {
+ return bool(x);
+ }
+
+ template <class T> constexpr bool operator<=(const optional<T>& x, nullopt_t) noexcept
+ {
+ return (!x);
+ }
+
+ template <class T> constexpr bool operator<=(nullopt_t, const optional<T>&) noexcept
+ {
+ return true;
+ }
+
+ template <class T> constexpr bool operator>(const optional<T>& x, nullopt_t) noexcept
+ {
+ return bool(x);
+ }
+
+ template <class T> constexpr bool operator>(nullopt_t, const optional<T>&) noexcept
+ {
+ return false;
+ }
+
+ template <class T> constexpr bool operator>=(const optional<T>&, nullopt_t) noexcept
+ {
+ return true;
+ }
+
+ template <class T> constexpr bool operator>=(nullopt_t, const optional<T>& x) noexcept
+ {
+ return (!x);
+ }
+
+ // 20.5.10, Comparison with T
+ template <class T> constexpr bool operator==(const optional<T>& x, const T& v)
+ {
+ return bool(x) ? *x == v : false;
+ }
+
+ template <class T> constexpr bool operator==(const T& v, const optional<T>& x)
+ {
+ return bool(x) ? v == *x : false;
+ }
+
+ template <class T> constexpr bool operator!=(const optional<T>& x, const T& v)
+ {
+ return bool(x) ? *x != v : true;
+ }
+
+ template <class T> constexpr bool operator!=(const T& v, const optional<T>& x)
+ {
+ return bool(x) ? v != *x : true;
+ }
+
+ template <class T> constexpr bool operator<(const optional<T>& x, const T& v)
+ {
+ return bool(x) ? *x < v : true;
+ }
+
+ template <class T> constexpr bool operator>(const T& v, const optional<T>& x)
+ {
+ return bool(x) ? v > *x : true;
+ }
+
+ template <class T> constexpr bool operator>(const optional<T>& x, const T& v)
+ {
+ return bool(x) ? *x > v : false;
+ }
+
+ template <class T> constexpr bool operator<(const T& v, const optional<T>& x)
+ {
+ return bool(x) ? v < *x : false;
+ }
+
+ template <class T> constexpr bool operator>=(const optional<T>& x, const T& v)
+ {
+ return bool(x) ? *x >= v : false;
+ }
+
+ template <class T> constexpr bool operator<=(const T& v, const optional<T>& x)
+ {
+ return bool(x) ? v <= *x : false;
+ }
+
+ template <class T> constexpr bool operator<=(const optional<T>& x, const T& v)
+ {
+ return bool(x) ? *x <= v : true;
+ }
+
+ template <class T> constexpr bool operator>=(const T& v, const optional<T>& x)
+ {
+ return bool(x) ? v >= *x : true;
+ }
+
+ // Comparison of optional<T&> with T
+ template <class T> constexpr bool operator==(const optional<T&>& x, const T& v)
+ {
+ return bool(x) ? *x == v : false;
+ }
+
+ template <class T> constexpr bool operator==(const T& v, const optional<T&>& x)
+ {
+ return bool(x) ? v == *x : false;
+ }
+
+ template <class T> constexpr bool operator!=(const optional<T&>& x, const T& v)
+ {
+ return bool(x) ? *x != v : true;
+ }
+
+ template <class T> constexpr bool operator!=(const T& v, const optional<T&>& x)
+ {
+ return bool(x) ? v != *x : true;
+ }
+
+ template <class T> constexpr bool operator<(const optional<T&>& x, const T& v)
+ {
+ return bool(x) ? *x < v : true;
+ }
+
+ template <class T> constexpr bool operator>(const T& v, const optional<T&>& x)
+ {
+ return bool(x) ? v > *x : true;
+ }
+
+ template <class T> constexpr bool operator>(const optional<T&>& x, const T& v)
+ {
+ return bool(x) ? *x > v : false;
+ }
+
+ template <class T> constexpr bool operator<(const T& v, const optional<T&>& x)
+ {
+ return bool(x) ? v < *x : false;
+ }
+
+ template <class T> constexpr bool operator>=(const optional<T&>& x, const T& v)
+ {
+ return bool(x) ? *x >= v : false;
+ }
+
+ template <class T> constexpr bool operator<=(const T& v, const optional<T&>& x)
+ {
+ return bool(x) ? v <= *x : false;
+ }
+
+ template <class T> constexpr bool operator<=(const optional<T&>& x, const T& v)
+ {
+ return bool(x) ? *x <= v : true;
+ }
+
+ template <class T> constexpr bool operator>=(const T& v, const optional<T&>& x)
+ {
+ return bool(x) ? v >= *x : true;
+ }
+
+ // Comparison of optional<T const&> with T
+ template <class T> constexpr bool operator==(const optional<const T&>& x, const T& v)
+ {
+ return bool(x) ? *x == v : false;
+ }
+
+ template <class T> constexpr bool operator==(const T& v, const optional<const T&>& x)
+ {
+ return bool(x) ? v == *x : false;
+ }
+
+ template <class T> constexpr bool operator!=(const optional<const T&>& x, const T& v)
+ {
+ return bool(x) ? *x != v : true;
+ }
+
+ template <class T> constexpr bool operator!=(const T& v, const optional<const T&>& x)
+ {
+ return bool(x) ? v != *x : true;
+ }
+
+ template <class T> constexpr bool operator<(const optional<const T&>& x, const T& v)
+ {
+ return bool(x) ? *x < v : true;
+ }
+
+ template <class T> constexpr bool operator>(const T& v, const optional<const T&>& x)
+ {
+ return bool(x) ? v > *x : true;
+ }
+
+ template <class T> constexpr bool operator>(const optional<const T&>& x, const T& v)
+ {
+ return bool(x) ? *x > v : false;
+ }
+
+ template <class T> constexpr bool operator<(const T& v, const optional<const T&>& x)
+ {
+ return bool(x) ? v < *x : false;
+ }
+
+ template <class T> constexpr bool operator>=(const optional<const T&>& x, const T& v)
+ {
+ return bool(x) ? *x >= v : false;
+ }
+
+ template <class T> constexpr bool operator<=(const T& v, const optional<const T&>& x)
+ {
+ return bool(x) ? v <= *x : false;
+ }
+
+ template <class T> constexpr bool operator<=(const optional<const T&>& x, const T& v)
+ {
+ return bool(x) ? *x <= v : true;
+ }
+
+ template <class T> constexpr bool operator>=(const T& v, const optional<const T&>& x)
+ {
+ return bool(x) ? v >= *x : true;
+ }
+
+ // 20.5.12, Specialized algorithms
+ template <class T>
+ void swap(optional<T>& x, optional<T>& y) noexcept(noexcept(x.swap(y))) {
+ x.swap(y);
+ }
+
+ template <class T>
+ constexpr optional<typename ::std::decay<T>::type> make_optional(T&& v) {
+ return optional<typename ::std::decay<T>::type>(constexpr_forward<T>(v));
+ }
+
+ template <class X>
+ constexpr optional<X&> make_optional(::std::reference_wrapper<X> v) {
+ return optional<X&>(v.get());
+ }
+
+} // namespace
+
+namespace std
+{
+ template <typename T>
+ struct hash<sol::optional<T>> {
+ typedef typename hash<T>::result_type result_type;
+ typedef sol::optional<T> argument_type;
+
+ constexpr result_type operator()(argument_type const& arg) const {
+ return arg ? ::std::hash<T>{}(*arg) : result_type{};
+ }
+ };
+
+ template <typename T>
+ struct hash<sol::optional<T&>> {
+ typedef typename hash<T>::result_type result_type;
+ typedef sol::optional<T&> argument_type;
+
+ constexpr result_type operator()(argument_type const& arg) const {
+ return arg ? ::std::hash<T>{}(*arg) : result_type{};
+ }
+ };
+}
+
+# undef TR2_OPTIONAL_REQUIRES
+# undef TR2_OPTIONAL_ASSERTED_EXPRESSION
+
+# endif // SOL_OPTIONAL_IMPLEMENTATION_HPP
+// end of sol/optional_implementation.hpp
+
+#endif // Boost vs. Better optional
+
+namespace sol {
+
+#if defined(SOL_USE_BOOST)
+ template <typename T>
+ using optional = boost::optional<T>;
+ using nullopt_t = boost::none_t;
+ const nullopt_t nullopt = boost::none;
+#endif // Boost vs. Better optional
+
+} // sol
+
+// end of sol/optional.hpp
+
// beginning of sol/string_shim.hpp
#pragma once
@@ -3216,6 +3301,7 @@ namespace sol {
new_index,
mode,
call,
+ call_function = call,
metatable,
to_string,
length,
@@ -3232,7 +3318,13 @@ namespace sol {
less_than,
less_than_or_equal_to,
garbage_collect,
- call_function = call,
+ floor_division,
+ bitwise_left_shift,
+ bitwise_right_shift,
+ bitwise_not,
+ bitwise_and,
+ bitwise_or,
+ bitwise_xor,
};
typedef meta_function meta_method;
@@ -3248,7 +3340,7 @@ namespace sol {
"__newindex",
"__mode",
"__call",
- "__metatable",
+ "__mt",
"__tostring",
"__len",
"__unm",
@@ -3498,6 +3590,12 @@ namespace sol {
template <typename T>
struct lua_type_of<T, std::enable_if_t<std::is_enum<T>::value>> : std::integral_constant<type, type::number> {};
+ template <typename T, typename C = void>
+ struct is_container : std::false_type {};
+
+ template <typename T>
+ struct is_container<T, std::enable_if_t<meta::has_begin_end<meta::unqualified_t<T>>::value>> : std::true_type {};
+
template <>
struct lua_type_of<meta_function> : std::integral_constant<type, type::string> {};
@@ -3602,6 +3700,9 @@ namespace sol {
template <typename T>
struct is_userdata<basic_userdata<T>> : std::true_type {};
+ template <typename T>
+ struct is_container : detail::is_container<T>{};
+
template<typename T>
inline type type_of() {
return lua_type_of<meta::unqualified_t<T>>::value;
@@ -4521,28 +4622,32 @@ namespace sol {
template<typename T>
struct usertype_traits {
- static const std::string name;
- static const std::string qualified_name;
- static const std::string metatable;
- static const std::string user_gc_metatable;
- static const std::string gc_table;
+ static const std::string& name() {
+ static const std::string n = detail::short_demangle<T>();
+ return n;
+ }
+ static const std::string& qualified_name() {
+ static const std::string q_n = detail::demangle<T>();
+ return q_n;
+ }
+ static const std::string& metatable() {
+ static const std::string m = std::string("sol.").append(detail::demangle<T>());
+ return m;
+ }
+ static const std::string& user_metatable() {
+ static const std::string u_m = std::string("sol.").append(detail::demangle<T>()).append(".user");
+ return u_m;
+ }
+ static const std::string& user_gc_metatable() {
+ static const std::string u_g_m = std::string("sol.").append(detail::demangle<T>()).append(".user\xE2\x99\xBB");
+ return u_g_m;
+ }
+ static const std::string& gc_table() {
+ static const std::string g_t = std::string("sol.").append(detail::demangle<T>().append(".\xE2\x99\xBB"));
+ return g_t;
+ }
};
- template<typename T>
- const std::string usertype_traits<T>::name = detail::short_demangle<T>();
-
- template<typename T>
- const std::string usertype_traits<T>::qualified_name = detail::demangle<T>();
-
- template<typename T>
- const std::string usertype_traits<T>::metatable = std::string("sol.").append(detail::demangle<T>());
-
- template<typename T>
- const std::string usertype_traits<T>::user_gc_metatable = std::string("sol.").append(detail::demangle<T>()).append(".user\xE2\x99\xBB");
-
- template<typename T>
- const std::string usertype_traits<T>::gc_table = std::string("sol.").append(detail::demangle<T>().append(".\xE2\x99\xBB"));
-
}
// end of sol/usertype_traits.hpp
@@ -4649,7 +4754,7 @@ namespace sol {
namespace stack_detail {
template <typename T, bool poptable = true>
inline bool check_metatable(lua_State* L, int index = -2) {
- const auto& metakey = usertype_traits<T>::metatable;
+ const auto& metakey = usertype_traits<T>::metatable();
luaL_getmetatable(L, &metakey[0]);
const type expectedmetatabletype = static_cast<type>(lua_type(L, -1));
if (expectedmetatabletype != type::nil) {
@@ -4692,6 +4797,34 @@ namespace sol {
}
};
+ template<typename T>
+ struct checker<T, type::number, std::enable_if_t<std::is_integral<T>::value>> {
+ template <typename Handler>
+ static bool check(lua_State* L, int index, Handler&& handler, record& tracking) {
+ tracking.use(1);
+ bool success = lua_isinteger(L, index) == 1;
+ if (!success) {
+ // expected type, actual type
+ handler(L, index, type::number, type_of(L, index));
+ }
+ return success;
+ }
+ };
+
+ template<typename T>
+ struct checker<T, type::number, std::enable_if_t<std::is_floating_point<T>::value>> {
+ template <typename Handler>
+ static bool check(lua_State* L, int index, Handler&& handler, record& tracking) {
+ tracking.use(1);
+ bool success = lua_isnumber(L, index) == 1;
+ if (!success) {
+ // expected type, actual type
+ handler(L, index, type::number, type_of(L, index));
+ }
+ return success;
+ }
+ };
+
template <type expected, typename C>
struct checker<nil_t, expected, C> {
template <typename Handler>
@@ -4854,21 +4987,7 @@ namespace sol {
};
template <typename T, typename C>
- struct checker<T*, type::userdata, C> {
- template <typename Handler>
- static bool check(lua_State* L, int index, Handler&& handler, record& tracking) {
- const type indextype = type_of(L, index);
- // Allow nil to be transformed to nullptr
- if (indextype == type::nil) {
- tracking.use(1);
- return true;
- }
- return checker<meta::unqualified_t<T>, type::userdata, C>{}.check(types<meta::unqualified_t<T>>(), L, indextype, index, std::forward<Handler>(handler), tracking);
- }
- };
-
- template <typename T, typename C>
- struct checker<T, type::userdata, C> {
+ struct checker<detail::as_value_tag<T>, type::userdata, C> {
template <typename U, typename Handler>
static bool check(types<U>, lua_State* L, type indextype, int index, Handler&& handler, record& tracking) {
tracking.use(1);
@@ -4907,11 +5026,28 @@ namespace sol {
lua_pop(L, 1);
return true;
}
+ };
+ template <typename T, typename C>
+ struct checker<T, type::userdata, C> {
template <typename Handler>
static bool check(lua_State* L, int index, Handler&& handler, record& tracking) {
const type indextype = type_of(L, index);
- return check(types<T>(), L, indextype, index, std::forward<Handler>(handler), tracking);
+ return checker<detail::as_value_tag<T>, type::userdata, C>{}.check(types<T>(), L, indextype, index, std::forward<Handler>(handler), tracking);
+ }
+ };
+
+ template <typename T, typename C>
+ struct checker<T*, type::userdata, C> {
+ template <typename Handler>
+ static bool check(lua_State* L, int index, Handler&& handler, record& tracking) {
+ const type indextype = type_of(L, index);
+ // Allow nil to be transformed to nullptr
+ if (indextype == type::nil) {
+ tracking.use(1);
+ return true;
+ }
+ return checker<meta::unqualified_t<T>, type::userdata, C>{}.check(L, index, std::forward<Handler>(handler), tracking);
}
};
@@ -4999,7 +5135,7 @@ namespace sol {
template<typename T, typename>
struct getter {
static T& get(lua_State* L, int index, record& tracking) {
- return getter<T&>{}.get(L, index, tracking);
+ return getter<sol::detail::as_value_tag<T>>{}.get(L, index, tracking);
}
};
@@ -5395,7 +5531,7 @@ namespace sol {
};
template<typename T>
- struct getter<T*> {
+ struct getter<detail::as_value_tag<T>> {
static T* get_no_nil(lua_State* L, int index, record& tracking) {
tracking.use(1);
void** pudata = static_cast<void**>(lua_touserdata(L, index));
@@ -5414,28 +5550,49 @@ namespace sol {
T* obj = static_cast<T*>(udata);
return obj;
}
+
+ static T& get(lua_State* L, int index, record& tracking) {
+ return *get_no_nil(L, index, tracking);
+ }
+ };
+ template<typename T>
+ struct getter<detail::as_pointer_tag<T>> {
static T* get(lua_State* L, int index, record& tracking) {
type t = type_of(L, index);
if (t == type::nil) {
tracking.use(1);
return nullptr;
}
- return get_no_nil(L, index, tracking);
+ return getter<detail::as_value_tag<T>>::get_no_nil(L, index, tracking);
}
};
template<typename T>
struct getter<non_null<T*>> {
static T* get(lua_State* L, int index, record& tracking) {
- return getter<T*>::get_no_nil(L, index, tracking);
+ return getter<detail::as_value_tag<T>>::get_no_nil(L, index, tracking);
}
};
template<typename T>
struct getter<T&> {
static T& get(lua_State* L, int index, record& tracking) {
- return *getter<T*>::get_no_nil(L, index, tracking);
+ return getter<detail::as_value_tag<T>>::get(L, index, tracking);
+ }
+ };
+
+ template<typename T>
+ struct getter<std::reference_wrapper<T>> {
+ static T& get(lua_State* L, int index, record& tracking) {
+ return getter<T&>{}.get(L, index, tracking);
+ }
+ };
+
+ template<typename T>
+ struct getter<T*> {
+ static T* get(lua_State* L, int index, record& tracking) {
+ return getter<detail::as_pointer_tag<T>>::get(L, index, tracking);
}
};
@@ -5453,13 +5610,6 @@ namespace sol {
}
};
- template<typename T>
- struct getter<std::reference_wrapper<T>> {
- static T& get(lua_State* L, int index, record& tracking) {
- return getter<T&>{}.get(L, index, tracking);
- }
- };
-
template<typename... Args>
struct getter<std::tuple<Args...>> {
typedef std::tuple<decltype(stack::get<Args>(nullptr, 0))...> R;
@@ -5726,7 +5876,7 @@ namespace sol {
template <typename... Args>
static int push(lua_State* L, Args&&... args) {
- return push_keyed(L, usertype_traits<T>::metatable, std::forward<Args>(args)...);
+ return push_keyed(L, usertype_traits<T>::metatable(), std::forward<Args>(args)...);
}
};
@@ -5751,7 +5901,7 @@ namespace sol {
}
static int push(lua_State* L, T* obj) {
- return push_keyed(L, usertype_traits<meta::unqualified_t<T>*>::metatable, obj);
+ return push_keyed(L, usertype_traits<meta::unqualified_t<T>*>::metatable(), obj);
}
};
@@ -5804,7 +5954,7 @@ namespace sol {
*fx = detail::special_destruct<P, Real>;
detail::default_construct::construct(mem, std::forward<Args>(args)...);
*pref = unique_usertype_traits<T>::get(*mem);
- if (luaL_newmetatable(L, &usertype_traits<detail::unique_usertype<P>>::metatable[0]) == 1) {
+ if (luaL_newmetatable(L, &usertype_traits<detail::unique_usertype<P>>::metatable()[0]) == 1) {
set_field(L, "__gc", detail::unique_destruct<P>);
}
lua_setmetatable(L, -2);
@@ -6026,13 +6176,13 @@ namespace sol {
template <typename Arg, typename... Args, meta::disable<meta::any_same<meta::unqualified_t<Arg>, no_metatable_t, metatable_key_t>> = meta::enabler>
static int push(lua_State* L, Arg&& arg, Args&&... args) {
- const auto name = &usertype_traits<meta::unqualified_t<T>>::user_gc_metatable[0];
+ const auto name = &usertype_traits<meta::unqualified_t<T>>::user_gc_metatable()[0];
return push_with(L, name, std::forward<Arg>(arg), std::forward<Args>(args)...);
}
template <typename... Args>
static int push(lua_State* L, no_metatable_t, Args&&... args) {
- const auto name = &usertype_traits<meta::unqualified_t<T>>::user_gc_metatable[0];
+ const auto name = &usertype_traits<meta::unqualified_t<T>>::user_gc_metatable()[0];
return push_with<false>(L, name, std::forward<Args>(args)...);
}
@@ -6043,22 +6193,22 @@ namespace sol {
}
static int push(lua_State* L, const user<T>& u) {
- const auto name = &usertype_traits<meta::unqualified_t<T>>::user_gc_metatable[0];
+ const auto name = &usertype_traits<meta::unqualified_t<T>>::user_gc_metatable()[0];
return push_with(L, name, u.value);
}
static int push(lua_State* L, user<T>&& u) {
- const auto name = &usertype_traits<meta::unqualified_t<T>>::user_gc_metatable[0];
+ const auto name = &usertype_traits<meta::unqualified_t<T>>::user_gc_metatable()[0];
return push_with(L, name, std::move(u.value));
}
static int push(lua_State* L, no_metatable_t, const user<T>& u) {
- const auto name = &usertype_traits<meta::unqualified_t<T>>::user_gc_metatable[0];
+ const auto name = &usertype_traits<meta::unqualified_t<T>>::user_gc_metatable()[0];
return push_with<false>(L, name, u.value);
}
static int push(lua_State* L, no_metatable_t, user<T>&& u) {
- const auto name = &usertype_traits<meta::unqualified_t<T>>::user_gc_metatable[0];
+ const auto name = &usertype_traits<meta::unqualified_t<T>>::user_gc_metatable()[0];
return push_with<false>(L, name, std::move(u.value));
}
};
@@ -7335,7 +7485,7 @@ namespace sol {
template <typename Fx, std::size_t I, typename... R, typename... Args>
int operator()(types<Fx>, index_value<I>, types<R...> r, types<Args...> a, lua_State* L, int, int start) const {
detail::default_construct func{};
- return stack::call_into_lua<false>(r, a, L, start, func, obj);
+ return stack::call_into_lua<stack::stack_detail::default_check_arguments>(r, a, L, start, func, obj);
}
};
@@ -7363,11 +7513,50 @@ namespace sol {
}
return matchfx(types<Fx>(), index_value<I>(), return_types(), args_list(), L, fxarity, start, std::forward<Args>(args)...);
}
+
+ template <std::size_t... M, typename Match, typename... Args>
+ inline int overload_match_arity_single(types<>, std::index_sequence<>, std::index_sequence<M...>, Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) {
+ return overload_match_arity(types<>(), std::index_sequence<>(), std::index_sequence<M...>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...);
+ }
+
+ template <typename Fx, std::size_t I, std::size_t... M, typename Match, typename... Args>
+ inline int overload_match_arity_single(types<Fx>, std::index_sequence<I>, std::index_sequence<M...>, Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) {
+ typedef lua_bind_traits<meta::unqualified_t<Fx>> traits;
+ typedef meta::tuple_types<typename traits::return_type> return_types;
+ typedef typename traits::free_args_list args_list;
+ // compile-time eliminate any functions that we know ahead of time are of improper arity
+ if (meta::find_in_pack_v<index_value<traits::free_arity>, index_value<M>...>::value) {
+ return overload_match_arity(types<>(), std::index_sequence<>(), std::index_sequence<M...>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...);
+ }
+ if (traits::free_arity != fxarity) {
+ return overload_match_arity(types<>(), std::index_sequence<>(), std::index_sequence<traits::free_arity, M...>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...);
+ }
+ return matchfx(types<Fx>(), index_value<I>(), return_types(), args_list(), L, fxarity, start, std::forward<Args>(args)...);
+ }
+
+ template <typename Fx, typename Fx1, typename... Fxs, std::size_t I, std::size_t I1, std::size_t... In, std::size_t... M, typename Match, typename... Args>
+ inline int overload_match_arity_single(types<Fx, Fx1, Fxs...>, std::index_sequence<I, I1, In...>, std::index_sequence<M...>, Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) {
+ typedef lua_bind_traits<meta::unqualified_t<Fx>> traits;
+ typedef meta::tuple_types<typename traits::return_type> return_types;
+ typedef typename traits::free_args_list args_list;
+ // compile-time eliminate any functions that we know ahead of time are of improper arity
+ if (meta::find_in_pack_v<index_value<traits::free_arity>, index_value<M>...>::value) {
+ return overload_match_arity(types<Fx1, Fxs...>(), std::index_sequence<I1, In...>(), std::index_sequence<M...>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...);
+ }
+ if (traits::free_arity != fxarity) {
+ return overload_match_arity(types<Fx1, Fxs...>(), std::index_sequence<I1, In...>(), std::index_sequence<traits::free_arity, M...>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...);
+ }
+ stack::record tracking{};
+ if (!stack::stack_detail::check_types<true>{}.check(args_list(), L, start, no_panic, tracking)) {
+ return overload_match_arity(types<Fx1, Fxs...>(), std::index_sequence<I1, In...>(), std::index_sequence<M...>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...);
+ }
+ return matchfx(types<Fx>(), index_value<I>(), return_types(), args_list(), L, fxarity, start, std::forward<Args>(args)...);
+ }
} // overload_detail
template <typename... Functions, typename Match, typename... Args>
inline int overload_match_arity(Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) {
- return overload_detail::overload_match_arity(types<Functions...>(), std::make_index_sequence<sizeof...(Functions)>(), std::index_sequence<>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...);
+ return overload_detail::overload_match_arity_single(types<Functions...>(), std::make_index_sequence<sizeof...(Functions)>(), std::index_sequence<>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...);
}
template <typename... Functions, typename Match, typename... Args>
@@ -7384,9 +7573,9 @@ namespace sol {
template <typename T, typename... TypeLists>
inline int construct(lua_State* L) {
- static const auto& meta = usertype_traits<T>::metatable;
+ static const auto& meta = usertype_traits<T>::metatable();
int argcount = lua_gettop(L);
- call_syntax syntax = argcount > 0 ? stack::get_call_syntax(L, meta, 1) : call_syntax::dot;
+ call_syntax syntax = argcount > 0 ? stack::get_call_syntax(L, &usertype_traits<T>::user_metatable()[0], 1) : call_syntax::dot;
argcount -= static_cast<int>(syntax);
T** pointerpointer = reinterpret_cast<T**>(lua_newuserdata(L, sizeof(T*) + sizeof(T)));
@@ -7622,9 +7811,9 @@ namespace sol {
typedef constructor_list<Args...> F;
static int call(lua_State* L, F&) {
- const auto& metakey = usertype_traits<T>::metatable;
+ const auto& metakey = usertype_traits<T>::metatable();
int argcount = lua_gettop(L);
- call_syntax syntax = argcount > 0 ? stack::get_call_syntax(L, metakey, 1) : call_syntax::dot;
+ call_syntax syntax = argcount > 0 ? stack::get_call_syntax(L, &usertype_traits<T>::user_metatable()[0], 1) : call_syntax::dot;
argcount -= static_cast<int>(syntax);
T** pointerpointer = reinterpret_cast<T**>(lua_newuserdata(L, sizeof(T*) + sizeof(T)));
@@ -7654,7 +7843,7 @@ namespace sol {
struct onmatch {
template <typename Fx, std::size_t I, typename... R, typename... Args>
int operator()(types<Fx>, index_value<I>, types<R...> r, types<Args...> a, lua_State* L, int, int start, F& f) {
- const auto& metakey = usertype_traits<T>::metatable;
+ const auto& metakey = usertype_traits<T>::metatable();
T** pointerpointer = reinterpret_cast<T**>(lua_newuserdata(L, sizeof(T*) + sizeof(T)));
reference userdataref(L, -1);
T*& referencepointer = *pointerpointer;
@@ -7669,7 +7858,7 @@ namespace sol {
if (type_of(L, -1) == type::nil) {
lua_pop(L, 1);
std::string err = "sol: unable to get usertype metatable for ";
- err += usertype_traits<T>::name;
+ err += usertype_traits<T>::name();
return luaL_error(L, err.c_str());
}
lua_setmetatable(L, -2);
@@ -7679,7 +7868,7 @@ namespace sol {
};
static int call(lua_State* L, F& f) {
- call_syntax syntax = stack::get_call_syntax(L, usertype_traits<T>::metatable);
+ call_syntax syntax = stack::get_call_syntax(L, &usertype_traits<T>::user_metatable()[0]);
int syntaxval = static_cast<int>(syntax);
int argcount = lua_gettop(L) - syntaxval;
return construct_match<T, meta::pop_front_type_t<meta::function_args_t<Cxs>>...>(onmatch(), L, argcount, 1 + syntaxval, f);
@@ -9507,22 +9696,26 @@ namespace sol {
template<typename Table, typename Key, typename T>
inline bool operator==(T&& left, const proxy<Table, Key>& right) {
- return left == right.template get<std::decay_t<T>>();
+ typedef decltype(stack::get<T>(nullptr, 0)) U;
+ return right.template get<optional<U>>() == left;
}
template<typename Table, typename Key, typename T>
inline bool operator==(const proxy<Table, Key>& right, T&& left) {
- return right.template get<std::decay_t<T>>() == left;
+ typedef decltype(stack::get<T>(nullptr, 0)) U;
+ return right.template get<optional<U>>() == left;
}
template<typename Table, typename Key, typename T>
inline bool operator!=(T&& left, const proxy<Table, Key>& right) {
- return right.template get<std::decay_t<T>>() != left;
+ typedef decltype(stack::get<T>(nullptr, 0)) U;
+ return right.template get<optional<U>>() == left;
}
template<typename Table, typename Key, typename T>
inline bool operator!=(const proxy<Table, Key>& right, T&& left) {
- return right.template get<std::decay_t<T>>() != left;
+ typedef decltype(stack::get<T>(nullptr, 0)) U;
+ return right.template get<optional<U>>() == left;
}
template<typename Table, typename Key>
@@ -9670,8 +9863,8 @@ namespace sol {
static void walk_single_base(lua_State* L, bool& found, int& ret, string_detail::string_shim&) {
if (found)
return;
- const char* metakey = &usertype_traits<Base>::metatable[0];
- const char* gcmetakey = &usertype_traits<Base>::gc_table[0];
+ const char* metakey = &usertype_traits<Base>::metatable()[0];
+ const char* gcmetakey = &usertype_traits<Base>::gc_table()[0];
const char* basewalkkey = is_index ? detail::base_class_index_propogation_key() : detail::base_class_new_index_propogation_key();
luaL_getmetatable(L, metakey);
@@ -10020,7 +10213,7 @@ namespace sol {
static umt_t& make_cleanup(lua_State* L, umt_t&& umx) {
// ensure some sort of uniqueness
static int uniqueness = 0;
- std::string uniquegcmetakey = usertype_traits<T>::user_gc_metatable;
+ std::string uniquegcmetakey = usertype_traits<T>::user_gc_metatable();
// std::to_string doesn't exist in android still, with NDK, so this bullshit
// is necessary
// thanks, Android :v
@@ -10031,7 +10224,7 @@ namespace sol {
snprintf(uniquetarget, uniquegcmetakey.length(), "%d", uniqueness);
++uniqueness;
- const char* gcmetakey = &usertype_traits<T>::gc_table[0];
+ const char* gcmetakey = &usertype_traits<T>::gc_table()[0];
// Make sure userdata's memory is properly in lua first,
// otherwise all the light userdata we make later will become invalid
stack::push<user<umt_t>>(L, metatable_key, uniquegcmetakey, std::move(umx));
@@ -10068,16 +10261,16 @@ namespace sol {
luaL_Reg* metaregs = nullptr;
switch (i) {
case 0:
- metakey = &usertype_traits<T*>::metatable[0];
+ metakey = &usertype_traits<T*>::metatable()[0];
metaregs = ref_table.data();
break;
case 1:
- metakey = &usertype_traits<detail::unique_usertype<T>>::metatable[0];
+ metakey = &usertype_traits<detail::unique_usertype<T>>::metatable()[0];
metaregs = unique_table.data();
break;
case 2:
default:
- metakey = &usertype_traits<T>::metatable[0];
+ metakey = &usertype_traits<T>::metatable()[0];
metaregs = value_table.data();
break;
}
@@ -10108,7 +10301,7 @@ namespace sol {
}
// metatable on the metatable
// for call constructor purposes and such
- lua_createtable(L, 0, 1);
+ lua_createtable(L, 0, 3);
stack_reference metabehind(L, -1);
if (um.callconstructfunc != nullptr) {
stack::set_field(L, meta_function::call_function, make_closure(um.callconstructfunc, make_light(um)), metabehind.stack_index());
@@ -10121,9 +10314,26 @@ namespace sol {
metabehind.pop();
// We want to just leave the table
// in the registry only, otherwise we return it
- if (i < 2) {
- t.pop();
+ t.pop();
+ }
+
+ // Now for the shim-table that actually gets assigned to the name
+ luaL_newmetatable(L, &usertype_traits<T>::user_metatable()[0]);
+ stack_reference t(L, -1);
+ stack::push(L, make_light(um));
+ luaL_setfuncs(L, value_table.data(), 1);
+ {
+ lua_createtable(L, 0, 3);
+ stack_reference metabehind(L, -1);
+ if (um.callconstructfunc != nullptr) {
+ stack::set_field(L, meta_function::call_function, make_closure(um.callconstructfunc, make_light(um)), metabehind.stack_index());
}
+ if (um.secondarymeta) {
+ stack::set_field(L, meta_function::index, make_closure(umt_t::index_call, make_light(um)), metabehind.stack_index());
+ stack::set_field(L, meta_function::new_index, make_closure(umt_t::new_index_call, make_light(um)), metabehind.stack_index());
+ }
+ stack::set_field(L, metatable_key, metabehind, t.stack_index());
+ metabehind.pop();
}
return 1;
@@ -10141,6 +10351,8 @@ namespace sol {
namespace sol {
namespace usertype_detail {
+ const lua_Integer toplevel_magic = static_cast<lua_Integer>(0x00000001);
+
struct variable_wrapper {
virtual int index(lua_State* L) = 0;
virtual int new_index(lua_State* L) = 0;
@@ -10178,8 +10390,31 @@ namespace sol {
template <typename T>
inline int simple_metatable_newindex(lua_State* L) {
- if (stack::stack_detail::check_metatable<T, false>(L, 1)) {
- stack::set_field<false, true>(L, stack_reference(L, 2), stack_reference(L, 3), 1);
+ int isnum = 0;
+ lua_Integer magic = lua_tointegerx(L, lua_upvalueindex(4), &isnum);
+ if (isnum != 0 && magic == toplevel_magic) {
+ for (std::size_t i = 0; i < 3; lua_pop(L, 1), ++i) {
+ // Pointer types, AKA "references" from C++
+ const char* metakey = nullptr;
+ switch (i) {
+ case 0:
+ metakey = &usertype_traits<T*>::metatable()[0];
+ break;
+ case 1:
+ metakey = &usertype_traits<detail::unique_usertype<T>>::metatable()[0];
+ break;
+ case 2:
+ default:
+ metakey = &usertype_traits<T>::metatable()[0];
+ break;
+ }
+ luaL_getmetatable(L, metakey);
+ int tableindex = lua_gettop(L);
+ if (type_of(L, tableindex) == type::nil) {
+ continue;
+ }
+ stack::set_field<false, true>(L, stack_reference(L, 2), stack_reference(L, 3), tableindex);
+ }
lua_settop(L, 0);
return 0;
}
@@ -10369,15 +10604,15 @@ namespace sol {
template <typename... Bases>
void add(lua_State*, base_classes_tag, bases<Bases...>) {
- static_assert(sizeof(usertype_detail::base_walk) <= sizeof(void*), "size of function pointer is greater than sizeof(void*); cannot work on this platform");
+ static_assert(sizeof(usertype_detail::base_walk) <= sizeof(void*), "size of function pointer is greater than sizeof(void*); cannot work on this platform. Please file a bug report.");
if (sizeof...(Bases) < 1) {
return;
}
mustindex = true;
(void)detail::swallow{ 0, ((detail::has_derived<Bases>::value = true), 0)... };
- static_assert(sizeof(void*) <= sizeof(detail::inheritance_check_function), "The size of this data pointer is too small to fit the inheritance checking function: file a bug report.");
- static_assert(sizeof(void*) <= sizeof(detail::inheritance_cast_function), "The size of this data pointer is too small to fit the inheritance checking function: file a bug report.");
+ static_assert(sizeof(void*) <= sizeof(detail::inheritance_check_function), "The size of this data pointer is too small to fit the inheritance checking function: Please file a bug report.");
+ static_assert(sizeof(void*) <= sizeof(detail::inheritance_cast_function), "The size of this data pointer is too small to fit the inheritance checking function: Please file a bug report.");
baseclasscheck = (void*)&detail::inheritance<T, Bases...>::type_check;
baseclasscast = (void*)&detail::inheritance<T, Bases...>::type_cast;
indexbaseclasspropogation = usertype_detail::walk_all_bases<true, Bases...>;
@@ -10388,11 +10623,11 @@ namespace sol {
template<std::size_t... I, typename Tuple>
simple_usertype_metatable(usertype_detail::verified_tag, std::index_sequence<I...>, lua_State* L, Tuple&& args)
: callconstructfunc(nil),
- indexfunc(&usertype_detail::indexing_fail<true>), newindexfunc(&usertype_detail::simple_metatable_newindex<T>),
+ indexfunc(&usertype_detail::indexing_fail<true>), newindexfunc(&usertype_detail::indexing_fail<false>),
indexbase(&usertype_detail::simple_core_indexing_call<true>), newindexbase(&usertype_detail::simple_core_indexing_call<false>),
indexbaseclasspropogation(usertype_detail::walk_all_bases<true>), newindexbaseclasspropogation(&usertype_detail::walk_all_bases<false>),
baseclasscheck(nullptr), baseclasscast(nullptr),
- mustindex(true), secondarymeta(true) {
+ mustindex(false), secondarymeta(false) {
(void)detail::swallow{ 0,
(add(L, detail::forward_get<I * 2>(args), detail::forward_get<I * 2 + 1>(args)),0)...
};
@@ -10439,7 +10674,7 @@ namespace sol {
static usertype_detail::simple_map& make_cleanup(lua_State* L, umt_t& umx) {
static int uniqueness = 0;
- std::string uniquegcmetakey = usertype_traits<T>::user_gc_metatable;
+ std::string uniquegcmetakey = usertype_traits<T>::user_gc_metatable();
// std::to_string doesn't exist in android still, with NDK, so this bullshit
// is necessary
// thanks, Android :v
@@ -10450,8 +10685,11 @@ namespace sol {
snprintf(uniquetarget, uniquegcmetakey.length(), "%d", uniqueness);
++uniqueness;
- const char* gcmetakey = &usertype_traits<T>::gc_table[0];
- stack::push<user<usertype_detail::simple_map>>(L, metatable_key, uniquegcmetakey, &usertype_traits<T>::metatable[0], umx.indexbaseclasspropogation, umx.newindexbaseclasspropogation, std::move(umx.varmap), std::move(umx.registrations));
+ const char* gcmetakey = &usertype_traits<T>::gc_table()[0];
+ stack::push<user<usertype_detail::simple_map>>(L, metatable_key, uniquegcmetakey, &usertype_traits<T>::metatable()[0],
+ umx.indexbaseclasspropogation, umx.newindexbaseclasspropogation,
+ std::move(umx.varmap), std::move(umx.registrations)
+ );
stack_reference stackvarmap(L, -1);
stack::set_field<true>(L, gcmetakey, stackvarmap);
stackvarmap.pop();
@@ -10466,19 +10704,53 @@ namespace sol {
bool hasequals = false;
bool hasless = false;
bool haslessequals = false;
+ auto register_kvp = [&](std::size_t i, stack_reference& t, const std::string& first, object& second) {
+ if (first == name_of(meta_function::equal_to)) {
+ hasequals = true;
+ }
+ else if (first == name_of(meta_function::less_than)) {
+ hasless = true;
+ }
+ else if (first == name_of(meta_function::less_than_or_equal_to)) {
+ haslessequals = true;
+ }
+ else if (first == name_of(meta_function::index)) {
+ umx.indexfunc = second.template as<lua_CFunction>();
+ }
+ else if (first == name_of(meta_function::new_index)) {
+ umx.newindexfunc = second.template as<lua_CFunction>();
+ }
+ switch (i) {
+ case 0:
+ if (first == name_of(meta_function::garbage_collect)) {
+ return;
+ }
+ break;
+ case 1:
+ if (first == name_of(meta_function::garbage_collect)) {
+ stack::set_field(L, first, detail::unique_destruct<T>, t.stack_index());
+ return;
+ }
+ break;
+ case 2:
+ default:
+ break;
+ }
+ stack::set_field(L, first, second, t.stack_index());
+ };
for (std::size_t i = 0; i < 3; ++i) {
// Pointer types, AKA "references" from C++
const char* metakey = nullptr;
switch (i) {
case 0:
- metakey = &usertype_traits<T*>::metatable[0];
+ metakey = &usertype_traits<T*>::metatable()[0];
break;
case 1:
- metakey = &usertype_traits<detail::unique_usertype<T>>::metatable[0];
+ metakey = &usertype_traits<detail::unique_usertype<T>>::metatable()[0];
break;
case 2:
default:
- metakey = &usertype_traits<T>::metatable[0];
+ metakey = &usertype_traits<T>::metatable()[0];
break;
}
luaL_newmetatable(L, metakey);
@@ -10486,38 +10758,7 @@ namespace sol {
for (auto& kvp : varmap.functions) {
auto& first = std::get<0>(kvp);
auto& second = std::get<1>(kvp);
- if (first == name_of(meta_function::equal_to)) {
- hasequals = true;
- }
- else if (first == name_of(meta_function::less_than)) {
- hasless = true;
- }
- else if (first == name_of(meta_function::less_than_or_equal_to)) {
- haslessequals = true;
- }
- else if (first == name_of(meta_function::index)) {
- umx.indexfunc = second.template as<lua_CFunction>();
- }
- else if (first == name_of(meta_function::new_index)) {
- umx.newindexfunc = second.template as<lua_CFunction>();
- }
- switch (i) {
- case 0:
- if (first == name_of(meta_function::garbage_collect)) {
- continue;
- }
- break;
- case 1:
- if (first == name_of(meta_function::garbage_collect)) {
- stack::set_field(L, first, detail::unique_destruct<T>, t.stack_index());
- continue;
- }
- break;
- case 2:
- default:
- break;
- }
- stack::set_field(L, first, second, t.stack_index());
+ register_kvp(i, t, first, second);
}
luaL_Reg opregs[4]{};
int opregsindex = 0;
@@ -10550,7 +10791,6 @@ namespace sol {
if (umx.mustindex) {
// use indexing function
- static_assert(sizeof(usertype_detail::base_walk) <= sizeof(void*), "The size of this data pointer is too small to fit the base class index propagation key: file a bug report.");
stack::set_field(L, meta_function::index,
make_closure(&usertype_detail::simple_index_call,
make_light(varmap),
@@ -10570,7 +10810,7 @@ namespace sol {
}
// metatable on the metatable
// for call constructor purposes and such
- lua_createtable(L, 0, 1);
+ lua_createtable(L, 0, 2 * static_cast<int>(umx.secondarymeta) + static_cast<int>(umx.callconstructfunc.valid()));
stack_reference metabehind(L, -1);
if (umx.callconstructfunc.valid()) {
stack::set_field(L, sol::meta_function::call_function, umx.callconstructfunc, metabehind.stack_index());
@@ -10592,9 +10832,44 @@ namespace sol {
stack::set_field(L, metatable_key, metabehind, t.stack_index());
metabehind.pop();
- if (i < 2)
- t.pop();
+ t.pop();
}
+
+ // Now for the shim-table that actually gets pushed
+ luaL_newmetatable(L, &usertype_traits<T>::user_metatable()[0]);
+ stack_reference t(L, -1);
+ for (auto& kvp : varmap.functions) {
+ auto& first = std::get<0>(kvp);
+ auto& second = std::get<1>(kvp);
+ register_kvp(2, t, first, second);
+ }
+ {
+ lua_createtable(L, 0, 2 + static_cast<int>(umx.callconstructfunc.valid()));
+ stack_reference metabehind(L, -1);
+ if (umx.callconstructfunc.valid()) {
+ stack::set_field(L, sol::meta_function::call_function, umx.callconstructfunc, metabehind.stack_index());
+ }
+ // use indexing function
+ stack::set_field(L, meta_function::index,
+ make_closure(&usertype_detail::simple_index_call,
+ make_light(varmap),
+ &usertype_detail::simple_index_call,
+ &usertype_detail::simple_metatable_newindex<T>,
+ usertype_detail::toplevel_magic
+ ), metabehind.stack_index());
+ stack::set_field(L, meta_function::new_index,
+ make_closure(&usertype_detail::simple_new_index_call,
+ make_light(varmap),
+ &usertype_detail::simple_index_call,
+ &usertype_detail::simple_metatable_newindex<T>,
+ usertype_detail::toplevel_magic
+ ), metabehind.stack_index());
+ stack::set_field(L, metatable_key, metabehind, t.stack_index());
+ metabehind.pop();
+ }
+
+ // Don't pop the table when we're done;
+ // return it
return 1;
}
};
@@ -10623,6 +10898,19 @@ namespace sol {
};
template <typename T>
+ struct has_push_back {
+ private:
+ typedef std::array<char, 1> one;
+ typedef std::array<char, 2> two;
+
+ template <typename C> static one test(decltype(&C::push_back));
+ template <typename C> static two test(...);
+
+ public:
+ static const bool value = sizeof(test<T>(0)) == sizeof(char);
+ };
+
+ template <typename T>
T& get_first(const T& t) {
return std::forward<T>(t);
}
@@ -10677,58 +10965,65 @@ namespace sol {
static int real_index_call(lua_State* L) {
auto& src = get_src(L);
-#ifdef SOL_SAFE_USERTYPE
auto maybek = stack::check_get<K>(L, 2);
if (maybek) {
using std::begin;
auto it = begin(src);
K k = *maybek;
- if (k <= src.size() && k > 0) {
- --k;
- std::advance(it, k);
- return stack::push_reference(L, *it);
+#ifdef SOL_SAFE_USERTYPE
+ if (k > src.size() || k < 1) {
+ return stack::push(L, nil);
}
- }
- return stack::push(L, nil);
#else
- using std::begin;
- auto it = begin(src);
- K k = stack::get<K>(L, 2);
- --k;
- std::advance(it, k);
- return stack::push_reference(L, *it);
#endif // Safety
+ --k;
+ std::advance(it, k);
+ return stack::push_reference(L, *it);
+ }
+ else {
+ auto maybename = stack::check_get<string_detail::string_shim>(L, 2);
+ if (maybename) {
+ auto& name = *maybename;
+ if (name == "add") {
+ return stack::push(L, &add_call);
+ }
+ else if (name == "insert") {
+ return stack::push(L, &insert_call);
+ }
+ else if (name == "clear") {
+ return stack::push(L, &clear_call);
+ }
+ }
+ }
+
+ return stack::push(L, nil);
}
- template <bool b, meta::disable<meta::boolean<b>> = meta::enabler>
- static int real_new_index_call_const(std::integral_constant<bool, b>, lua_State* L) {
+ static int real_new_index_call_const(std::false_type, lua_State* L) {
luaL_error(L, "sol: cannot write to a const value type or an immutable iterator (e.g., std::set)");
return 0;
}
- template <bool b, meta::enable<meta::boolean<b>> = meta::enabler>
- static int real_new_index_call_const(std::integral_constant<bool, b>, lua_State* L) {
+ static int real_new_index_call_const(std::true_type, lua_State* L) {
auto& src = get_src(L);
#ifdef SOL_SAFE_USERTYPE
auto maybek = stack::check_get<K>(L, 2);
- if (maybek) {
- K k = *maybek;
- if (k <= src.size() && k > 0) {
- --k;
- using std::begin;
- auto it = begin(src);
- std::advance(it, k);
- *it = stack::get<V>(L, 3);
- }
+ if (!maybek) {
+ return stack::push(L, nil);
}
+ K k = *maybek;
#else
+ K k = stack::get<K>(L, 2);
+#endif
using std::begin;
auto it = begin(src);
- K k = stack::get<K>(L, 2);
+ if (k == src.size()) {
+ real_add_call_push(std::integral_constant<bool, detail::has_push_back<T>::value>(), L, src, 1);
+ return 0;
+ }
--k;
std::advance(it, k);
*it = stack::get<V>(L, 3);
-#endif
return 0;
}
@@ -10764,13 +11059,22 @@ namespace sol {
return stack::push(L, src.size());
}
-#if 0
- static int real_push_back_call(lua_State*L) {
- auto& src = get_src(L);
- src.push_back(stack::get<V>(L, 2));
+ static int real_add_call_push(std::true_type, lua_State*L, T& src, int boost = 0) {
+ src.push_back(stack::get<V>(L, 2 + boost));
return 0;
}
+ static int real_add_call_push(std::false_type, lua_State*L, T& src, int boost = 0) {
+ using std::end;
+ src.insert(end(src), stack::get<V>(L, 2 + boost));
+ return 0;
+ }
+
+ static int real_add_call(lua_State*L) {
+ auto& src = get_src(L);
+ return real_add_call_push(std::integral_constant<bool, detail::has_push_back<T>::value>(), L, src);
+ }
+
static int real_insert_call(lua_State*L) {
using std::begin;
auto& src = get_src(L);
@@ -10778,14 +11082,23 @@ namespace sol {
return 0;
}
- static int push_back_call(lua_State*L) {
- return detail::static_trampoline<(&real_length_call)>(L);
+ static int real_clear_call(lua_State*L) {
+ auto& src = get_src(L);
+ src.clear();
+ return 0;
+ }
+
+ static int add_call(lua_State*L) {
+ return detail::static_trampoline<(&real_add_call)>(L);
}
static int insert_call(lua_State*L) {
return detail::static_trampoline<(&real_insert_call)>(L);
}
-#endif // Sometime later, in a distant universe...
+
+ static int clear_call(lua_State*L) {
+ return detail::static_trampoline<(&real_clear_call)>(L);
+ }
static int length_call(lua_State*L) {
return detail::static_trampoline<(&real_length_call)>(L);
@@ -10835,9 +11148,9 @@ namespace sol {
}
static int real_index_call(lua_State* L) {
- auto& src = get_src(L);
auto k = stack::check_get<K>(L, 2);
if (k) {
+ auto& src = get_src(L);
using std::end;
auto it = detail::find(src, *k);
if (it != end(src)) {
@@ -10845,6 +11158,21 @@ namespace sol {
return stack::push_reference(L, v.second);
}
}
+ else {
+ auto maybename = stack::check_get<string_detail::string_shim>(L, 2);
+ if (maybename) {
+ auto& name = *maybename;
+ if (name == "add") {
+ return stack::push(L, &add_call);
+ }
+ else if (name == "insert") {
+ return stack::push(L, &insert_call);
+ }
+ else if (name == "clear") {
+ return stack::push(L, &clear_call);
+ }
+ }
+ }
return stack::push(L, nil);
}
@@ -10879,11 +11207,12 @@ namespace sol {
iter& i = stack::get<user<iter>>(L, 1);
auto& source = i.source;
auto& it = i.it;
- std::advance(it, 1);
if (it == end(source)) {
return 0;
}
- return stack::multi_push_reference(L, it->first, it->second);
+ int p = stack::multi_push_reference(L, it->first, it->second);
+ std::advance(it, 1);
+ return p;
}
static int real_pairs_call(lua_State* L) {
@@ -10900,6 +11229,28 @@ namespace sol {
return stack::push(L, src.size());
}
+ static int real_insert_call(lua_State*L) {
+ return real_new_index_call(L);
+ }
+
+ static int real_clear_call(lua_State*L) {
+ auto& src = get_src(L);
+ src.clear();
+ return 0;
+ }
+
+ static int add_call(lua_State*L) {
+ return detail::static_trampoline<(&real_insert_call)>(L);
+ }
+
+ static int insert_call(lua_State*L) {
+ return detail::static_trampoline<(&real_insert_call)>(L);
+ }
+
+ static int clear_call(lua_State*L) {
+ return detail::static_trampoline<(&real_clear_call)>(L);
+ }
+
static int length_call(lua_State*L) {
return detail::static_trampoline<(&real_length_call)>(L);
}
@@ -10922,67 +11273,80 @@ namespace sol {
};
namespace stack {
+ namespace stack_detail {
+ template <typename T>
+ inline auto container_metatable() {
+ typedef container_usertype_metatable<std::remove_pointer_t<T>> meta_cumt;
+ std::array<luaL_Reg, 10> reg = { {
+ { "__index", &meta_cumt::index_call },
+ { "__newindex", &meta_cumt::new_index_call },
+ { "__pairs", &meta_cumt::pairs_call },
+ { "__ipairs", &meta_cumt::pairs_call },
+ { "__len", &meta_cumt::length_call },
+ { "clear", &meta_cumt::clear_call },
+ { "insert", &meta_cumt::insert_call },
+ { "add", &meta_cumt::add_call },
+ std::is_pointer<T>::value ? luaL_Reg{ nullptr, nullptr } : luaL_Reg{ "__gc", &detail::usertype_alloc_destroy<T> },
+ { nullptr, nullptr }
+ } };
+ return reg;
+ }
- template<typename T>
- struct pusher<T, std::enable_if_t<meta::all<meta::has_begin_end<T>, meta::neg<meta::any<std::is_base_of<reference, T>, std::is_base_of<stack_reference, T>>>>::value>> {
- typedef container_usertype_metatable<T> cumt;
- static int push(lua_State* L, const T& cont) {
- auto fx = [&L]() {
- const char* metakey = &usertype_traits<T>::metatable[0];
+ template <typename T>
+ inline auto container_metatable_behind() {
+ typedef container_usertype_metatable<std::remove_pointer_t<T>> meta_cumt;
+ std::array<luaL_Reg, 3> reg = { {
+ { "__index", &meta_cumt::index_call },
+ { "__newindex", &meta_cumt::new_index_call },
+ { nullptr, nullptr }
+ } };
+ return reg;
+ }
+
+ template <typename T>
+ struct metatable_setup {
+ lua_State* L;
+
+ metatable_setup(lua_State* L) : L(L) {}
+
+ void operator()() {
+ static const auto reg = container_metatable<T>();
+ static const auto containerreg = container_metatable_behind<T>();
+ static const char* metakey = &usertype_traits<T>::metatable()[0];
+
if (luaL_newmetatable(L, metakey) == 1) {
- luaL_Reg reg[] = {
- { "__index", &cumt::index_call },
- { "__newindex", &cumt::new_index_call },
- { "__pairs", &cumt::pairs_call },
- { "__len", &cumt::length_call },
- { "__gc", &detail::usertype_alloc_destroy<T> },
- { nullptr, nullptr }
- };
- luaL_setfuncs(L, reg, 0);
+ stack_reference metatable(L, -1);
+ luaL_setfuncs(L, reg.data(), 0);
+
+ lua_createtable(L, 0, static_cast<int>(containerreg.size()));
+ stack_reference metabehind(L, -1);
+ luaL_setfuncs(L, containerreg.data(), 0);
+
+ stack::set_field(L, metatable_key, metabehind, metatable.stack_index());
+ metabehind.pop();
}
lua_setmetatable(L, -2);
- };
+ }
+ };
+ }
+
+ template<typename T>
+ struct pusher<T, std::enable_if_t<meta::all<is_container<T>, meta::neg<meta::any<std::is_base_of<reference, meta::unqualified_t<T>>, std::is_base_of<stack_reference, meta::unqualified_t<T>>>>>::value>> {
+ static int push(lua_State* L, const T& cont) {
+ stack_detail::metatable_setup<T> fx(L);
return pusher<detail::as_value_tag<T>>{}.push_fx(L, fx, cont);
}
static int push(lua_State* L, T&& cont) {
- auto fx = [&L]() {
- const char* metakey = &usertype_traits<T>::metatable[0];
- if (luaL_newmetatable(L, metakey) == 1) {
- luaL_Reg reg[] = {
- { "__index", &cumt::index_call },
- { "__newindex", &cumt::new_index_call },
- { "__pairs", &cumt::pairs_call },
- { "__len", &cumt::length_call },
- { "__gc", &detail::usertype_alloc_destroy<T> },
- { nullptr, nullptr }
- };
- luaL_setfuncs(L, reg, 0);
- }
- lua_setmetatable(L, -2);
- };
+ stack_detail::metatable_setup<T> fx(L);
return pusher<detail::as_value_tag<T>>{}.push_fx(L, fx, std::move(cont));
}
};
template<typename T>
- struct pusher<T*, std::enable_if_t<meta::all<meta::has_begin_end<meta::unqualified_t<T>>, meta::neg<meta::any<std::is_base_of<reference, meta::unqualified_t<T>>, std::is_base_of<stack_reference, meta::unqualified_t<T>>>>>::value>> {
- typedef container_usertype_metatable<T> cumt;
+ struct pusher<T*, std::enable_if_t<meta::all<is_container<T>, meta::neg<meta::any<std::is_base_of<reference, meta::unqualified_t<T>>, std::is_base_of<stack_reference, meta::unqualified_t<T>>>>>::value>> {
static int push(lua_State* L, T* cont) {
- auto fx = [&L]() {
- const char* metakey = &usertype_traits<meta::unqualified_t<T>*>::metatable[0];
- if (luaL_newmetatable(L, metakey) == 1) {
- luaL_Reg reg[] = {
- { "__index", &cumt::index_call },
- { "__newindex", &cumt::new_index_call },
- { "__pairs", &cumt::pairs_call },
- { "__len", &cumt::length_call },
- { nullptr, nullptr }
- };
- luaL_setfuncs(L, reg, 0);
- }
- lua_setmetatable(L, -2);
- };
+ stack_detail::metatable_setup<T*> fx(L);
return pusher<detail::as_pointer_tag<T>>{}.push_fx(L, fx, cont);
}
};
@@ -11372,7 +11736,7 @@ namespace sol {
template<typename T>
basic_table_core& set_usertype(usertype<T>& user) {
- return set_usertype(usertype_traits<T>::name, user);
+ return set_usertype(usertype_traits<T>::name(), user);
}
template<typename Key, typename T>
@@ -11547,6 +11911,7 @@ namespace sol {
template <typename... Args>
static inline table create_with(lua_State* L, Args&&... args) {
+ static_assert(sizeof...(Args) % 2 == 0, "You must have an even number of arguments for a key, value ... list.");
static const int narr = static_cast<int>(meta::count_2_for_pack<std::is_integral, Args...>::value);
return create(L, narr, static_cast<int>((sizeof...(Args) / 2) - narr), std::forward<Args>(args)...);
}
@@ -11689,7 +12054,7 @@ namespace sol {
template<typename... Ret, typename... Args>
decltype(auto) call(Args&&... args) {
- return get<function>().template call<Ret...>(std::forward<Args>(args)...);
+ return get<protected_function>().template call<Ret...>(std::forward<Args>(args)...);
}
template<typename... Args>
@@ -11796,6 +12161,10 @@ namespace sol {
}
+ state_view(this_state L) : state_view(L.L){
+
+ }
+
lua_State* lua_state() const {
return L;
}
@@ -11903,18 +12272,30 @@ namespace sol {
return require_core(key, [this, &filename]() {stack::script_file(L, filename); }, create_global);
}
+ protected_function_result do_string(const std::string& code) {
+ sol::protected_function pf = load(code);
+ return pf();
+ }
+
+ protected_function_result do_file(const std::string& filename) {
+ sol::protected_function pf = load_file(filename);
+ return pf();
+ }
+
function_result script(const std::string& code) {
- int index = (::std::max)(lua_gettop(L), 1);
+ int index = lua_gettop(L);
stack::script(L, code);
- int returns = lua_gettop(L) - (index - 1);
- return function_result(L, index, returns);
+ int postindex = lua_gettop(L);
+ int returns = postindex - index;
+ return function_result(L, (std::max)(postindex - (returns - 1), 1), returns);
}
function_result script_file(const std::string& filename) {
- int index = (::std::max)(lua_gettop(L), 1);
+ int index = lua_gettop(L);
stack::script_file(L, filename);
- int returns = lua_gettop(L) - (index - 1);
- return function_result(L, index, returns);
+ int postindex = lua_gettop(L);
+ int returns = postindex - index;
+ return function_result(L, (std::max)(postindex - (returns - 1), 1), returns);
}
load_result load(const std::string& code) {
@@ -11998,7 +12379,7 @@ namespace sol {
template<typename T>
state_view& set_usertype(usertype<T>& user) {
- return set_usertype(usertype_traits<T>::name, user);
+ return set_usertype(usertype_traits<T>::name(), user);
}
template<typename Key, typename T>
@@ -12147,8 +12528,12 @@ namespace sol {
return -1;
#else
const char* message = lua_tostring(L, -1);
- std::string err = message ? message : "An unexpected error occurred and forced the lua state to call atpanic";
- throw error(err);
+ if (message) {
+ std::string err = message;
+ lua_pop(L, 1);
+ throw error(err);
+ }
+ throw error(std::string("An unexpected error occurred and forced the lua state to call atpanic"));
#endif
}
diff --git a/3rdparty/sol2/sol/call.hpp b/3rdparty/sol2/sol/call.hpp
index 0abeeefaa18..9f6a3af8c4c 100644
--- a/3rdparty/sol2/sol/call.hpp
+++ b/3rdparty/sol2/sol/call.hpp
@@ -57,7 +57,7 @@ namespace sol {
template <typename Fx, std::size_t I, typename... R, typename... Args>
int operator()(types<Fx>, index_value<I>, types<R...> r, types<Args...> a, lua_State* L, int, int start) const {
detail::default_construct func{};
- return stack::call_into_lua<false>(r, a, L, start, func, obj);
+ return stack::call_into_lua<stack::stack_detail::default_check_arguments>(r, a, L, start, func, obj);
}
};
@@ -85,11 +85,50 @@ namespace sol {
}
return matchfx(types<Fx>(), index_value<I>(), return_types(), args_list(), L, fxarity, start, std::forward<Args>(args)...);
}
+
+ template <std::size_t... M, typename Match, typename... Args>
+ inline int overload_match_arity_single(types<>, std::index_sequence<>, std::index_sequence<M...>, Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) {
+ return overload_match_arity(types<>(), std::index_sequence<>(), std::index_sequence<M...>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...);
+ }
+
+ template <typename Fx, std::size_t I, std::size_t... M, typename Match, typename... Args>
+ inline int overload_match_arity_single(types<Fx>, std::index_sequence<I>, std::index_sequence<M...>, Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) {
+ typedef lua_bind_traits<meta::unqualified_t<Fx>> traits;
+ typedef meta::tuple_types<typename traits::return_type> return_types;
+ typedef typename traits::free_args_list args_list;
+ // compile-time eliminate any functions that we know ahead of time are of improper arity
+ if (meta::find_in_pack_v<index_value<traits::free_arity>, index_value<M>...>::value) {
+ return overload_match_arity(types<>(), std::index_sequence<>(), std::index_sequence<M...>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...);
+ }
+ if (traits::free_arity != fxarity) {
+ return overload_match_arity(types<>(), std::index_sequence<>(), std::index_sequence<traits::free_arity, M...>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...);
+ }
+ return matchfx(types<Fx>(), index_value<I>(), return_types(), args_list(), L, fxarity, start, std::forward<Args>(args)...);
+ }
+
+ template <typename Fx, typename Fx1, typename... Fxs, std::size_t I, std::size_t I1, std::size_t... In, std::size_t... M, typename Match, typename... Args>
+ inline int overload_match_arity_single(types<Fx, Fx1, Fxs...>, std::index_sequence<I, I1, In...>, std::index_sequence<M...>, Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) {
+ typedef lua_bind_traits<meta::unqualified_t<Fx>> traits;
+ typedef meta::tuple_types<typename traits::return_type> return_types;
+ typedef typename traits::free_args_list args_list;
+ // compile-time eliminate any functions that we know ahead of time are of improper arity
+ if (meta::find_in_pack_v<index_value<traits::free_arity>, index_value<M>...>::value) {
+ return overload_match_arity(types<Fx1, Fxs...>(), std::index_sequence<I1, In...>(), std::index_sequence<M...>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...);
+ }
+ if (traits::free_arity != fxarity) {
+ return overload_match_arity(types<Fx1, Fxs...>(), std::index_sequence<I1, In...>(), std::index_sequence<traits::free_arity, M...>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...);
+ }
+ stack::record tracking{};
+ if (!stack::stack_detail::check_types<true>{}.check(args_list(), L, start, no_panic, tracking)) {
+ return overload_match_arity(types<Fx1, Fxs...>(), std::index_sequence<I1, In...>(), std::index_sequence<M...>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...);
+ }
+ return matchfx(types<Fx>(), index_value<I>(), return_types(), args_list(), L, fxarity, start, std::forward<Args>(args)...);
+ }
} // overload_detail
template <typename... Functions, typename Match, typename... Args>
inline int overload_match_arity(Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) {
- return overload_detail::overload_match_arity(types<Functions...>(), std::make_index_sequence<sizeof...(Functions)>(), std::index_sequence<>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...);
+ return overload_detail::overload_match_arity_single(types<Functions...>(), std::make_index_sequence<sizeof...(Functions)>(), std::index_sequence<>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...);
}
template <typename... Functions, typename Match, typename... Args>
@@ -106,9 +145,9 @@ namespace sol {
template <typename T, typename... TypeLists>
inline int construct(lua_State* L) {
- static const auto& meta = usertype_traits<T>::metatable;
+ static const auto& meta = usertype_traits<T>::metatable();
int argcount = lua_gettop(L);
- call_syntax syntax = argcount > 0 ? stack::get_call_syntax(L, meta, 1) : call_syntax::dot;
+ call_syntax syntax = argcount > 0 ? stack::get_call_syntax(L, &usertype_traits<T>::user_metatable()[0], 1) : call_syntax::dot;
argcount -= static_cast<int>(syntax);
T** pointerpointer = reinterpret_cast<T**>(lua_newuserdata(L, sizeof(T*) + sizeof(T)));
@@ -344,9 +383,9 @@ namespace sol {
typedef constructor_list<Args...> F;
static int call(lua_State* L, F&) {
- const auto& metakey = usertype_traits<T>::metatable;
+ const auto& metakey = usertype_traits<T>::metatable();
int argcount = lua_gettop(L);
- call_syntax syntax = argcount > 0 ? stack::get_call_syntax(L, metakey, 1) : call_syntax::dot;
+ call_syntax syntax = argcount > 0 ? stack::get_call_syntax(L, &usertype_traits<T>::user_metatable()[0], 1) : call_syntax::dot;
argcount -= static_cast<int>(syntax);
T** pointerpointer = reinterpret_cast<T**>(lua_newuserdata(L, sizeof(T*) + sizeof(T)));
@@ -376,7 +415,7 @@ namespace sol {
struct onmatch {
template <typename Fx, std::size_t I, typename... R, typename... Args>
int operator()(types<Fx>, index_value<I>, types<R...> r, types<Args...> a, lua_State* L, int, int start, F& f) {
- const auto& metakey = usertype_traits<T>::metatable;
+ const auto& metakey = usertype_traits<T>::metatable();
T** pointerpointer = reinterpret_cast<T**>(lua_newuserdata(L, sizeof(T*) + sizeof(T)));
reference userdataref(L, -1);
T*& referencepointer = *pointerpointer;
@@ -391,7 +430,7 @@ namespace sol {
if (type_of(L, -1) == type::nil) {
lua_pop(L, 1);
std::string err = "sol: unable to get usertype metatable for ";
- err += usertype_traits<T>::name;
+ err += usertype_traits<T>::name();
return luaL_error(L, err.c_str());
}
lua_setmetatable(L, -2);
@@ -401,7 +440,7 @@ namespace sol {
};
static int call(lua_State* L, F& f) {
- call_syntax syntax = stack::get_call_syntax(L, usertype_traits<T>::metatable);
+ call_syntax syntax = stack::get_call_syntax(L, &usertype_traits<T>::user_metatable()[0]);
int syntaxval = static_cast<int>(syntax);
int argcount = lua_gettop(L) - syntaxval;
return construct_match<T, meta::pop_front_type_t<meta::function_args_t<Cxs>>...>(onmatch(), L, argcount, 1 + syntaxval, f);
diff --git a/3rdparty/sol2/sol/compatibility/5.1.0.h b/3rdparty/sol2/sol/compatibility/5.1.0.h
index 0050b24eca4..7484aedf18f 100644
--- a/3rdparty/sol2/sol/compatibility/5.1.0.h
+++ b/3rdparty/sol2/sol/compatibility/5.1.0.h
@@ -158,7 +158,7 @@ inline const char* kepler_lua_compat_get_string(lua_State* L, void* ud, size_t*
return ls->s;
}
-#if !defined(SOL_LUAJIT) || ((SOL_LUAJIT_VERSION - 020100) <= 0)
+#if !defined(SOL_LUAJIT) || ((SOL_LUAJIT_VERSION - 20100) <= 0)
// Luajit 2.1.0 has this function already
inline int luaL_loadbufferx(lua_State* L, const char* buff, size_t size, const char* name, const char*) {
diff --git a/3rdparty/sol2/sol/compatibility/5.2.0.h b/3rdparty/sol2/sol/compatibility/5.2.0.h
new file mode 100644
index 00000000000..7068f2a3291
--- /dev/null
+++ b/3rdparty/sol2/sol/compatibility/5.2.0.h
@@ -0,0 +1,43 @@
+// The MIT License (MIT)
+
+// Copyright (c) 2013-2016 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.
+
+#ifndef SOL_5_2_0_H
+#define SOL_5_2_0_H
+#include "version.hpp"
+
+#if SOL_LUA_VERSION < 503
+
+inline int lua_isinteger(lua_State* L, int idx) {
+ if (lua_type(L, idx) != LUA_TNUMBER)
+ return 0;
+ // This is a very slipshod way to do the testing
+ // but lua_totingerx doesn't play ball nicely
+ // on older versions...
+ lua_Number n = lua_tonumber(L, idx);
+ lua_Integer i = lua_tointeger(L, idx);
+ if (i != n)
+ return 0;
+ // it's DEFINITELY an integer
+ return 1;
+}
+
+#endif // SOL_LUA_VERSION == 502
+#endif // SOL_5_2_0_H
diff --git a/3rdparty/sol2/sol/compatibility/5.x.x.inl b/3rdparty/sol2/sol/compatibility/5.x.x.inl
index 1d420e3f3f6..17bab23cb57 100644
--- a/3rdparty/sol2/sol/compatibility/5.x.x.inl
+++ b/3rdparty/sol2/sol/compatibility/5.x.x.inl
@@ -23,6 +23,7 @@
#define SOL_5_X_X_INL
#include "version.hpp"
+#include "5.2.0.h"
#include "5.1.0.h"
#include "5.0.0.h"
#include "5.x.x.h"
diff --git a/3rdparty/sol2/sol/container_usertype_metatable.hpp b/3rdparty/sol2/sol/container_usertype_metatable.hpp
index a07b85be851..268f8db1616 100644
--- a/3rdparty/sol2/sol/container_usertype_metatable.hpp
+++ b/3rdparty/sol2/sol/container_usertype_metatable.hpp
@@ -42,6 +42,19 @@ namespace sol {
};
template <typename T>
+ struct has_push_back {
+ private:
+ typedef std::array<char, 1> one;
+ typedef std::array<char, 2> two;
+
+ template <typename C> static one test(decltype(&C::push_back));
+ template <typename C> static two test(...);
+
+ public:
+ static const bool value = sizeof(test<T>(0)) == sizeof(char);
+ };
+
+ template <typename T>
T& get_first(const T& t) {
return std::forward<T>(t);
}
@@ -96,58 +109,65 @@ namespace sol {
static int real_index_call(lua_State* L) {
auto& src = get_src(L);
-#ifdef SOL_SAFE_USERTYPE
auto maybek = stack::check_get<K>(L, 2);
if (maybek) {
using std::begin;
auto it = begin(src);
K k = *maybek;
- if (k <= src.size() && k > 0) {
- --k;
- std::advance(it, k);
- return stack::push_reference(L, *it);
+#ifdef SOL_SAFE_USERTYPE
+ if (k > src.size() || k < 1) {
+ return stack::push(L, nil);
}
- }
- return stack::push(L, nil);
#else
- using std::begin;
- auto it = begin(src);
- K k = stack::get<K>(L, 2);
- --k;
- std::advance(it, k);
- return stack::push_reference(L, *it);
#endif // Safety
+ --k;
+ std::advance(it, k);
+ return stack::push_reference(L, *it);
+ }
+ else {
+ auto maybename = stack::check_get<string_detail::string_shim>(L, 2);
+ if (maybename) {
+ auto& name = *maybename;
+ if (name == "add") {
+ return stack::push(L, &add_call);
+ }
+ else if (name == "insert") {
+ return stack::push(L, &insert_call);
+ }
+ else if (name == "clear") {
+ return stack::push(L, &clear_call);
+ }
+ }
+ }
+
+ return stack::push(L, nil);
}
- template <bool b, meta::disable<meta::boolean<b>> = meta::enabler>
- static int real_new_index_call_const(std::integral_constant<bool, b>, lua_State* L) {
+ static int real_new_index_call_const(std::false_type, lua_State* L) {
luaL_error(L, "sol: cannot write to a const value type or an immutable iterator (e.g., std::set)");
return 0;
}
- template <bool b, meta::enable<meta::boolean<b>> = meta::enabler>
- static int real_new_index_call_const(std::integral_constant<bool, b>, lua_State* L) {
+ static int real_new_index_call_const(std::true_type, lua_State* L) {
auto& src = get_src(L);
#ifdef SOL_SAFE_USERTYPE
auto maybek = stack::check_get<K>(L, 2);
- if (maybek) {
- K k = *maybek;
- if (k <= src.size() && k > 0) {
- --k;
- using std::begin;
- auto it = begin(src);
- std::advance(it, k);
- *it = stack::get<V>(L, 3);
- }
+ if (!maybek) {
+ return stack::push(L, nil);
}
+ K k = *maybek;
#else
+ K k = stack::get<K>(L, 2);
+#endif
using std::begin;
auto it = begin(src);
- K k = stack::get<K>(L, 2);
+ if (k == src.size()) {
+ real_add_call_push(std::integral_constant<bool, detail::has_push_back<T>::value>(), L, src, 1);
+ return 0;
+ }
--k;
std::advance(it, k);
*it = stack::get<V>(L, 3);
-#endif
return 0;
}
@@ -183,13 +203,22 @@ namespace sol {
return stack::push(L, src.size());
}
-#if 0
- static int real_push_back_call(lua_State*L) {
- auto& src = get_src(L);
- src.push_back(stack::get<V>(L, 2));
+ static int real_add_call_push(std::true_type, lua_State*L, T& src, int boost = 0) {
+ src.push_back(stack::get<V>(L, 2 + boost));
+ return 0;
+ }
+
+ static int real_add_call_push(std::false_type, lua_State*L, T& src, int boost = 0) {
+ using std::end;
+ src.insert(end(src), stack::get<V>(L, 2 + boost));
return 0;
}
+ static int real_add_call(lua_State*L) {
+ auto& src = get_src(L);
+ return real_add_call_push(std::integral_constant<bool, detail::has_push_back<T>::value>(), L, src);
+ }
+
static int real_insert_call(lua_State*L) {
using std::begin;
auto& src = get_src(L);
@@ -197,14 +226,23 @@ namespace sol {
return 0;
}
- static int push_back_call(lua_State*L) {
- return detail::static_trampoline<(&real_length_call)>(L);
+ static int real_clear_call(lua_State*L) {
+ auto& src = get_src(L);
+ src.clear();
+ return 0;
+ }
+
+ static int add_call(lua_State*L) {
+ return detail::static_trampoline<(&real_add_call)>(L);
}
static int insert_call(lua_State*L) {
return detail::static_trampoline<(&real_insert_call)>(L);
}
-#endif // Sometime later, in a distant universe...
+
+ static int clear_call(lua_State*L) {
+ return detail::static_trampoline<(&real_clear_call)>(L);
+ }
static int length_call(lua_State*L) {
return detail::static_trampoline<(&real_length_call)>(L);
@@ -254,9 +292,9 @@ namespace sol {
}
static int real_index_call(lua_State* L) {
- auto& src = get_src(L);
auto k = stack::check_get<K>(L, 2);
if (k) {
+ auto& src = get_src(L);
using std::end;
auto it = detail::find(src, *k);
if (it != end(src)) {
@@ -264,6 +302,21 @@ namespace sol {
return stack::push_reference(L, v.second);
}
}
+ else {
+ auto maybename = stack::check_get<string_detail::string_shim>(L, 2);
+ if (maybename) {
+ auto& name = *maybename;
+ if (name == "add") {
+ return stack::push(L, &add_call);
+ }
+ else if (name == "insert") {
+ return stack::push(L, &insert_call);
+ }
+ else if (name == "clear") {
+ return stack::push(L, &clear_call);
+ }
+ }
+ }
return stack::push(L, nil);
}
@@ -298,11 +351,12 @@ namespace sol {
iter& i = stack::get<user<iter>>(L, 1);
auto& source = i.source;
auto& it = i.it;
- std::advance(it, 1);
if (it == end(source)) {
return 0;
}
- return stack::multi_push_reference(L, it->first, it->second);
+ int p = stack::multi_push_reference(L, it->first, it->second);
+ std::advance(it, 1);
+ return p;
}
static int real_pairs_call(lua_State* L) {
@@ -319,6 +373,28 @@ namespace sol {
return stack::push(L, src.size());
}
+ static int real_insert_call(lua_State*L) {
+ return real_new_index_call(L);
+ }
+
+ static int real_clear_call(lua_State*L) {
+ auto& src = get_src(L);
+ src.clear();
+ return 0;
+ }
+
+ static int add_call(lua_State*L) {
+ return detail::static_trampoline<(&real_insert_call)>(L);
+ }
+
+ static int insert_call(lua_State*L) {
+ return detail::static_trampoline<(&real_insert_call)>(L);
+ }
+
+ static int clear_call(lua_State*L) {
+ return detail::static_trampoline<(&real_clear_call)>(L);
+ }
+
static int length_call(lua_State*L) {
return detail::static_trampoline<(&real_length_call)>(L);
}
@@ -341,67 +417,80 @@ namespace sol {
};
namespace stack {
+ namespace stack_detail {
+ template <typename T>
+ inline auto container_metatable() {
+ typedef container_usertype_metatable<std::remove_pointer_t<T>> meta_cumt;
+ std::array<luaL_Reg, 10> reg = { {
+ { "__index", &meta_cumt::index_call },
+ { "__newindex", &meta_cumt::new_index_call },
+ { "__pairs", &meta_cumt::pairs_call },
+ { "__ipairs", &meta_cumt::pairs_call },
+ { "__len", &meta_cumt::length_call },
+ { "clear", &meta_cumt::clear_call },
+ { "insert", &meta_cumt::insert_call },
+ { "add", &meta_cumt::add_call },
+ std::is_pointer<T>::value ? luaL_Reg{ nullptr, nullptr } : luaL_Reg{ "__gc", &detail::usertype_alloc_destroy<T> },
+ { nullptr, nullptr }
+ } };
+ return reg;
+ }
- template<typename T>
- struct pusher<T, std::enable_if_t<meta::all<meta::has_begin_end<T>, meta::neg<meta::any<std::is_base_of<reference, T>, std::is_base_of<stack_reference, T>>>>::value>> {
- typedef container_usertype_metatable<T> cumt;
- static int push(lua_State* L, const T& cont) {
- auto fx = [&L]() {
- const char* metakey = &usertype_traits<T>::metatable[0];
+ template <typename T>
+ inline auto container_metatable_behind() {
+ typedef container_usertype_metatable<std::remove_pointer_t<T>> meta_cumt;
+ std::array<luaL_Reg, 3> reg = { {
+ { "__index", &meta_cumt::index_call },
+ { "__newindex", &meta_cumt::new_index_call },
+ { nullptr, nullptr }
+ } };
+ return reg;
+ }
+
+ template <typename T>
+ struct metatable_setup {
+ lua_State* L;
+
+ metatable_setup(lua_State* L) : L(L) {}
+
+ void operator()() {
+ static const auto reg = container_metatable<T>();
+ static const auto containerreg = container_metatable_behind<T>();
+ static const char* metakey = &usertype_traits<T>::metatable()[0];
+
if (luaL_newmetatable(L, metakey) == 1) {
- luaL_Reg reg[] = {
- { "__index", &cumt::index_call },
- { "__newindex", &cumt::new_index_call },
- { "__pairs", &cumt::pairs_call },
- { "__len", &cumt::length_call },
- { "__gc", &detail::usertype_alloc_destroy<T> },
- { nullptr, nullptr }
- };
- luaL_setfuncs(L, reg, 0);
+ stack_reference metatable(L, -1);
+ luaL_setfuncs(L, reg.data(), 0);
+
+ lua_createtable(L, 0, static_cast<int>(containerreg.size()));
+ stack_reference metabehind(L, -1);
+ luaL_setfuncs(L, containerreg.data(), 0);
+
+ stack::set_field(L, metatable_key, metabehind, metatable.stack_index());
+ metabehind.pop();
}
lua_setmetatable(L, -2);
- };
+ }
+ };
+ }
+
+ template<typename T>
+ struct pusher<T, std::enable_if_t<meta::all<is_container<T>, meta::neg<meta::any<std::is_base_of<reference, meta::unqualified_t<T>>, std::is_base_of<stack_reference, meta::unqualified_t<T>>>>>::value>> {
+ static int push(lua_State* L, const T& cont) {
+ stack_detail::metatable_setup<T> fx(L);
return pusher<detail::as_value_tag<T>>{}.push_fx(L, fx, cont);
}
static int push(lua_State* L, T&& cont) {
- auto fx = [&L]() {
- const char* metakey = &usertype_traits<T>::metatable[0];
- if (luaL_newmetatable(L, metakey) == 1) {
- luaL_Reg reg[] = {
- { "__index", &cumt::index_call },
- { "__newindex", &cumt::new_index_call },
- { "__pairs", &cumt::pairs_call },
- { "__len", &cumt::length_call },
- { "__gc", &detail::usertype_alloc_destroy<T> },
- { nullptr, nullptr }
- };
- luaL_setfuncs(L, reg, 0);
- }
- lua_setmetatable(L, -2);
- };
+ stack_detail::metatable_setup<T> fx(L);
return pusher<detail::as_value_tag<T>>{}.push_fx(L, fx, std::move(cont));
}
};
template<typename T>
- struct pusher<T*, std::enable_if_t<meta::all<meta::has_begin_end<meta::unqualified_t<T>>, meta::neg<meta::any<std::is_base_of<reference, meta::unqualified_t<T>>, std::is_base_of<stack_reference, meta::unqualified_t<T>>>>>::value>> {
- typedef container_usertype_metatable<T> cumt;
+ struct pusher<T*, std::enable_if_t<meta::all<is_container<T>, meta::neg<meta::any<std::is_base_of<reference, meta::unqualified_t<T>>, std::is_base_of<stack_reference, meta::unqualified_t<T>>>>>::value>> {
static int push(lua_State* L, T* cont) {
- auto fx = [&L]() {
- const char* metakey = &usertype_traits<meta::unqualified_t<T>*>::metatable[0];
- if (luaL_newmetatable(L, metakey) == 1) {
- luaL_Reg reg[] = {
- { "__index", &cumt::index_call },
- { "__newindex", &cumt::new_index_call },
- { "__pairs", &cumt::pairs_call },
- { "__len", &cumt::length_call },
- { nullptr, nullptr }
- };
- luaL_setfuncs(L, reg, 0);
- }
- lua_setmetatable(L, -2);
- };
+ stack_detail::metatable_setup<T*> fx(L);
return pusher<detail::as_pointer_tag<T>>{}.push_fx(L, fx, cont);
}
};
diff --git a/3rdparty/sol2/sol/error.hpp b/3rdparty/sol2/sol/error.hpp
index 0458e0a5f65..e24861effe9 100644
--- a/3rdparty/sol2/sol/error.hpp
+++ b/3rdparty/sol2/sol/error.hpp
@@ -37,6 +37,7 @@ namespace sol {
std::string w;
public:
error(const std::string& str) : error(detail::direct_error, "lua: error: " + str) {}
+ error(std::string&& str) : error(detail::direct_error, "lua: error: " + std::move(str)) {}
error(detail::direct_error_tag, const std::string& str) : std::runtime_error(""), w(str) {}
error(detail::direct_error_tag, std::string&& str) : std::runtime_error(""), w(std::move(str)) {}
diff --git a/3rdparty/sol2/sol/load_result.hpp b/3rdparty/sol2/sol/load_result.hpp
index 1a91cc6f3dc..0f465a2bc5a 100644
--- a/3rdparty/sol2/sol/load_result.hpp
+++ b/3rdparty/sol2/sol/load_result.hpp
@@ -119,7 +119,7 @@ namespace sol {
template<typename... Ret, typename... Args>
decltype(auto) call(Args&&... args) {
- return get<function>().template call<Ret...>(std::forward<Args>(args)...);
+ return get<protected_function>().template call<Ret...>(std::forward<Args>(args)...);
}
template<typename... Args>
diff --git a/3rdparty/sol2/sol/object.hpp b/3rdparty/sol2/sol/object.hpp
index 42b46f9c41e..87d8f229b5d 100644
--- a/3rdparty/sol2/sol/object.hpp
+++ b/3rdparty/sol2/sol/object.hpp
@@ -22,11 +22,11 @@
#ifndef SOL_OBJECT_HPP
#define SOL_OBJECT_HPP
-#include "optional.hpp"
#include "reference.hpp"
#include "stack.hpp"
#include "userdata.hpp"
#include "variadic_args.hpp"
+#include "optional.hpp"
namespace sol {
diff --git a/3rdparty/sol2/sol/optional.hpp b/3rdparty/sol2/sol/optional.hpp
index 823bdc3d5c3..16f805e4ebf 100644
--- a/3rdparty/sol2/sol/optional.hpp
+++ b/3rdparty/sol2/sol/optional.hpp
@@ -22,11 +22,12 @@
#ifndef SOL_OPTIONAL_HPP
#define SOL_OPTIONAL_HPP
+#include "compatibility.hpp"
#include "in_place.hpp"
#if defined(SOL_USE_BOOST)
#include <boost/optional.hpp>
#else
-#include "../Optional/optional.hpp"
+#include "optional_implementation.hpp"
#endif // Boost vs. Better optional
namespace sol {
diff --git a/3rdparty/sol2/sol/optional_implementation.hpp b/3rdparty/sol2/sol/optional_implementation.hpp
new file mode 100644
index 00000000000..374b80e7c36
--- /dev/null
+++ b/3rdparty/sol2/sol/optional_implementation.hpp
@@ -0,0 +1,1127 @@
+// The MIT License (MIT)
+
+// Copyright (c) 2013-2016 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.
+
+// Copyright (C) 2011 - 2012 Andrzej Krzemienski.
+// Use, modification, and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// The idea and interface is based on Boost.Optional library
+// authored by Fernando Luis Cacciola Carballal
+
+# ifndef SOL_OPTIONAL_IMPLEMENTATION_HPP
+# define SOL_OPTIONAL_IMPLEMENTATION_HPP
+
+# include <utility>
+# include <type_traits>
+# include <initializer_list>
+# include <cassert>
+# include <functional>
+# include <string>
+# include <stdexcept>
+#ifdef SOL_NO_EXCEPTIONS
+#include <cstdlib>
+#endif // Exceptions
+
+# define TR2_OPTIONAL_REQUIRES(...) typename ::std::enable_if<__VA_ARGS__::value, bool>::type = false
+
+# if defined __GNUC__ // NOTE: GNUC is also defined for Clang
+# if (__GNUC__ >= 5)
+# define TR2_OPTIONAL_GCC_5_0_AND_HIGHER___
+# define TR2_OPTIONAL_GCC_4_8_AND_HIGHER___
+# elif (__GNUC__ == 4) && (__GNUC_MINOR__ >= 8)
+# define TR2_OPTIONAL_GCC_4_8_AND_HIGHER___
+# elif (__GNUC__ > 4)
+# define TR2_OPTIONAL_GCC_4_8_AND_HIGHER___
+# endif
+#
+# if (__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)
+# define TR2_OPTIONAL_GCC_4_7_AND_HIGHER___
+# elif (__GNUC__ > 4)
+# define TR2_OPTIONAL_GCC_4_7_AND_HIGHER___
+# endif
+#
+# if (__GNUC__ == 4) && (__GNUC_MINOR__ == 8) && (__GNUC_PATCHLEVEL__ >= 1)
+# define TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___
+# elif (__GNUC__ == 4) && (__GNUC_MINOR__ >= 9)
+# define TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___
+# elif (__GNUC__ > 4)
+# define TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___
+# endif
+# endif
+#
+# if defined __clang_major__
+# if (__clang_major__ == 3 && __clang_minor__ >= 5)
+# define TR2_OPTIONAL_CLANG_3_5_AND_HIGHTER_
+# elif (__clang_major__ > 3)
+# define TR2_OPTIONAL_CLANG_3_5_AND_HIGHTER_
+# endif
+# if defined TR2_OPTIONAL_CLANG_3_5_AND_HIGHTER_
+# define TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_
+# elif (__clang_major__ == 3 && __clang_minor__ == 4 && __clang_patchlevel__ >= 2)
+# define TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_
+# endif
+# endif
+#
+# if defined _MSC_VER
+# if (_MSC_VER >= 1900)
+# define TR2_OPTIONAL_MSVC_2015_AND_HIGHER___
+# endif
+# endif
+
+# if defined __clang__
+# if (__clang_major__ > 2) || (__clang_major__ == 2) && (__clang_minor__ >= 9)
+# define OPTIONAL_HAS_THIS_RVALUE_REFS 1
+# else
+# define OPTIONAL_HAS_THIS_RVALUE_REFS 0
+# endif
+# elif defined TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___
+# define OPTIONAL_HAS_THIS_RVALUE_REFS 1
+# elif defined TR2_OPTIONAL_MSVC_2015_AND_HIGHER___
+# define OPTIONAL_HAS_THIS_RVALUE_REFS 1
+# else
+# define OPTIONAL_HAS_THIS_RVALUE_REFS 0
+# endif
+
+
+# if defined TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___
+# define OPTIONAL_HAS_CONSTEXPR_INIT_LIST 1
+# define OPTIONAL_CONSTEXPR_INIT_LIST constexpr
+# else
+# define OPTIONAL_HAS_CONSTEXPR_INIT_LIST 0
+# define OPTIONAL_CONSTEXPR_INIT_LIST
+# endif
+
+# if defined TR2_OPTIONAL_CLANG_3_5_AND_HIGHTER_ && (defined __cplusplus) && (__cplusplus != 201103L)
+# define OPTIONAL_HAS_MOVE_ACCESSORS 1
+# else
+# define OPTIONAL_HAS_MOVE_ACCESSORS 0
+# endif
+
+# // In C++11 constexpr implies const, so we need to make non-const members also non-constexpr
+# if (defined __cplusplus) && (__cplusplus == 201103L)
+# define OPTIONAL_MUTABLE_CONSTEXPR
+# else
+# define OPTIONAL_MUTABLE_CONSTEXPR constexpr
+# endif
+
+namespace sol {
+
+ // BEGIN workaround for missing is_trivially_destructible
+# if defined TR2_OPTIONAL_GCC_4_8_AND_HIGHER___
+ // leave it: it is already there
+# elif defined TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_
+ // leave it: it is already there
+# elif defined TR2_OPTIONAL_MSVC_2015_AND_HIGHER___
+ // leave it: it is already there
+# elif defined TR2_OPTIONAL_DISABLE_EMULATION_OF_TYPE_TRAITS
+ // leave it: the user doesn't want it
+# else
+ template <typename T>
+ using is_trivially_destructible = ::std::has_trivial_destructor<T>;
+# endif
+ // END workaround for missing is_trivially_destructible
+
+# if (defined TR2_OPTIONAL_GCC_4_7_AND_HIGHER___)
+ // leave it; our metafunctions are already defined.
+# elif defined TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_
+ // leave it; our metafunctions are already defined.
+# elif defined TR2_OPTIONAL_MSVC_2015_AND_HIGHER___
+ // leave it: it is already there
+# elif defined TR2_OPTIONAL_DISABLE_EMULATION_OF_TYPE_TRAITS
+ // leave it: the user doesn't want it
+# else
+
+
+// workaround for missing traits in GCC and CLANG
+ template <class T>
+ struct is_nothrow_move_constructible
+ {
+ constexpr static bool value = ::std::is_nothrow_constructible<T, T&&>::value;
+ };
+
+
+ template <class T, class U>
+ struct is_assignable
+ {
+ template <class X, class Y>
+ constexpr static bool has_assign(...) { return false; }
+
+ template <class X, class Y, size_t S = sizeof((::std::declval<X>() = ::std::declval<Y>(), true)) >
+ // the comma operator is necessary for the cases where operator= returns void
+ constexpr static bool has_assign(bool) { return true; }
+
+ constexpr static bool value = has_assign<T, U>(true);
+ };
+
+
+ template <class T>
+ struct is_nothrow_move_assignable
+ {
+ template <class X, bool has_any_move_assign>
+ struct has_nothrow_move_assign {
+ constexpr static bool value = false;
+ };
+
+ template <class X>
+ struct has_nothrow_move_assign<X, true> {
+ constexpr static bool value = noexcept(::std::declval<X&>() = ::std::declval<X&&>());
+ };
+
+ constexpr static bool value = has_nothrow_move_assign<T, is_assignable<T&, T&&>::value>::value;
+ };
+ // end workaround
+
+
+# endif
+
+
+
+// 20.5.4, optional for object types
+ template <class T> class optional;
+
+ // 20.5.5, optional for lvalue reference types
+ template <class T> class optional<T&>;
+
+
+ // workaround: std utility functions aren't constexpr yet
+ template <class T> inline constexpr T&& constexpr_forward(typename ::std::remove_reference<T>::type& t) noexcept
+ {
+ return static_cast<T&&>(t);
+ }
+
+ template <class T> inline constexpr T&& constexpr_forward(typename ::std::remove_reference<T>::type&& t) noexcept
+ {
+ static_assert(!::std::is_lvalue_reference<T>::value, "!!");
+ return static_cast<T&&>(t);
+ }
+
+ template <class T> inline constexpr typename ::std::remove_reference<T>::type&& constexpr_move(T&& t) noexcept
+ {
+ return static_cast<typename ::std::remove_reference<T>::type&&>(t);
+ }
+
+
+#if defined NDEBUG
+# define TR2_OPTIONAL_ASSERTED_EXPRESSION(CHECK, EXPR) (EXPR)
+#else
+# define TR2_OPTIONAL_ASSERTED_EXPRESSION(CHECK, EXPR) ((CHECK) ? (EXPR) : ([]{assert(!#CHECK);}(), (EXPR)))
+#endif
+
+
+ namespace detail_
+ {
+
+ // static_addressof: a constexpr version of addressof
+ template <typename T>
+ struct has_overloaded_addressof
+ {
+ template <class X>
+ constexpr static bool has_overload(...) { return false; }
+
+ template <class X, size_t S = sizeof(::std::declval<X&>().operator&()) >
+ constexpr static bool has_overload(bool) { return true; }
+
+ constexpr static bool value = has_overload<T>(true);
+ };
+
+ template <typename T, TR2_OPTIONAL_REQUIRES(!has_overloaded_addressof<T>)>
+ constexpr T* static_addressof(T& ref)
+ {
+ return &ref;
+ }
+
+ template <typename T, TR2_OPTIONAL_REQUIRES(has_overloaded_addressof<T>)>
+ T* static_addressof(T& ref)
+ {
+ return ::std::addressof(ref);
+ }
+
+
+ // the call to convert<A>(b) has return type A and converts b to type A iff b decltype(b) is implicitly convertible to A
+ template <class U>
+ constexpr U convert(U v) { return v; }
+
+ } // namespace detail_
+
+ constexpr struct trivial_init_t {} trivial_init{};
+
+ // 20.5.7, Disengaged state indicator
+ struct nullopt_t
+ {
+ struct init {};
+ constexpr explicit nullopt_t(init) {}
+ };
+ constexpr nullopt_t nullopt{ nullopt_t::init() };
+
+
+ // 20.5.8, class bad_optional_access
+ class bad_optional_access : public ::std::logic_error {
+ public:
+ explicit bad_optional_access(const ::std::string& what_arg) : ::std::logic_error{ what_arg } {}
+ explicit bad_optional_access(const char* what_arg) : ::std::logic_error{ what_arg } {}
+ };
+
+
+ template <class T>
+ struct optional_base
+ {
+ bool init_;
+ char storage_[sizeof(T)];
+
+ constexpr optional_base() noexcept : init_(false), storage_() {};
+
+ explicit optional_base(const T& v) : init_(true), storage_() {
+ new (&storage())T(v);
+ }
+
+ explicit optional_base(T&& v) : init_(true), storage_() {
+ new (&storage())T(constexpr_move(v));
+ }
+
+ template <class... Args> explicit optional_base(in_place_t, Args&&... args)
+ : init_(true), storage_() {
+ new (&storage())T(constexpr_forward<Args>(args)...);
+ }
+
+ template <class U, class... Args, TR2_OPTIONAL_REQUIRES(::std::is_constructible<T, ::std::initializer_list<U>>)>
+ explicit optional_base(in_place_t, ::std::initializer_list<U> il, Args&&... args)
+ : init_(true), storage_() {
+ new (&storage())T(il, constexpr_forward<Args>(args)...);
+ }
+#if defined __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wstrict-aliasing"
+#endif
+ T& storage() {
+ return *reinterpret_cast<T*>(&storage_[0]);
+ }
+
+ constexpr const T& storage() const {
+ return *reinterpret_cast<T const*>(&storage_[0]);
+ }
+#if defined __GNUC__
+#pragma GCC diagnostic pop
+#endif
+
+ ~optional_base() { if (init_) { storage().T::~T(); } }
+ };
+
+#if defined __GNUC__ && !defined TR2_OPTIONAL_GCC_5_0_AND_HIGHER___
+ // Sorry, GCC 4.x; you're just a piece of shit
+ template <typename T>
+ using constexpr_optional_base = optional_base<T>;
+#else
+ template <class T>
+ struct constexpr_optional_base
+ {
+ bool init_;
+ char storage_[sizeof(T)];
+ constexpr constexpr_optional_base() noexcept : init_(false), storage_() {}
+
+ explicit constexpr constexpr_optional_base(const T& v) : init_(true), storage_() {
+ new (&storage())T(v);
+ }
+
+ explicit constexpr constexpr_optional_base(T&& v) : init_(true), storage_() {
+ new (&storage())T(constexpr_move(v));
+ }
+
+ template <class... Args> explicit constexpr constexpr_optional_base(in_place_t, Args&&... args)
+ : init_(true), storage_() {
+ new (&storage())T(constexpr_forward<Args>(args)...);
+ }
+
+ template <class U, class... Args, TR2_OPTIONAL_REQUIRES(::std::is_constructible<T, ::std::initializer_list<U>>)>
+ OPTIONAL_CONSTEXPR_INIT_LIST explicit constexpr_optional_base(in_place_t, ::std::initializer_list<U> il, Args&&... args)
+ : init_(true), storage_() {
+ new (&storage())T(il, constexpr_forward<Args>(args)...);
+ }
+
+#if defined __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wstrict-aliasing"
+#endif
+ T& storage() {
+ return (*reinterpret_cast<T*>(&storage_[0]));
+ }
+
+ constexpr const T& storage() const {
+ return (*reinterpret_cast<T const*>(&storage_[0]));
+ }
+#if defined __GNUC__
+#pragma GCC diagnostic pop
+#endif
+
+ ~constexpr_optional_base() = default;
+ };
+#endif
+
+ template <class T>
+ using OptionalBase = typename ::std::conditional<
+ ::std::is_trivially_destructible<T>::value,
+ constexpr_optional_base<typename ::std::remove_const<T>::type>,
+ optional_base<typename ::std::remove_const<T>::type>
+ >::type;
+
+
+
+ template <class T>
+ class optional : private OptionalBase<T>
+ {
+ static_assert(!::std::is_same<typename ::std::decay<T>::type, nullopt_t>::value, "bad T");
+ static_assert(!::std::is_same<typename ::std::decay<T>::type, in_place_t>::value, "bad T");
+
+
+ constexpr bool initialized() const noexcept { return OptionalBase<T>::init_; }
+ typename ::std::remove_const<T>::type* dataptr() { return ::std::addressof(OptionalBase<T>::storage()); }
+ constexpr const T* dataptr() const { return detail_::static_addressof(OptionalBase<T>::storage()); }
+
+# if OPTIONAL_HAS_THIS_RVALUE_REFS == 1
+ constexpr const T& contained_val() const& { return OptionalBase<T>::storage(); }
+# if OPTIONAL_HAS_MOVE_ACCESSORS == 1
+ OPTIONAL_MUTABLE_CONSTEXPR T&& contained_val() && { return ::std::move(OptionalBase<T>::storage()); }
+ OPTIONAL_MUTABLE_CONSTEXPR T& contained_val() & { return OptionalBase<T>::storage(); }
+# else
+ T& contained_val() & { return OptionalBase<T>::storage(); }
+ T&& contained_val() && { return ::std::move(OptionalBase<T>::storage()); }
+# endif
+# else
+ constexpr const T& contained_val() const { return OptionalBase<T>::storage(); }
+ T& contained_val() { return OptionalBase<T>::storage(); }
+# endif
+
+ void clear() noexcept {
+ if (initialized()) dataptr()->T::~T();
+ OptionalBase<T>::init_ = false;
+ }
+
+ template <class... Args>
+ void initialize(Args&&... args) noexcept(noexcept(T(::std::forward<Args>(args)...)))
+ {
+ assert(!OptionalBase<T>::init_);
+ ::new (static_cast<void*>(dataptr())) T(::std::forward<Args>(args)...);
+ OptionalBase<T>::init_ = true;
+ }
+
+ template <class U, class... Args>
+ void initialize(::std::initializer_list<U> il, Args&&... args) noexcept(noexcept(T(il, ::std::forward<Args>(args)...)))
+ {
+ assert(!OptionalBase<T>::init_);
+ ::new (static_cast<void*>(dataptr())) T(il, ::std::forward<Args>(args)...);
+ OptionalBase<T>::init_ = true;
+ }
+
+ public:
+ typedef T value_type;
+
+ // 20.5.5.1, constructors
+ constexpr optional() noexcept : OptionalBase<T>() {};
+ constexpr optional(nullopt_t) noexcept : OptionalBase<T>() {};
+
+ optional(const optional& rhs)
+ : OptionalBase<T>()
+ {
+ if (rhs.initialized()) {
+ ::new (static_cast<void*>(dataptr())) T(*rhs);
+ OptionalBase<T>::init_ = true;
+ }
+ }
+
+ optional(const optional<T&>& rhs) : optional()
+ {
+ if (rhs) {
+ ::new (static_cast<void*>(dataptr())) T(*rhs);
+ OptionalBase<T>::init_ = true;
+ }
+ }
+
+
+ optional(optional&& rhs) noexcept(::std::is_nothrow_move_constructible<T>::value)
+ : OptionalBase<T>()
+ {
+ if (rhs.initialized()) {
+ ::new (static_cast<void*>(dataptr())) T(::std::move(*rhs));
+ OptionalBase<T>::init_ = true;
+ }
+ }
+
+ constexpr optional(const T& v) : OptionalBase<T>(v) {}
+
+ constexpr optional(T&& v) : OptionalBase<T>(constexpr_move(v)) {}
+
+ template <class... Args>
+ explicit constexpr optional(in_place_t, Args&&... args)
+ : OptionalBase<T>(in_place, constexpr_forward<Args>(args)...) {}
+
+ template <class U, class... Args, TR2_OPTIONAL_REQUIRES(::std::is_constructible<T, ::std::initializer_list<U>>)>
+ OPTIONAL_CONSTEXPR_INIT_LIST explicit optional(in_place_t, ::std::initializer_list<U> il, Args&&... args)
+ : OptionalBase<T>(in_place, il, constexpr_forward<Args>(args)...) {}
+
+ // 20.5.4.2, Destructor
+ ~optional() = default;
+
+ // 20.5.4.3, assignment
+ optional& operator=(nullopt_t) noexcept
+ {
+ clear();
+ return *this;
+ }
+
+ optional& operator=(const optional& rhs)
+ {
+ if (initialized() == true && rhs.initialized() == false) clear();
+ else if (initialized() == false && rhs.initialized() == true) initialize(*rhs);
+ else if (initialized() == true && rhs.initialized() == true) contained_val() = *rhs;
+ return *this;
+ }
+
+ optional& operator=(optional&& rhs)
+ noexcept(::std::is_nothrow_move_assignable<T>::value && ::std::is_nothrow_move_constructible<T>::value)
+ {
+ if (initialized() == true && rhs.initialized() == false) clear();
+ else if (initialized() == false && rhs.initialized() == true) initialize(::std::move(*rhs));
+ else if (initialized() == true && rhs.initialized() == true) contained_val() = ::std::move(*rhs);
+ return *this;
+ }
+
+ template <class U>
+ auto operator=(U&& v)
+ -> typename ::std::enable_if
+ <
+ ::std::is_same<typename ::std::decay<U>::type, T>::value,
+ optional&
+ >::type
+ {
+ if (initialized()) { contained_val() = ::std::forward<U>(v); }
+ else { initialize(::std::forward<U>(v)); }
+ return *this;
+ }
+
+
+ template <class... Args>
+ void emplace(Args&&... args)
+ {
+ clear();
+ initialize(::std::forward<Args>(args)...);
+ }
+
+ template <class U, class... Args>
+ void emplace(::std::initializer_list<U> il, Args&&... args)
+ {
+ clear();
+ initialize<U, Args...>(il, ::std::forward<Args>(args)...);
+ }
+
+ // 20.5.4.4, Swap
+ void swap(optional<T>& rhs) noexcept(::std::is_nothrow_move_constructible<T>::value && noexcept(swap(::std::declval<T&>(), ::std::declval<T&>())))
+ {
+ if (initialized() == true && rhs.initialized() == false) { rhs.initialize(::std::move(**this)); clear(); }
+ else if (initialized() == false && rhs.initialized() == true) { initialize(::std::move(*rhs)); rhs.clear(); }
+ else if (initialized() == true && rhs.initialized() == true) { using ::std::swap; swap(**this, *rhs); }
+ }
+
+ // 20.5.4.5, Observers
+
+ explicit constexpr operator bool() const noexcept { return initialized(); }
+
+ constexpr T const* operator ->() const {
+ return TR2_OPTIONAL_ASSERTED_EXPRESSION(initialized(), dataptr());
+ }
+
+# if OPTIONAL_HAS_MOVE_ACCESSORS == 1
+
+ OPTIONAL_MUTABLE_CONSTEXPR T* operator ->() {
+ assert(initialized());
+ return dataptr();
+ }
+
+ constexpr T const& operator *() const& {
+ return TR2_OPTIONAL_ASSERTED_EXPRESSION(initialized(), contained_val());
+ }
+
+ OPTIONAL_MUTABLE_CONSTEXPR T& operator *() & {
+ assert(initialized());
+ return contained_val();
+ }
+
+ OPTIONAL_MUTABLE_CONSTEXPR T&& operator *() && {
+ assert(initialized());
+ return constexpr_move(contained_val());
+ }
+
+ constexpr T const& value() const& {
+ return initialized() ?
+ contained_val()
+#ifdef SOL_NO_EXCEPTIONS
+ // we can't abort here
+ // because there's no constexpr abort
+ : *(T*)nullptr;
+#else
+ : (throw bad_optional_access("bad optional access"), contained_val());
+#endif
+ }
+
+ OPTIONAL_MUTABLE_CONSTEXPR T& value() & {
+ return initialized() ?
+ contained_val()
+#ifdef SOL_NO_EXCEPTIONS
+ : *(T*)nullptr;
+#else
+ : (throw bad_optional_access("bad optional access"), contained_val());
+#endif
+ }
+
+ OPTIONAL_MUTABLE_CONSTEXPR T&& value() && {
+ return initialized() ?
+ contained_val()
+#ifdef SOL_NO_EXCEPTIONS
+ // we can't abort here
+ // because there's no constexpr abort
+ : std::move(*(T*)nullptr);
+#else
+ : (throw bad_optional_access("bad optional access"), contained_val());
+#endif
+ }
+
+# else
+
+ T* operator ->() {
+ assert(initialized());
+ return dataptr();
+ }
+
+ constexpr T const& operator *() const {
+ return TR2_OPTIONAL_ASSERTED_EXPRESSION(initialized(), contained_val());
+ }
+
+ T& operator *() {
+ assert(initialized());
+ return contained_val();
+ }
+
+ constexpr T const& value() const {
+ return initialized() ?
+ contained_val()
+#ifdef SOL_NO_EXCEPTIONS
+ // we can't abort here
+ // because there's no constexpr abort
+ : *(T*)nullptr;
+#else
+ : (throw bad_optional_access("bad optional access"), contained_val());
+#endif
+ }
+
+ T& value() {
+ return initialized() ?
+ contained_val()
+#ifdef SOL_NO_EXCEPTIONS
+ // we can abort here
+ // but the others are constexpr, so we can't...
+ : (std::abort(), *(T*)nullptr)
+#else
+ : (throw bad_optional_access("bad optional access"), contained_val());
+#endif
+ }
+
+# endif
+
+# if OPTIONAL_HAS_THIS_RVALUE_REFS == 1
+
+ template <class V>
+ constexpr T value_or(V&& v) const&
+ {
+ return *this ? **this : detail_::convert<T>(constexpr_forward<V>(v));
+ }
+
+# if OPTIONAL_HAS_MOVE_ACCESSORS == 1
+
+ template <class V>
+ OPTIONAL_MUTABLE_CONSTEXPR T value_or(V&& v) &&
+ {
+ return *this ? constexpr_move(const_cast<optional<T>&>(*this).contained_val()) : detail_::convert<T>(constexpr_forward<V>(v));
+ }
+
+# else
+
+ template <class V>
+ T value_or(V&& v) &&
+ {
+ return *this ? constexpr_move(const_cast<optional<T>&>(*this).contained_val()) : detail_::convert<T>(constexpr_forward<V>(v));
+ }
+
+# endif
+
+# else
+
+ template <class V>
+ constexpr T value_or(V&& v) const
+ {
+ return *this ? **this : detail_::convert<T>(constexpr_forward<V>(v));
+ }
+
+# endif
+
+ };
+
+
+ template <class T>
+ class optional<T&>
+ {
+ static_assert(!::std::is_same<T, nullopt_t>::value, "bad T");
+ static_assert(!::std::is_same<T, in_place_t>::value, "bad T");
+ T* ref;
+
+ public:
+
+ // 20.5.5.1, construction/destruction
+ constexpr optional() noexcept : ref(nullptr) {}
+
+ constexpr optional(nullopt_t) noexcept : ref(nullptr) {}
+
+ constexpr optional(T& v) noexcept : ref(detail_::static_addressof(v)) {}
+
+ optional(T&&) = delete;
+
+ constexpr optional(const optional& rhs) noexcept : ref(rhs.ref) {}
+
+ explicit constexpr optional(in_place_t, T& v) noexcept : ref(detail_::static_addressof(v)) {}
+
+ explicit optional(in_place_t, T&&) = delete;
+
+ ~optional() = default;
+
+ // 20.5.5.2, mutation
+ optional& operator=(nullopt_t) noexcept {
+ ref = nullptr;
+ return *this;
+ }
+
+ // optional& operator=(const optional& rhs) noexcept {
+ // ref = rhs.ref;
+ // return *this;
+ // }
+
+ // optional& operator=(optional&& rhs) noexcept {
+ // ref = rhs.ref;
+ // return *this;
+ // }
+
+ template <typename U>
+ auto operator=(U&& rhs) noexcept
+ -> typename ::std::enable_if
+ <
+ ::std::is_same<typename ::std::decay<U>::type, optional<T&>>::value,
+ optional&
+ >::type
+ {
+ ref = rhs.ref;
+ return *this;
+ }
+
+ template <typename U>
+ auto operator=(U&& rhs) noexcept
+ -> typename ::std::enable_if
+ <
+ !::std::is_same<typename ::std::decay<U>::type, optional<T&>>::value,
+ optional&
+ >::type
+ = delete;
+
+ void emplace(T& v) noexcept {
+ ref = detail_::static_addressof(v);
+ }
+
+ void emplace(T&&) = delete;
+
+
+ void swap(optional<T&>& rhs) noexcept
+ {
+ ::std::swap(ref, rhs.ref);
+ }
+
+ // 20.5.5.3, observers
+ constexpr T* operator->() const {
+ return TR2_OPTIONAL_ASSERTED_EXPRESSION(ref, ref);
+ }
+
+ constexpr T& operator*() const {
+ return TR2_OPTIONAL_ASSERTED_EXPRESSION(ref, *ref);
+ }
+
+ constexpr T& value() const {
+ return ref ?
+ *ref
+#ifdef SOL_NO_EXCEPTIONS
+ // we can't abort here
+ // because there's no constexpr abort
+ : *(T*)nullptr;
+#else
+ : throw bad_optional_access("bad optional access");
+#endif
+ }
+
+ explicit constexpr operator bool() const noexcept {
+ return ref != nullptr;
+ }
+
+ template <typename V>
+ constexpr T& value_or(V&& v) const
+ {
+ return *this ? **this : detail_::convert<T&>(constexpr_forward<V>(v));
+ }
+ };
+
+
+ template <class T>
+ class optional<T&&>
+ {
+ static_assert(sizeof(T) == 0, "optional rvalue references disallowed");
+ };
+
+
+ // 20.5.8, Relational operators
+ template <class T> constexpr bool operator==(const optional<T>& x, const optional<T>& y)
+ {
+ return bool(x) != bool(y) ? false : bool(x) == false ? true : *x == *y;
+ }
+
+ template <class T> constexpr bool operator!=(const optional<T>& x, const optional<T>& y)
+ {
+ return !(x == y);
+ }
+
+ template <class T> constexpr bool operator<(const optional<T>& x, const optional<T>& y)
+ {
+ return (!y) ? false : (!x) ? true : *x < *y;
+ }
+
+ template <class T> constexpr bool operator>(const optional<T>& x, const optional<T>& y)
+ {
+ return (y < x);
+ }
+
+ template <class T> constexpr bool operator<=(const optional<T>& x, const optional<T>& y)
+ {
+ return !(y < x);
+ }
+
+ template <class T> constexpr bool operator>=(const optional<T>& x, const optional<T>& y)
+ {
+ return !(x < y);
+ }
+
+
+ // 20.5.9, Comparison with nullopt
+ template <class T> constexpr bool operator==(const optional<T>& x, nullopt_t) noexcept
+ {
+ return (!x);
+ }
+
+ template <class T> constexpr bool operator==(nullopt_t, const optional<T>& x) noexcept
+ {
+ return (!x);
+ }
+
+ template <class T> constexpr bool operator!=(const optional<T>& x, nullopt_t) noexcept
+ {
+ return bool(x);
+ }
+
+ template <class T> constexpr bool operator!=(nullopt_t, const optional<T>& x) noexcept
+ {
+ return bool(x);
+ }
+
+ template <class T> constexpr bool operator<(const optional<T>&, nullopt_t) noexcept
+ {
+ return false;
+ }
+
+ template <class T> constexpr bool operator<(nullopt_t, const optional<T>& x) noexcept
+ {
+ return bool(x);
+ }
+
+ template <class T> constexpr bool operator<=(const optional<T>& x, nullopt_t) noexcept
+ {
+ return (!x);
+ }
+
+ template <class T> constexpr bool operator<=(nullopt_t, const optional<T>&) noexcept
+ {
+ return true;
+ }
+
+ template <class T> constexpr bool operator>(const optional<T>& x, nullopt_t) noexcept
+ {
+ return bool(x);
+ }
+
+ template <class T> constexpr bool operator>(nullopt_t, const optional<T>&) noexcept
+ {
+ return false;
+ }
+
+ template <class T> constexpr bool operator>=(const optional<T>&, nullopt_t) noexcept
+ {
+ return true;
+ }
+
+ template <class T> constexpr bool operator>=(nullopt_t, const optional<T>& x) noexcept
+ {
+ return (!x);
+ }
+
+
+
+ // 20.5.10, Comparison with T
+ template <class T> constexpr bool operator==(const optional<T>& x, const T& v)
+ {
+ return bool(x) ? *x == v : false;
+ }
+
+ template <class T> constexpr bool operator==(const T& v, const optional<T>& x)
+ {
+ return bool(x) ? v == *x : false;
+ }
+
+ template <class T> constexpr bool operator!=(const optional<T>& x, const T& v)
+ {
+ return bool(x) ? *x != v : true;
+ }
+
+ template <class T> constexpr bool operator!=(const T& v, const optional<T>& x)
+ {
+ return bool(x) ? v != *x : true;
+ }
+
+ template <class T> constexpr bool operator<(const optional<T>& x, const T& v)
+ {
+ return bool(x) ? *x < v : true;
+ }
+
+ template <class T> constexpr bool operator>(const T& v, const optional<T>& x)
+ {
+ return bool(x) ? v > *x : true;
+ }
+
+ template <class T> constexpr bool operator>(const optional<T>& x, const T& v)
+ {
+ return bool(x) ? *x > v : false;
+ }
+
+ template <class T> constexpr bool operator<(const T& v, const optional<T>& x)
+ {
+ return bool(x) ? v < *x : false;
+ }
+
+ template <class T> constexpr bool operator>=(const optional<T>& x, const T& v)
+ {
+ return bool(x) ? *x >= v : false;
+ }
+
+ template <class T> constexpr bool operator<=(const T& v, const optional<T>& x)
+ {
+ return bool(x) ? v <= *x : false;
+ }
+
+ template <class T> constexpr bool operator<=(const optional<T>& x, const T& v)
+ {
+ return bool(x) ? *x <= v : true;
+ }
+
+ template <class T> constexpr bool operator>=(const T& v, const optional<T>& x)
+ {
+ return bool(x) ? v >= *x : true;
+ }
+
+
+ // Comparison of optional<T&> with T
+ template <class T> constexpr bool operator==(const optional<T&>& x, const T& v)
+ {
+ return bool(x) ? *x == v : false;
+ }
+
+ template <class T> constexpr bool operator==(const T& v, const optional<T&>& x)
+ {
+ return bool(x) ? v == *x : false;
+ }
+
+ template <class T> constexpr bool operator!=(const optional<T&>& x, const T& v)
+ {
+ return bool(x) ? *x != v : true;
+ }
+
+ template <class T> constexpr bool operator!=(const T& v, const optional<T&>& x)
+ {
+ return bool(x) ? v != *x : true;
+ }
+
+ template <class T> constexpr bool operator<(const optional<T&>& x, const T& v)
+ {
+ return bool(x) ? *x < v : true;
+ }
+
+ template <class T> constexpr bool operator>(const T& v, const optional<T&>& x)
+ {
+ return bool(x) ? v > *x : true;
+ }
+
+ template <class T> constexpr bool operator>(const optional<T&>& x, const T& v)
+ {
+ return bool(x) ? *x > v : false;
+ }
+
+ template <class T> constexpr bool operator<(const T& v, const optional<T&>& x)
+ {
+ return bool(x) ? v < *x : false;
+ }
+
+ template <class T> constexpr bool operator>=(const optional<T&>& x, const T& v)
+ {
+ return bool(x) ? *x >= v : false;
+ }
+
+ template <class T> constexpr bool operator<=(const T& v, const optional<T&>& x)
+ {
+ return bool(x) ? v <= *x : false;
+ }
+
+ template <class T> constexpr bool operator<=(const optional<T&>& x, const T& v)
+ {
+ return bool(x) ? *x <= v : true;
+ }
+
+ template <class T> constexpr bool operator>=(const T& v, const optional<T&>& x)
+ {
+ return bool(x) ? v >= *x : true;
+ }
+
+ // Comparison of optional<T const&> with T
+ template <class T> constexpr bool operator==(const optional<const T&>& x, const T& v)
+ {
+ return bool(x) ? *x == v : false;
+ }
+
+ template <class T> constexpr bool operator==(const T& v, const optional<const T&>& x)
+ {
+ return bool(x) ? v == *x : false;
+ }
+
+ template <class T> constexpr bool operator!=(const optional<const T&>& x, const T& v)
+ {
+ return bool(x) ? *x != v : true;
+ }
+
+ template <class T> constexpr bool operator!=(const T& v, const optional<const T&>& x)
+ {
+ return bool(x) ? v != *x : true;
+ }
+
+ template <class T> constexpr bool operator<(const optional<const T&>& x, const T& v)
+ {
+ return bool(x) ? *x < v : true;
+ }
+
+ template <class T> constexpr bool operator>(const T& v, const optional<const T&>& x)
+ {
+ return bool(x) ? v > *x : true;
+ }
+
+ template <class T> constexpr bool operator>(const optional<const T&>& x, const T& v)
+ {
+ return bool(x) ? *x > v : false;
+ }
+
+ template <class T> constexpr bool operator<(const T& v, const optional<const T&>& x)
+ {
+ return bool(x) ? v < *x : false;
+ }
+
+ template <class T> constexpr bool operator>=(const optional<const T&>& x, const T& v)
+ {
+ return bool(x) ? *x >= v : false;
+ }
+
+ template <class T> constexpr bool operator<=(const T& v, const optional<const T&>& x)
+ {
+ return bool(x) ? v <= *x : false;
+ }
+
+ template <class T> constexpr bool operator<=(const optional<const T&>& x, const T& v)
+ {
+ return bool(x) ? *x <= v : true;
+ }
+
+ template <class T> constexpr bool operator>=(const T& v, const optional<const T&>& x)
+ {
+ return bool(x) ? v >= *x : true;
+ }
+
+
+ // 20.5.12, Specialized algorithms
+ template <class T>
+ void swap(optional<T>& x, optional<T>& y) noexcept(noexcept(x.swap(y))) {
+ x.swap(y);
+ }
+
+
+ template <class T>
+ constexpr optional<typename ::std::decay<T>::type> make_optional(T&& v) {
+ return optional<typename ::std::decay<T>::type>(constexpr_forward<T>(v));
+ }
+
+ template <class X>
+ constexpr optional<X&> make_optional(::std::reference_wrapper<X> v) {
+ return optional<X&>(v.get());
+ }
+
+
+} // namespace
+
+namespace std
+{
+ template <typename T>
+ struct hash<sol::optional<T>> {
+ typedef typename hash<T>::result_type result_type;
+ typedef sol::optional<T> argument_type;
+
+ constexpr result_type operator()(argument_type const& arg) const {
+ return arg ? ::std::hash<T>{}(*arg) : result_type{};
+ }
+ };
+
+ template <typename T>
+ struct hash<sol::optional<T&>> {
+ typedef typename hash<T>::result_type result_type;
+ typedef sol::optional<T&> argument_type;
+
+ constexpr result_type operator()(argument_type const& arg) const {
+ return arg ? ::std::hash<T>{}(*arg) : result_type{};
+ }
+ };
+}
+
+# undef TR2_OPTIONAL_REQUIRES
+# undef TR2_OPTIONAL_ASSERTED_EXPRESSION
+
+# endif // SOL_OPTIONAL_IMPLEMENTATION_HPP
diff --git a/3rdparty/sol2/sol/proxy.hpp b/3rdparty/sol2/sol/proxy.hpp
index 22247a8d818..20bb0666598 100644
--- a/3rdparty/sol2/sol/proxy.hpp
+++ b/3rdparty/sol2/sol/proxy.hpp
@@ -123,22 +123,26 @@ namespace sol {
template<typename Table, typename Key, typename T>
inline bool operator==(T&& left, const proxy<Table, Key>& right) {
- return left == right.template get<std::decay_t<T>>();
+ typedef decltype(stack::get<T>(nullptr, 0)) U;
+ return right.template get<optional<U>>() == left;
}
template<typename Table, typename Key, typename T>
inline bool operator==(const proxy<Table, Key>& right, T&& left) {
- return right.template get<std::decay_t<T>>() == left;
+ typedef decltype(stack::get<T>(nullptr, 0)) U;
+ return right.template get<optional<U>>() == left;
}
template<typename Table, typename Key, typename T>
inline bool operator!=(T&& left, const proxy<Table, Key>& right) {
- return right.template get<std::decay_t<T>>() != left;
+ typedef decltype(stack::get<T>(nullptr, 0)) U;
+ return right.template get<optional<U>>() == left;
}
template<typename Table, typename Key, typename T>
inline bool operator!=(const proxy<Table, Key>& right, T&& left) {
- return right.template get<std::decay_t<T>>() != left;
+ typedef decltype(stack::get<T>(nullptr, 0)) U;
+ return right.template get<optional<U>>() == left;
}
template<typename Table, typename Key>
diff --git a/3rdparty/sol2/sol/simple_usertype_metatable.hpp b/3rdparty/sol2/sol/simple_usertype_metatable.hpp
index 586e0d18527..482ad8037dc 100644
--- a/3rdparty/sol2/sol/simple_usertype_metatable.hpp
+++ b/3rdparty/sol2/sol/simple_usertype_metatable.hpp
@@ -31,6 +31,8 @@
namespace sol {
namespace usertype_detail {
+ const lua_Integer toplevel_magic = static_cast<lua_Integer>(0x00000001);
+
struct variable_wrapper {
virtual int index(lua_State* L) = 0;
virtual int new_index(lua_State* L) = 0;
@@ -68,8 +70,31 @@ namespace sol {
template <typename T>
inline int simple_metatable_newindex(lua_State* L) {
- if (stack::stack_detail::check_metatable<T, false>(L, 1)) {
- stack::set_field<false, true>(L, stack_reference(L, 2), stack_reference(L, 3), 1);
+ int isnum = 0;
+ lua_Integer magic = lua_tointegerx(L, lua_upvalueindex(4), &isnum);
+ if (isnum != 0 && magic == toplevel_magic) {
+ for (std::size_t i = 0; i < 3; lua_pop(L, 1), ++i) {
+ // Pointer types, AKA "references" from C++
+ const char* metakey = nullptr;
+ switch (i) {
+ case 0:
+ metakey = &usertype_traits<T*>::metatable()[0];
+ break;
+ case 1:
+ metakey = &usertype_traits<detail::unique_usertype<T>>::metatable()[0];
+ break;
+ case 2:
+ default:
+ metakey = &usertype_traits<T>::metatable()[0];
+ break;
+ }
+ luaL_getmetatable(L, metakey);
+ int tableindex = lua_gettop(L);
+ if (type_of(L, tableindex) == type::nil) {
+ continue;
+ }
+ stack::set_field<false, true>(L, stack_reference(L, 2), stack_reference(L, 3), tableindex);
+ }
lua_settop(L, 0);
return 0;
}
@@ -259,15 +284,15 @@ namespace sol {
template <typename... Bases>
void add(lua_State*, base_classes_tag, bases<Bases...>) {
- static_assert(sizeof(usertype_detail::base_walk) <= sizeof(void*), "size of function pointer is greater than sizeof(void*); cannot work on this platform");
+ static_assert(sizeof(usertype_detail::base_walk) <= sizeof(void*), "size of function pointer is greater than sizeof(void*); cannot work on this platform. Please file a bug report.");
if (sizeof...(Bases) < 1) {
return;
}
mustindex = true;
(void)detail::swallow{ 0, ((detail::has_derived<Bases>::value = true), 0)... };
- static_assert(sizeof(void*) <= sizeof(detail::inheritance_check_function), "The size of this data pointer is too small to fit the inheritance checking function: file a bug report.");
- static_assert(sizeof(void*) <= sizeof(detail::inheritance_cast_function), "The size of this data pointer is too small to fit the inheritance checking function: file a bug report.");
+ static_assert(sizeof(void*) <= sizeof(detail::inheritance_check_function), "The size of this data pointer is too small to fit the inheritance checking function: Please file a bug report.");
+ static_assert(sizeof(void*) <= sizeof(detail::inheritance_cast_function), "The size of this data pointer is too small to fit the inheritance checking function: Please file a bug report.");
baseclasscheck = (void*)&detail::inheritance<T, Bases...>::type_check;
baseclasscast = (void*)&detail::inheritance<T, Bases...>::type_cast;
indexbaseclasspropogation = usertype_detail::walk_all_bases<true, Bases...>;
@@ -278,11 +303,11 @@ namespace sol {
template<std::size_t... I, typename Tuple>
simple_usertype_metatable(usertype_detail::verified_tag, std::index_sequence<I...>, lua_State* L, Tuple&& args)
: callconstructfunc(nil),
- indexfunc(&usertype_detail::indexing_fail<true>), newindexfunc(&usertype_detail::simple_metatable_newindex<T>),
+ indexfunc(&usertype_detail::indexing_fail<true>), newindexfunc(&usertype_detail::indexing_fail<false>),
indexbase(&usertype_detail::simple_core_indexing_call<true>), newindexbase(&usertype_detail::simple_core_indexing_call<false>),
indexbaseclasspropogation(usertype_detail::walk_all_bases<true>), newindexbaseclasspropogation(&usertype_detail::walk_all_bases<false>),
baseclasscheck(nullptr), baseclasscast(nullptr),
- mustindex(true), secondarymeta(true) {
+ mustindex(false), secondarymeta(false) {
(void)detail::swallow{ 0,
(add(L, detail::forward_get<I * 2>(args), detail::forward_get<I * 2 + 1>(args)),0)...
};
@@ -329,7 +354,7 @@ namespace sol {
static usertype_detail::simple_map& make_cleanup(lua_State* L, umt_t& umx) {
static int uniqueness = 0;
- std::string uniquegcmetakey = usertype_traits<T>::user_gc_metatable;
+ std::string uniquegcmetakey = usertype_traits<T>::user_gc_metatable();
// std::to_string doesn't exist in android still, with NDK, so this bullshit
// is necessary
// thanks, Android :v
@@ -340,8 +365,11 @@ namespace sol {
snprintf(uniquetarget, uniquegcmetakey.length(), "%d", uniqueness);
++uniqueness;
- const char* gcmetakey = &usertype_traits<T>::gc_table[0];
- stack::push<user<usertype_detail::simple_map>>(L, metatable_key, uniquegcmetakey, &usertype_traits<T>::metatable[0], umx.indexbaseclasspropogation, umx.newindexbaseclasspropogation, std::move(umx.varmap), std::move(umx.registrations));
+ const char* gcmetakey = &usertype_traits<T>::gc_table()[0];
+ stack::push<user<usertype_detail::simple_map>>(L, metatable_key, uniquegcmetakey, &usertype_traits<T>::metatable()[0],
+ umx.indexbaseclasspropogation, umx.newindexbaseclasspropogation,
+ std::move(umx.varmap), std::move(umx.registrations)
+ );
stack_reference stackvarmap(L, -1);
stack::set_field<true>(L, gcmetakey, stackvarmap);
stackvarmap.pop();
@@ -356,19 +384,53 @@ namespace sol {
bool hasequals = false;
bool hasless = false;
bool haslessequals = false;
+ auto register_kvp = [&](std::size_t i, stack_reference& t, const std::string& first, object& second) {
+ if (first == name_of(meta_function::equal_to)) {
+ hasequals = true;
+ }
+ else if (first == name_of(meta_function::less_than)) {
+ hasless = true;
+ }
+ else if (first == name_of(meta_function::less_than_or_equal_to)) {
+ haslessequals = true;
+ }
+ else if (first == name_of(meta_function::index)) {
+ umx.indexfunc = second.template as<lua_CFunction>();
+ }
+ else if (first == name_of(meta_function::new_index)) {
+ umx.newindexfunc = second.template as<lua_CFunction>();
+ }
+ switch (i) {
+ case 0:
+ if (first == name_of(meta_function::garbage_collect)) {
+ return;
+ }
+ break;
+ case 1:
+ if (first == name_of(meta_function::garbage_collect)) {
+ stack::set_field(L, first, detail::unique_destruct<T>, t.stack_index());
+ return;
+ }
+ break;
+ case 2:
+ default:
+ break;
+ }
+ stack::set_field(L, first, second, t.stack_index());
+ };
for (std::size_t i = 0; i < 3; ++i) {
// Pointer types, AKA "references" from C++
const char* metakey = nullptr;
switch (i) {
case 0:
- metakey = &usertype_traits<T*>::metatable[0];
+ metakey = &usertype_traits<T*>::metatable()[0];
break;
case 1:
- metakey = &usertype_traits<detail::unique_usertype<T>>::metatable[0];
+ metakey = &usertype_traits<detail::unique_usertype<T>>::metatable()[0];
break;
case 2:
default:
- metakey = &usertype_traits<T>::metatable[0];
+ metakey = &usertype_traits<T>::metatable()[0];
break;
}
luaL_newmetatable(L, metakey);
@@ -376,38 +438,7 @@ namespace sol {
for (auto& kvp : varmap.functions) {
auto& first = std::get<0>(kvp);
auto& second = std::get<1>(kvp);
- if (first == name_of(meta_function::equal_to)) {
- hasequals = true;
- }
- else if (first == name_of(meta_function::less_than)) {
- hasless = true;
- }
- else if (first == name_of(meta_function::less_than_or_equal_to)) {
- haslessequals = true;
- }
- else if (first == name_of(meta_function::index)) {
- umx.indexfunc = second.template as<lua_CFunction>();
- }
- else if (first == name_of(meta_function::new_index)) {
- umx.newindexfunc = second.template as<lua_CFunction>();
- }
- switch (i) {
- case 0:
- if (first == name_of(meta_function::garbage_collect)) {
- continue;
- }
- break;
- case 1:
- if (first == name_of(meta_function::garbage_collect)) {
- stack::set_field(L, first, detail::unique_destruct<T>, t.stack_index());
- continue;
- }
- break;
- case 2:
- default:
- break;
- }
- stack::set_field(L, first, second, t.stack_index());
+ register_kvp(i, t, first, second);
}
luaL_Reg opregs[4]{};
int opregsindex = 0;
@@ -440,7 +471,6 @@ namespace sol {
if (umx.mustindex) {
// use indexing function
- static_assert(sizeof(usertype_detail::base_walk) <= sizeof(void*), "The size of this data pointer is too small to fit the base class index propagation key: file a bug report.");
stack::set_field(L, meta_function::index,
make_closure(&usertype_detail::simple_index_call,
make_light(varmap),
@@ -460,7 +490,7 @@ namespace sol {
}
// metatable on the metatable
// for call constructor purposes and such
- lua_createtable(L, 0, 1);
+ lua_createtable(L, 0, 2 * static_cast<int>(umx.secondarymeta) + static_cast<int>(umx.callconstructfunc.valid()));
stack_reference metabehind(L, -1);
if (umx.callconstructfunc.valid()) {
stack::set_field(L, sol::meta_function::call_function, umx.callconstructfunc, metabehind.stack_index());
@@ -482,9 +512,44 @@ namespace sol {
stack::set_field(L, metatable_key, metabehind, t.stack_index());
metabehind.pop();
- if (i < 2)
- t.pop();
+ t.pop();
+ }
+
+ // Now for the shim-table that actually gets pushed
+ luaL_newmetatable(L, &usertype_traits<T>::user_metatable()[0]);
+ stack_reference t(L, -1);
+ for (auto& kvp : varmap.functions) {
+ auto& first = std::get<0>(kvp);
+ auto& second = std::get<1>(kvp);
+ register_kvp(2, t, first, second);
}
+ {
+ lua_createtable(L, 0, 2 + static_cast<int>(umx.callconstructfunc.valid()));
+ stack_reference metabehind(L, -1);
+ if (umx.callconstructfunc.valid()) {
+ stack::set_field(L, sol::meta_function::call_function, umx.callconstructfunc, metabehind.stack_index());
+ }
+ // use indexing function
+ stack::set_field(L, meta_function::index,
+ make_closure(&usertype_detail::simple_index_call,
+ make_light(varmap),
+ &usertype_detail::simple_index_call,
+ &usertype_detail::simple_metatable_newindex<T>,
+ usertype_detail::toplevel_magic
+ ), metabehind.stack_index());
+ stack::set_field(L, meta_function::new_index,
+ make_closure(&usertype_detail::simple_new_index_call,
+ make_light(varmap),
+ &usertype_detail::simple_index_call,
+ &usertype_detail::simple_metatable_newindex<T>,
+ usertype_detail::toplevel_magic
+ ), metabehind.stack_index());
+ stack::set_field(L, metatable_key, metabehind, t.stack_index());
+ metabehind.pop();
+ }
+
+ // Don't pop the table when we're done;
+ // return it
return 1;
}
};
diff --git a/3rdparty/sol2/sol/stack_check.hpp b/3rdparty/sol2/sol/stack_check.hpp
index bf9faa1ed52..5a8610f270a 100644
--- a/3rdparty/sol2/sol/stack_check.hpp
+++ b/3rdparty/sol2/sol/stack_check.hpp
@@ -34,7 +34,7 @@ namespace sol {
namespace stack_detail {
template <typename T, bool poptable = true>
inline bool check_metatable(lua_State* L, int index = -2) {
- const auto& metakey = usertype_traits<T>::metatable;
+ const auto& metakey = usertype_traits<T>::metatable();
luaL_getmetatable(L, &metakey[0]);
const type expectedmetatabletype = static_cast<type>(lua_type(L, -1));
if (expectedmetatabletype != type::nil) {
@@ -77,6 +77,34 @@ namespace sol {
}
};
+ template<typename T>
+ struct checker<T, type::number, std::enable_if_t<std::is_integral<T>::value>> {
+ template <typename Handler>
+ static bool check(lua_State* L, int index, Handler&& handler, record& tracking) {
+ tracking.use(1);
+ bool success = lua_isinteger(L, index) == 1;
+ if (!success) {
+ // expected type, actual type
+ handler(L, index, type::number, type_of(L, index));
+ }
+ return success;
+ }
+ };
+
+ template<typename T>
+ struct checker<T, type::number, std::enable_if_t<std::is_floating_point<T>::value>> {
+ template <typename Handler>
+ static bool check(lua_State* L, int index, Handler&& handler, record& tracking) {
+ tracking.use(1);
+ bool success = lua_isnumber(L, index) == 1;
+ if (!success) {
+ // expected type, actual type
+ handler(L, index, type::number, type_of(L, index));
+ }
+ return success;
+ }
+ };
+
template <type expected, typename C>
struct checker<nil_t, expected, C> {
template <typename Handler>
@@ -239,21 +267,7 @@ namespace sol {
};
template <typename T, typename C>
- struct checker<T*, type::userdata, C> {
- template <typename Handler>
- static bool check(lua_State* L, int index, Handler&& handler, record& tracking) {
- const type indextype = type_of(L, index);
- // Allow nil to be transformed to nullptr
- if (indextype == type::nil) {
- tracking.use(1);
- return true;
- }
- return checker<meta::unqualified_t<T>, type::userdata, C>{}.check(types<meta::unqualified_t<T>>(), L, indextype, index, std::forward<Handler>(handler), tracking);
- }
- };
-
- template <typename T, typename C>
- struct checker<T, type::userdata, C> {
+ struct checker<detail::as_value_tag<T>, type::userdata, C> {
template <typename U, typename Handler>
static bool check(types<U>, lua_State* L, type indextype, int index, Handler&& handler, record& tracking) {
tracking.use(1);
@@ -292,11 +306,28 @@ namespace sol {
lua_pop(L, 1);
return true;
}
+ };
+
+ template <typename T, typename C>
+ struct checker<T, type::userdata, C> {
+ template <typename Handler>
+ static bool check(lua_State* L, int index, Handler&& handler, record& tracking) {
+ const type indextype = type_of(L, index);
+ return checker<detail::as_value_tag<T>, type::userdata, C>{}.check(types<T>(), L, indextype, index, std::forward<Handler>(handler), tracking);
+ }
+ };
+ template <typename T, typename C>
+ struct checker<T*, type::userdata, C> {
template <typename Handler>
static bool check(lua_State* L, int index, Handler&& handler, record& tracking) {
const type indextype = type_of(L, index);
- return check(types<T>(), L, indextype, index, std::forward<Handler>(handler), tracking);
+ // Allow nil to be transformed to nullptr
+ if (indextype == type::nil) {
+ tracking.use(1);
+ return true;
+ }
+ return checker<meta::unqualified_t<T>, type::userdata, C>{}.check(L, index, std::forward<Handler>(handler), tracking);
}
};
diff --git a/3rdparty/sol2/sol/stack_get.hpp b/3rdparty/sol2/sol/stack_get.hpp
index 52c52efa10e..7cb7f2b82c9 100644
--- a/3rdparty/sol2/sol/stack_get.hpp
+++ b/3rdparty/sol2/sol/stack_get.hpp
@@ -41,7 +41,7 @@ namespace sol {
template<typename T, typename>
struct getter {
static T& get(lua_State* L, int index, record& tracking) {
- return getter<T&>{}.get(L, index, tracking);
+ return getter<sol::detail::as_value_tag<T>>{}.get(L, index, tracking);
}
};
@@ -437,7 +437,7 @@ namespace sol {
};
template<typename T>
- struct getter<T*> {
+ struct getter<detail::as_value_tag<T>> {
static T* get_no_nil(lua_State* L, int index, record& tracking) {
tracking.use(1);
void** pudata = static_cast<void**>(lua_touserdata(L, index));
@@ -456,28 +456,49 @@ namespace sol {
T* obj = static_cast<T*>(udata);
return obj;
}
+
+ static T& get(lua_State* L, int index, record& tracking) {
+ return *get_no_nil(L, index, tracking);
+ }
+ };
+ template<typename T>
+ struct getter<detail::as_pointer_tag<T>> {
static T* get(lua_State* L, int index, record& tracking) {
type t = type_of(L, index);
if (t == type::nil) {
tracking.use(1);
return nullptr;
}
- return get_no_nil(L, index, tracking);
+ return getter<detail::as_value_tag<T>>::get_no_nil(L, index, tracking);
}
};
template<typename T>
struct getter<non_null<T*>> {
static T* get(lua_State* L, int index, record& tracking) {
- return getter<T*>::get_no_nil(L, index, tracking);
+ return getter<detail::as_value_tag<T>>::get_no_nil(L, index, tracking);
}
};
template<typename T>
struct getter<T&> {
static T& get(lua_State* L, int index, record& tracking) {
- return *getter<T*>::get_no_nil(L, index, tracking);
+ return getter<detail::as_value_tag<T>>::get(L, index, tracking);
+ }
+ };
+
+ template<typename T>
+ struct getter<std::reference_wrapper<T>> {
+ static T& get(lua_State* L, int index, record& tracking) {
+ return getter<T&>{}.get(L, index, tracking);
+ }
+ };
+
+ template<typename T>
+ struct getter<T*> {
+ static T* get(lua_State* L, int index, record& tracking) {
+ return getter<detail::as_pointer_tag<T>>::get(L, index, tracking);
}
};
@@ -495,13 +516,6 @@ namespace sol {
}
};
- template<typename T>
- struct getter<std::reference_wrapper<T>> {
- static T& get(lua_State* L, int index, record& tracking) {
- return getter<T&>{}.get(L, index, tracking);
- }
- };
-
template<typename... Args>
struct getter<std::tuple<Args...>> {
typedef std::tuple<decltype(stack::get<Args>(nullptr, 0))...> R;
diff --git a/3rdparty/sol2/sol/stack_push.hpp b/3rdparty/sol2/sol/stack_push.hpp
index 27d28fc081e..cf39d1e40c8 100644
--- a/3rdparty/sol2/sol/stack_push.hpp
+++ b/3rdparty/sol2/sol/stack_push.hpp
@@ -62,7 +62,7 @@ namespace sol {
template <typename... Args>
static int push(lua_State* L, Args&&... args) {
- return push_keyed(L, usertype_traits<T>::metatable, std::forward<Args>(args)...);
+ return push_keyed(L, usertype_traits<T>::metatable(), std::forward<Args>(args)...);
}
};
@@ -87,7 +87,7 @@ namespace sol {
}
static int push(lua_State* L, T* obj) {
- return push_keyed(L, usertype_traits<meta::unqualified_t<T>*>::metatable, obj);
+ return push_keyed(L, usertype_traits<meta::unqualified_t<T>*>::metatable(), obj);
}
};
@@ -140,7 +140,7 @@ namespace sol {
*fx = detail::special_destruct<P, Real>;
detail::default_construct::construct(mem, std::forward<Args>(args)...);
*pref = unique_usertype_traits<T>::get(*mem);
- if (luaL_newmetatable(L, &usertype_traits<detail::unique_usertype<P>>::metatable[0]) == 1) {
+ if (luaL_newmetatable(L, &usertype_traits<detail::unique_usertype<P>>::metatable()[0]) == 1) {
set_field(L, "__gc", detail::unique_destruct<P>);
}
lua_setmetatable(L, -2);
@@ -362,13 +362,13 @@ namespace sol {
template <typename Arg, typename... Args, meta::disable<meta::any_same<meta::unqualified_t<Arg>, no_metatable_t, metatable_key_t>> = meta::enabler>
static int push(lua_State* L, Arg&& arg, Args&&... args) {
- const auto name = &usertype_traits<meta::unqualified_t<T>>::user_gc_metatable[0];
+ const auto name = &usertype_traits<meta::unqualified_t<T>>::user_gc_metatable()[0];
return push_with(L, name, std::forward<Arg>(arg), std::forward<Args>(args)...);
}
template <typename... Args>
static int push(lua_State* L, no_metatable_t, Args&&... args) {
- const auto name = &usertype_traits<meta::unqualified_t<T>>::user_gc_metatable[0];
+ const auto name = &usertype_traits<meta::unqualified_t<T>>::user_gc_metatable()[0];
return push_with<false>(L, name, std::forward<Args>(args)...);
}
@@ -379,22 +379,22 @@ namespace sol {
}
static int push(lua_State* L, const user<T>& u) {
- const auto name = &usertype_traits<meta::unqualified_t<T>>::user_gc_metatable[0];
+ const auto name = &usertype_traits<meta::unqualified_t<T>>::user_gc_metatable()[0];
return push_with(L, name, u.value);
}
static int push(lua_State* L, user<T>&& u) {
- const auto name = &usertype_traits<meta::unqualified_t<T>>::user_gc_metatable[0];
+ const auto name = &usertype_traits<meta::unqualified_t<T>>::user_gc_metatable()[0];
return push_with(L, name, std::move(u.value));
}
static int push(lua_State* L, no_metatable_t, const user<T>& u) {
- const auto name = &usertype_traits<meta::unqualified_t<T>>::user_gc_metatable[0];
+ const auto name = &usertype_traits<meta::unqualified_t<T>>::user_gc_metatable()[0];
return push_with<false>(L, name, u.value);
}
static int push(lua_State* L, no_metatable_t, user<T>&& u) {
- const auto name = &usertype_traits<meta::unqualified_t<T>>::user_gc_metatable[0];
+ const auto name = &usertype_traits<meta::unqualified_t<T>>::user_gc_metatable()[0];
return push_with<false>(L, name, std::move(u.value));
}
};
diff --git a/3rdparty/sol2/sol/state.hpp b/3rdparty/sol2/sol/state.hpp
index 18c32db5010..b2b03622748 100644
--- a/3rdparty/sol2/sol/state.hpp
+++ b/3rdparty/sol2/sol/state.hpp
@@ -31,8 +31,12 @@ namespace sol {
return -1;
#else
const char* message = lua_tostring(L, -1);
- std::string err = message ? message : "An unexpected error occurred and forced the lua state to call atpanic";
- throw error(err);
+ if (message) {
+ std::string err = message;
+ lua_pop(L, 1);
+ throw error(err);
+ }
+ throw error(std::string("An unexpected error occurred and forced the lua state to call atpanic"));
#endif
}
diff --git a/3rdparty/sol2/sol/state_view.hpp b/3rdparty/sol2/sol/state_view.hpp
index 3efb3674d25..d3c12d3bd4a 100644
--- a/3rdparty/sol2/sol/state_view.hpp
+++ b/3rdparty/sol2/sol/state_view.hpp
@@ -115,6 +115,10 @@ namespace sol {
}
+ state_view(this_state L) : state_view(L.L){
+
+ }
+
lua_State* lua_state() const {
return L;
}
@@ -222,18 +226,30 @@ namespace sol {
return require_core(key, [this, &filename]() {stack::script_file(L, filename); }, create_global);
}
+ protected_function_result do_string(const std::string& code) {
+ sol::protected_function pf = load(code);
+ return pf();
+ }
+
+ protected_function_result do_file(const std::string& filename) {
+ sol::protected_function pf = load_file(filename);
+ return pf();
+ }
+
function_result script(const std::string& code) {
- int index = (::std::max)(lua_gettop(L), 1);
+ int index = lua_gettop(L);
stack::script(L, code);
- int returns = lua_gettop(L) - (index - 1);
- return function_result(L, index, returns);
+ int postindex = lua_gettop(L);
+ int returns = postindex - index;
+ return function_result(L, (std::max)(postindex - (returns - 1), 1), returns);
}
function_result script_file(const std::string& filename) {
- int index = (::std::max)(lua_gettop(L), 1);
+ int index = lua_gettop(L);
stack::script_file(L, filename);
- int returns = lua_gettop(L) - (index - 1);
- return function_result(L, index, returns);
+ int postindex = lua_gettop(L);
+ int returns = postindex - index;
+ return function_result(L, (std::max)(postindex - (returns - 1), 1), returns);
}
load_result load(const std::string& code) {
@@ -317,7 +333,7 @@ namespace sol {
template<typename T>
state_view& set_usertype(usertype<T>& user) {
- return set_usertype(usertype_traits<T>::name, user);
+ return set_usertype(usertype_traits<T>::name(), user);
}
template<typename Key, typename T>
diff --git a/3rdparty/sol2/sol/table_core.hpp b/3rdparty/sol2/sol/table_core.hpp
index 918f3d4ad76..107cd19776e 100644
--- a/3rdparty/sol2/sol/table_core.hpp
+++ b/3rdparty/sol2/sol/table_core.hpp
@@ -244,7 +244,7 @@ namespace sol {
template<typename T>
basic_table_core& set_usertype(usertype<T>& user) {
- return set_usertype(usertype_traits<T>::name, user);
+ return set_usertype(usertype_traits<T>::name(), user);
}
template<typename Key, typename T>
@@ -419,6 +419,7 @@ namespace sol {
template <typename... Args>
static inline table create_with(lua_State* L, Args&&... args) {
+ static_assert(sizeof...(Args) % 2 == 0, "You must have an even number of arguments for a key, value ... list.");
static const int narr = static_cast<int>(meta::count_2_for_pack<std::is_integral, Args...>::value);
return create(L, narr, static_cast<int>((sizeof...(Args) / 2) - narr), std::forward<Args>(args)...);
}
diff --git a/3rdparty/sol2/sol/types.hpp b/3rdparty/sol2/sol/types.hpp
index 86ac4806532..7761be6d0f2 100644
--- a/3rdparty/sol2/sol/types.hpp
+++ b/3rdparty/sol2/sol/types.hpp
@@ -361,6 +361,7 @@ namespace sol {
new_index,
mode,
call,
+ call_function = call,
metatable,
to_string,
length,
@@ -377,7 +378,13 @@ namespace sol {
less_than,
less_than_or_equal_to,
garbage_collect,
- call_function = call,
+ floor_division,
+ bitwise_left_shift,
+ bitwise_right_shift,
+ bitwise_not,
+ bitwise_and,
+ bitwise_or,
+ bitwise_xor,
};
typedef meta_function meta_method;
@@ -393,7 +400,7 @@ namespace sol {
"__newindex",
"__mode",
"__call",
- "__metatable",
+ "__mt",
"__tostring",
"__len",
"__unm",
@@ -643,6 +650,12 @@ namespace sol {
template <typename T>
struct lua_type_of<T, std::enable_if_t<std::is_enum<T>::value>> : std::integral_constant<type, type::number> {};
+ template <typename T, typename C = void>
+ struct is_container : std::false_type {};
+
+ template <typename T>
+ struct is_container<T, std::enable_if_t<meta::has_begin_end<meta::unqualified_t<T>>::value>> : std::true_type {};
+
template <>
struct lua_type_of<meta_function> : std::integral_constant<type, type::string> {};
@@ -747,6 +760,9 @@ namespace sol {
template <typename T>
struct is_userdata<basic_userdata<T>> : std::true_type {};
+ template <typename T>
+ struct is_container : detail::is_container<T>{};
+
template<typename T>
inline type type_of() {
return lua_type_of<meta::unqualified_t<T>>::value;
diff --git a/3rdparty/sol2/sol/usertype_metatable.hpp b/3rdparty/sol2/sol/usertype_metatable.hpp
index cd57f2679b9..fff5f60dab8 100644
--- a/3rdparty/sol2/sol/usertype_metatable.hpp
+++ b/3rdparty/sol2/sol/usertype_metatable.hpp
@@ -116,8 +116,8 @@ namespace sol {
static void walk_single_base(lua_State* L, bool& found, int& ret, string_detail::string_shim&) {
if (found)
return;
- const char* metakey = &usertype_traits<Base>::metatable[0];
- const char* gcmetakey = &usertype_traits<Base>::gc_table[0];
+ const char* metakey = &usertype_traits<Base>::metatable()[0];
+ const char* gcmetakey = &usertype_traits<Base>::gc_table()[0];
const char* basewalkkey = is_index ? detail::base_class_index_propogation_key() : detail::base_class_new_index_propogation_key();
luaL_getmetatable(L, metakey);
@@ -466,7 +466,7 @@ namespace sol {
static umt_t& make_cleanup(lua_State* L, umt_t&& umx) {
// ensure some sort of uniqueness
static int uniqueness = 0;
- std::string uniquegcmetakey = usertype_traits<T>::user_gc_metatable;
+ std::string uniquegcmetakey = usertype_traits<T>::user_gc_metatable();
// std::to_string doesn't exist in android still, with NDK, so this bullshit
// is necessary
// thanks, Android :v
@@ -477,7 +477,7 @@ namespace sol {
snprintf(uniquetarget, uniquegcmetakey.length(), "%d", uniqueness);
++uniqueness;
- const char* gcmetakey = &usertype_traits<T>::gc_table[0];
+ const char* gcmetakey = &usertype_traits<T>::gc_table()[0];
// Make sure userdata's memory is properly in lua first,
// otherwise all the light userdata we make later will become invalid
stack::push<user<umt_t>>(L, metatable_key, uniquegcmetakey, std::move(umx));
@@ -514,16 +514,16 @@ namespace sol {
luaL_Reg* metaregs = nullptr;
switch (i) {
case 0:
- metakey = &usertype_traits<T*>::metatable[0];
+ metakey = &usertype_traits<T*>::metatable()[0];
metaregs = ref_table.data();
break;
case 1:
- metakey = &usertype_traits<detail::unique_usertype<T>>::metatable[0];
+ metakey = &usertype_traits<detail::unique_usertype<T>>::metatable()[0];
metaregs = unique_table.data();
break;
case 2:
default:
- metakey = &usertype_traits<T>::metatable[0];
+ metakey = &usertype_traits<T>::metatable()[0];
metaregs = value_table.data();
break;
}
@@ -554,7 +554,7 @@ namespace sol {
}
// metatable on the metatable
// for call constructor purposes and such
- lua_createtable(L, 0, 1);
+ lua_createtable(L, 0, 3);
stack_reference metabehind(L, -1);
if (um.callconstructfunc != nullptr) {
stack::set_field(L, meta_function::call_function, make_closure(um.callconstructfunc, make_light(um)), metabehind.stack_index());
@@ -567,9 +567,26 @@ namespace sol {
metabehind.pop();
// We want to just leave the table
// in the registry only, otherwise we return it
- if (i < 2) {
- t.pop();
+ t.pop();
+ }
+
+ // Now for the shim-table that actually gets assigned to the name
+ luaL_newmetatable(L, &usertype_traits<T>::user_metatable()[0]);
+ stack_reference t(L, -1);
+ stack::push(L, make_light(um));
+ luaL_setfuncs(L, value_table.data(), 1);
+ {
+ lua_createtable(L, 0, 3);
+ stack_reference metabehind(L, -1);
+ if (um.callconstructfunc != nullptr) {
+ stack::set_field(L, meta_function::call_function, make_closure(um.callconstructfunc, make_light(um)), metabehind.stack_index());
}
+ if (um.secondarymeta) {
+ stack::set_field(L, meta_function::index, make_closure(umt_t::index_call, make_light(um)), metabehind.stack_index());
+ stack::set_field(L, meta_function::new_index, make_closure(umt_t::new_index_call, make_light(um)), metabehind.stack_index());
+ }
+ stack::set_field(L, metatable_key, metabehind, t.stack_index());
+ metabehind.pop();
}
return 1;
diff --git a/3rdparty/sol2/sol/usertype_traits.hpp b/3rdparty/sol2/sol/usertype_traits.hpp
index 2dd3d62cbaf..0857b30e0c2 100644
--- a/3rdparty/sol2/sol/usertype_traits.hpp
+++ b/3rdparty/sol2/sol/usertype_traits.hpp
@@ -28,28 +28,32 @@ namespace sol {
template<typename T>
struct usertype_traits {
- static const std::string name;
- static const std::string qualified_name;
- static const std::string metatable;
- static const std::string user_gc_metatable;
- static const std::string gc_table;
+ static const std::string& name() {
+ static const std::string n = detail::short_demangle<T>();
+ return n;
+ }
+ static const std::string& qualified_name() {
+ static const std::string q_n = detail::demangle<T>();
+ return q_n;
+ }
+ static const std::string& metatable() {
+ static const std::string m = std::string("sol.").append(detail::demangle<T>());
+ return m;
+ }
+ static const std::string& user_metatable() {
+ static const std::string u_m = std::string("sol.").append(detail::demangle<T>()).append(".user");
+ return u_m;
+ }
+ static const std::string& user_gc_metatable() {
+ static const std::string u_g_m = std::string("sol.").append(detail::demangle<T>()).append(".user\xE2\x99\xBB");
+ return u_g_m;
+ }
+ static const std::string& gc_table() {
+ static const std::string g_t = std::string("sol.").append(detail::demangle<T>().append(".\xE2\x99\xBB"));
+ return g_t;
+ }
};
- template<typename T>
- const std::string usertype_traits<T>::name = detail::short_demangle<T>();
-
- template<typename T>
- const std::string usertype_traits<T>::qualified_name = detail::demangle<T>();
-
- template<typename T>
- const std::string usertype_traits<T>::metatable = std::string("sol.").append(detail::demangle<T>());
-
- template<typename T>
- const std::string usertype_traits<T>::user_gc_metatable = std::string("sol.").append(detail::demangle<T>()).append(".user\xE2\x99\xBB");
-
- template<typename T>
- const std::string usertype_traits<T>::gc_table = std::string("sol.").append(detail::demangle<T>().append(".\xE2\x99\xBB"));
-
}
#endif // SOL_USERTYPE_TRAITS_HPP
diff --git a/3rdparty/sol2/test_containers.cpp b/3rdparty/sol2/test_containers.cpp
index 015fbd20db0..d43db52d4b4 100644
--- a/3rdparty/sol2/test_containers.cpp
+++ b/3rdparty/sol2/test_containers.cpp
@@ -273,6 +273,57 @@ TEST_CASE("containers/arbitrary-creation", "userdata and tables should be usable
REQUIRE(c.get<std::string>("project") == "sol");
}
+TEST_CASE("containers/extra-functions", "make sure the manipulation functions are present and usable and working across various container types") {
+ sol::state lua;
+ lua.open_libraries();
+
+ lua.script(R"(
+function g (x)
+ x:add(20)
+end
+
+function h (x)
+ x:add(20, 40)
+end
+
+function i (x)
+ x:clear()
+end
+)");
+
+ // Have the function we
+ // just defined in Lua
+ sol::function g = lua["g"];
+ sol::function h = lua["h"];
+ sol::function i = lua["i"];
+
+ // Set a global variable called
+ // "arr" to be a vector of 5 lements
+ lua["arr"] = std::vector<int>{ 2, 4, 6, 8, 10 };
+ lua["map"] = std::map<int, int>{ { 1 , 2 },{ 2, 4 },{ 3, 6 },{ 4, 8 },{ 5, 10 } };
+ lua["set"] = std::set<int>{ 2, 4, 6, 8, 10 };
+ std::vector<int>& arr = lua["arr"];
+ std::map<int, int>& map = lua["map"];
+ std::set<int>& set = lua["set"];
+ REQUIRE(arr.size() == 5);
+ REQUIRE(map.size() == 5);
+ REQUIRE(set.size() == 5);
+
+ g(lua["set"]);
+ g(lua["arr"]);
+ h(lua["map"]);
+ REQUIRE(arr.size() == 6);
+ REQUIRE(map.size() == 6);
+ REQUIRE(set.size() == 6);
+
+ i(lua["arr"]);
+ i(lua["map"]);
+ i(lua["set"]);
+ REQUIRE(arr.empty());
+ REQUIRE(map.empty());
+ REQUIRE(set.empty());
+}
+
TEST_CASE("containers/usertype-transparency", "Make sure containers pass their arguments through transparently and push the results as references, not new values") {
class A {
public:
diff --git a/3rdparty/sol2/test_simple_usertypes.cpp b/3rdparty/sol2/test_simple_usertypes.cpp
index 4683aa3b631..ca3e7cdca89 100644
--- a/3rdparty/sol2/test_simple_usertypes.cpp
+++ b/3rdparty/sol2/test_simple_usertypes.cpp
@@ -453,7 +453,11 @@ TEST_CASE("usertype/simple-table-append", "Ensure that appending to the meta tab
table["func"] = &A::func;
A a;
lua.set("a", &a);
+ lua.set("pa", &a);
+ lua.set("ua", std::make_unique<A>());
REQUIRE_NOTHROW(
- lua.script("assert(a:func() == 5000)")
+ lua.script("assert(a:func() == 5000)");
+ lua.script("assert(pa:func() == 5000)");
+ lua.script("assert(ua:func() == 5000)");
);
}
diff --git a/3rdparty/sol2/tests.cpp b/3rdparty/sol2/tests.cpp
index 9aeaf255a34..9e6dcf5c5d5 100644
--- a/3rdparty/sol2/tests.cpp
+++ b/3rdparty/sol2/tests.cpp
@@ -664,6 +664,21 @@ TEST_CASE("proxy/proper-pushing", "allow proxies to reference other proxies and
REQUIRE(b);
}
+TEST_CASE("proxy/equality", "check to make sure equality tests work") {
+ sol::state lua;
+ REQUIRE((lua["a"] == sol::nil));
+ REQUIRE_FALSE((lua["a"] == nullptr));
+ REQUIRE_FALSE((lua["a"] == 0));
+ REQUIRE_FALSE((lua["a"] == 2));
+
+ lua["a"] = 2;
+
+ REQUIRE_FALSE((lua["a"] == sol::nil)); //0
+ REQUIRE_FALSE((lua["a"] == nullptr)); //0
+ REQUIRE_FALSE((lua["a"] == 0)); //0
+ REQUIRE((lua["a"] == 2)); //1
+}
+
TEST_CASE("compilation/const-regression", "make sure constness in tables is respected all the way down") {
struct State {
public:
@@ -678,3 +693,102 @@ TEST_CASE("compilation/const-regression", "make sure constness in tables is resp
State* s = state.state_.registry()["state"];
REQUIRE(s == &state);
}
+
+TEST_CASE("numbers/integers", "make sure integers are detectable on most platforms") {
+ sol::state lua;
+
+ lua["a"] = 50; // int
+ lua["b"] = 50.5; // double
+
+ sol::object a = lua["a"];
+ sol::object b = lua["b"];
+
+ bool a_is_int = a.is<int>();
+ bool a_is_double = a.is<double>();
+
+ bool b_is_int = b.is<int>();
+ bool b_is_double = b.is<double>();
+
+ REQUIRE(a_is_int);
+ REQUIRE(a_is_double);
+
+ // TODO: will this fail on certain lower Lua versions?
+ REQUIRE_FALSE(b_is_int);
+ REQUIRE(b_is_double);
+}
+
+TEST_CASE("state/script-returns", "make sure script returns are done properly") {
+ std::string script =
+ R"(
+local example =
+{
+ str = "this is a string",
+ num = 1234,
+
+ func = function(self)
+ print(self.str)
+ return "fstr"
+ end
+}
+
+return example;
+)";
+
+ auto bar = [&script](sol::this_state l) {
+ sol::state_view lua = l;
+ sol::table data = lua.script(script);
+
+ std::string str = data["str"];
+ int num = data["num"];
+ std::string fstr = data["func"](data);
+ REQUIRE(str == "this is a string");
+ REQUIRE(fstr == "fstr");
+ REQUIRE(num == 1234);
+ };
+
+ auto foo = [&script](int, sol::this_state l) {
+ sol::state_view lua = l;
+ sol::table data = lua.script(script);
+
+ std::string str = data["str"];
+ int num = data["num"];
+ std::string fstr = data["func"](data);
+ REQUIRE(str == "this is a string");
+ REQUIRE(fstr == "fstr");
+ REQUIRE(num == 1234);
+ };
+
+ auto bar2 = [&script](sol::this_state l) {
+ sol::state_view lua = l;
+ sol::table data = lua.do_string(script);
+
+ std::string str = data["str"];
+ int num = data["num"];
+ std::string fstr = data["func"](data);
+ REQUIRE(str == "this is a string");
+ REQUIRE(fstr == "fstr");
+ REQUIRE(num == 1234);
+ };
+
+ auto foo2 = [&script](int, sol::this_state l) {
+ sol::state_view lua = l;
+ sol::table data = lua.do_string(script);
+
+ std::string str = data["str"];
+ int num = data["num"];
+ std::string fstr = data["func"](data);
+ REQUIRE(str == "this is a string");
+ REQUIRE(fstr == "fstr");
+ REQUIRE(num == 1234);
+ };
+
+ sol::state lua;
+ lua.open_libraries();
+
+ lua.set_function("foo", foo);
+ lua.set_function("foo2", foo2);
+ lua.set_function("bar", bar);
+ lua.set_function("bar2", bar2);
+
+ lua.script("bar() bar2() foo(1) foo2(1)");
+}