update table documentation and force traits not to use a deleted destructor -- rather, default it according to what it inherits

This commit is contained in:
ThePhD 2017-08-22 10:53:46 -04:00
parent 7164a8a30a
commit e4c3ded4b2
7 changed files with 51 additions and 7 deletions

View File

@ -21,7 +21,7 @@ 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 C++ type without explicitly using the ``as_table_t`` marker for your get and conversion operations using Sol.
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. You can deserialize the Lua table into something explicitly using the ``sol::as_table_t`` marker for your get and conversion operations using Sol. At that point, the returned type is deserialized **from** a table, meaning you cannot reference any kind of C++ data directly as you do with regular userdata/usertypes. *All C++ type information is lost upon serialization into Lua.*
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``.

View File

@ -3,11 +3,15 @@ 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.
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 C++ container that they came from, as well as a small amount of indexing and other operations that behave properly given the table type.
An overview of these traits and additional information can be found :doc:`at the top level container page<../containers>`.
If you need to deal with these things from and in Lua to be **actual**, true-blue, Lua tables, please consider :doc:`sol::as_table<as_table>` and :doc:`sol::nested<nested>` for serialization and deserialization into and out of the VM with sol2 operations. You can also force something that is marked as not-a-container by using :doc:`sol::as_container<as_container>`.
If you need to deal with these things from and in Lua to be **actual**, true-blue, Lua tables, please consider :doc:`sol::as_table<as_table>` and :doc:`sol::nested<nested>` for serialization and deserialization into and out of the VM with sol2 operations. You can also force something that is marked as not-a-container by using :doc:`sol::as_container<as_container>` for sol2 to push it as a userdata with the aforementioned special usertype metatable into Lua.
.. note::
Overriding the detection traits and operation traits listed :doc:`on the top level container page<../containers>` and then trying to use ``sol::as_table`` or similar can result in compilation failures if you do not have a proper ``begin()`` or ``end()`` function on the type. If you want things to behave with special usertype considerations, please do not wrap the container in one of the special table-forcing abstractions.
a complete example

View File

@ -12,6 +12,8 @@ nested
``sol::nested<...>`` is a template class similar to :doc:`sol::as_table<as_table>`, but with the caveat that every :doc:`container type<containers>` within the ``sol::nested`` type will be retrieved as a table from lua. This is helpful when you need to receive C++-style vectors, lists, and maps nested within each other: all of them will be deserialized from lua using table properties rather than anything else.
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. You can deserialize the Lua table into something explicitly using the ``sol::as_table_t`` marker for your get and conversion operations using Sol. At that point, the returned type is deserialized **from** a table, meaning you cannot reference any kind of C++ data directly as you do with regular userdata/usertypes. *All C++ type information is lost upon serialization into Lua.*
The `example`_ provides a very in-depth look at both ``sol::as_table<T>`` and ``sol::nested<T>``, and how the two are equivalent.
.. _example: https://github.com/ThePhD/sol2/blob/develop/examples/containers_as_table.cpp

View File

@ -5,6 +5,9 @@ containers
Containers are objects that are meant to be inspected and iterated and whose job is to typically provide storage to a collection of items. The standard library has several containers of varying types, and all of them have ``begin()`` and ``end()`` methods which return iterators. C-style arrays are also containers, and sol2 will detect all of them for use and bestow upon them special properties and functions.
* Containers from C++ are stored as ``userdata`` with special ``usertype`` metatables with :ref:`special operations<container-operations>`
- In Lua 5.1, this means containers pushed without wrappers like :doc:`as_table<api/as_table>` and :doc:`nested<api/nested>` will not work with ``pairs`` or other built-in iteration functions from Lua
+ Lua 5.2+ will behave just fine (does not include LuaJIT 2.0.x)
- You must push containers into C++ by returning them directly and getting/setting them directly, and they will have a type of ``sol::type::userdata`` and treated like a usertype
* Containers can be manipulated from both C++ and Lua, and, like userdata, will `reflect changes if you use a reference`_ to the data.
* This means containers **do not automatically serialize as Lua tables**
- If you need tables, consider using ``sol::as_table`` and ``sol::nested``
@ -143,6 +146,10 @@ Below are the many container operations and their override points for ``containe
| | | | | - calling ``pairs( c )`` in Lua 5.1 / LuaJIT will crash with assertion failure (Lua expects ``c`` to be a table) |
+-----------+-------------------------------------------+---------------------------------------+----------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
.. note::
If your type does not adequately support ``begin()`` and ``end()`` and you cannot override it, use the ``sol::is_container`` trait override plus a custom implementation of ``pairs`` on your usertype to get it to work as you please. Note that a type not having proper ``begin()`` and ``end()`` will not work if you try to forcefully serialize it as a table (this means avoid using :doc:`sol::as_table<api/as_table>` and :doc:`sol::nested<api/nested>`, otherwise you will have compiler errors). Just set it or get it directly, as shown in the examples, to work with the container examples.
.. _container-classifications:
container classifications

View File

@ -20,8 +20,8 @@
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// This file was generated with a script.
// Generated 2017-08-21 20:22:51.208425 UTC
// This header was generated with sol v2.18.1 (revision 8f6b51a)
// Generated 2017-08-22 14:53:37.052568 UTC
// This header was generated with sol v2.18.1 (revision 7164a8a)
// https://github.com/ThePhD/sol2
#ifndef SOL_SINGLE_INCLUDE_HPP
@ -1097,7 +1097,7 @@ namespace sol {
using no = struct { char s[2]; };
struct F { void operator()(); };
struct Derived : T, F { ~Derived() = delete; };
struct Derived : T, F { ~Derived() = default; };
template<typename U, U> struct Check;
template<typename V>

View File

@ -261,7 +261,7 @@ namespace sol {
using no = struct { char s[2]; };
struct F { void operator()(); };
struct Derived : T, F { ~Derived() = delete; };
struct Derived : T, F { ~Derived() = default; };
template<typename U, U> struct Check;
template<typename V>

View File

@ -62,6 +62,37 @@ TEST_CASE("gc/destructors", "test if destructors are fired properly through gc o
REQUIRE(nullptr != pt);
}
TEST_CASE("gc/virtual destructors", "ensure types with virtual destructions behave just fine") {
class B;
class A;
static std::vector<B*> bs;
static std::vector<A*> as;
class A {
public:
virtual ~A() { as.push_back(this); std::cout << "~A" << std::endl; }
};
class B : public A {
public:
virtual ~B() { bs.push_back(this); std::cout << "~B" << std::endl; }
};
{
sol::state lua;
lua.open_libraries(sol::lib::base);
lua.new_usertype<A>("A");
lua.new_usertype<B>("B", sol::base_classes, sol::bases<A>());
B b1;
lua["b1"] = b1; // breaks here
}
REQUIRE(as.size() == 2);
REQUIRE(bs.size() == 2);
}
TEST_CASE("gc/function argument storage", "ensure functions take references on their types, not ownership, when specified") {
class gc_entity;
static std::vector<gc_entity*> entities;