Ensure construction of special types in simple_usertype is working, and for regular usertype as well.

This commit is contained in:
ThePhD 2017-02-20 03:44:41 -05:00
parent dde4aa64fc
commit b7b63668c8
8 changed files with 118 additions and 60 deletions

View File

@ -1,14 +1,14 @@
{%- extends "haiku/layout.html" %}
{% block haikuheader %}
<div class="header-left">
{{ super() }}
</div>
<div class="header-right">
<h3>Search the Documentation</h3>
<form action="{{ pathto('search') }}" method="get">
<input type="text" name="q" value="">
<input type="submit" value="search">
</form>
</div>
{%- extends "haiku/layout.html" %}
{% block haikuheader %}
<div class="header-left">
{{ super() }}
</div>
<div class="header-right">
<h3>Search the Documentation</h3>
<form action="{{ pathto('search') }}" method="get">
<input type="text" name="q" value="">
<input type="submit" value="search">
</form>
</div>
{% endblock %}

View File

@ -1,18 +1,18 @@
@import url('haiku.css');
.header-left {
float: left;
display: inline-block;
vertical-align: top;
}
.header-right {
float: right;
display: inline-block;
vertical-align: top;
}
.header-right h3 {
margin: 0;
padding-top: 15px;
@import url('haiku.css');
.header-left {
float: left;
display: inline-block;
vertical-align: top;
}
.header-right {
float: right;
display: inline-block;
vertical-align: top;
}
.header-right h3 {
margin: 0;
padding-top: 15px;
}

View File

@ -1,4 +1,4 @@
[theme]
inherit = haiku
stylesheet = sol2.css
[theme]
inherit = haiku
stylesheet = sol2.css
pygments_style = autumn

View File

@ -163,10 +163,6 @@ If you don't specify any constructor options at all and the type is `default_con
+ The functions can take any form and return anything, since they're just considered to be some plain function and no placement new or otherwise needs to be done. Results from this function will be pushed into Lua according to the same rules as everything else.
+ Can be used to stop the generation of a ``.new()`` default constructor since a ``sol::factories`` entry will be recognized as a constructor for the usertype
+ If this is not sufficient, see next 2 entries on how to specifically block a constructor
* ``{anything}, sol::no_constructor``
- Specifically tells Sol not to create a ``.new()`` if one is not specified and the type is default-constructible
- ``{anything}`` should probably be ``"new"``, which will specifically block its creation and give a proper warning if someone calls ``new`` (otherwise it will just give a nil value error)
- *Combine with the next one to only allow a factory function for your function type*
* ``{anything}, {some_factory_function}``
- Essentially binds whatever the function is to name ``{anything}``
- When used WITH the ``sol::no_constructor`` option above (e.g. ``"new", sol::no_constructor`` and after that having ``"create", &my_creation_func``), one can remove typical constructor avenues and then only provide specific factory functions. Note that this combination is similar to using the ``sol::factories`` method mentioned earlier in this list. To control the destructor as well, see further below
@ -174,6 +170,10 @@ If you don't specify any constructor options at all and the type is `default_con
- The purpose of this is to enable the syntax ``local v = my_class( 24 )`` and have that call a constructor; it has no other purpose
- This is compatible with luabind, kaguya and other Lua library syntaxes and looks similar to C++ syntax, but the general consensus in Programming with Lua and other places is to use a function named ``new``
- Note that with the ``sol::call_constructor`` key, a construct type above must be specified. A free function without it will pass in the metatable describing this object as the first argument without that distinction, which can cause strange runtime errors.
* ``{anything}, sol::no_constructor``
- Specifically tells Sol not to create a ``.new()`` if one is not specified and the type is default-constructible
- When the key ``{anything}`` is called on the table, it will result in an error. The error might be that the type is not-constructible.
- *Use this plus some of the above to allow a factory function for your function type but prevent other types of constructor idioms in Lua*
usertype destructor options
+++++++++++++++++++++++++++

View File

@ -28,6 +28,12 @@
#include "stack.hpp"
namespace sol {
namespace function_detail {
inline int no_construction_error(lua_State* L) {
return luaL_error(L, "sol: cannot call this constructor (tagged as non-constructible)");
}
}
namespace call_detail {
template <typename R, typename W>
@ -244,7 +250,7 @@ namespace sol {
template <bool is_index, bool is_variable, bool checked, int boost, typename C>
struct agnostic_lua_call_wrapper<no_construction, is_index, is_variable, checked, boost, C> {
static int call(lua_State* L, const no_construction&) {
return luaL_error(L, "sol: cannot call this constructor (tagged as non-constructible)");
return function_detail::no_construction_error(L);
}
};

View File

@ -333,6 +333,18 @@ namespace sol {
}
};
template <>
struct pusher<no_construction> {
static int push(lua_State* L, no_construction) {
lua_CFunction cf = &function_detail::no_construction_error;
return stack::push(L, cf);
}
static int push(lua_State* L, no_construction c, function_detail::call_indicator) {
return push(L, c);
}
};
template <typename T, typename... Lists>
struct pusher<detail::tagged<T, constructor_list<Lists...>>> {
static int push(lua_State* L, detail::tagged<T, constructor_list<Lists...>>) {

View File

@ -541,15 +541,12 @@ TEST_CASE("usertype/simple-call-constructor", "ensure that all kinds of call-bas
auto vfactories = sol::factories(
[](const sol::table& tbl) {
for (auto v : tbl)
{
REQUIRE(v.second.valid());
// This fails only when the call_constructor is used:
REQUIRE(v.second.is<thing>());
for (auto v : tbl) {
REQUIRE(v.second.valid());
REQUIRE(v.second.is<thing>());
}
return v_test();
}
return v_test();
}
);
lua.new_simple_usertype<v_test>("v_test",
@ -568,6 +565,30 @@ TEST_CASE("usertype/simple-call-constructor", "ensure that all kinds of call-bas
}
}
TEST_CASE("usertype/simple-no_constructor", "make sure simple usertype errors when no-constructor types are called") {
struct thing {};
SECTION("new no_constructor") {
sol::state lua;
lua.open_libraries(sol::lib::base);
lua.new_simple_usertype<thing>("thing",
sol::meta_function::construct, sol::no_constructor
);
REQUIRE_THROWS(lua.script("a = thing.new()"));
}
SECTION("call no_constructor") {
sol::state lua;
lua.open_libraries(sol::lib::base);
lua.new_simple_usertype<thing>("thing",
sol::call_constructor, sol::no_constructor
);
REQUIRE_THROWS(lua.script("a = thing()"));
}
}
TEST_CASE("usertype/simple-missing-key", "make sure a missing key returns nil") {
struct thing {};

View File

@ -1036,28 +1036,47 @@ TEST_CASE("usertype/blank_constructor", "make sure lua types cannot be construct
TEST_CASE("usertype/no_constructor", "make sure lua types cannot be constructed if a blank / empty constructor is provided") {
sol::state lua;
lua.open_libraries(sol::lib::base);
SECTION("order1")
{
SECTION("order1") {
sol::state lua;
lua.open_libraries(sol::lib::base);
lua.new_usertype<thing>("thing",
"v", &thing::v
, sol::call_constructor, sol::no_constructor
"v", &thing::v,
sol::call_constructor, sol::no_constructor
);
REQUIRE_THROWS(lua.script("t = thing.new()"));
REQUIRE_THROWS(lua.script("t = thing()"));
}
SECTION("order2")
{
lua.new_usertype<thing>("thing"
, sol::call_constructor, sol::no_constructor
, "v", &thing::v
SECTION("order2") {
sol::state lua;
lua.open_libraries(sol::lib::base);
lua.new_usertype<thing>("thing",
sol::call_constructor, sol::no_constructor,
"v", &thing::v
);
REQUIRE_THROWS(lua.script("t = thing.new()"));
}
REQUIRE_THROWS(lua.script("t = thing.new()"));
SECTION("new no_constructor") {
sol::state lua;
lua.open_libraries(sol::lib::base);
lua.new_usertype<thing>("thing",
sol::meta_function::construct, sol::no_constructor
);
REQUIRE_THROWS(lua.script("a = thing.new()"));
}
SECTION("call no_constructor") {
sol::state lua;
lua.open_libraries(sol::lib::base);
lua.new_usertype<thing>("thing",
sol::call_constructor, sol::no_constructor
);
REQUIRE_THROWS(lua.script("a = thing()"));
}
}
TEST_CASE("usertype/coverage", "try all the things") {