Revert previous change of not pushing nil when we encounter a nullptr from special usertypes. If people want to check, they'll need to use optional or a raw pointer: messing with the raw usertype can also lead to some surprising problems, so we don't need to specialize for that use case.

This commit is contained in:
ThePhD 2017-06-30 18:18:25 -04:00
parent 874a14f2d9
commit 1a6937e24e
3 changed files with 174 additions and 4 deletions

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-06-26 14:10:10.059447 UTC
// This header was generated with sol v2.17.5 (revision 13370e7)
// Generated 2017-06-30 22:15:33.363723 UTC
// This header was generated with sol v2.17.5 (revision 874a14f)
// https://github.com/ThePhD/sol2
#ifndef SOL_SINGLE_INCLUDE_HPP
@ -1614,7 +1614,7 @@ inline int luaL_fileresult(lua_State *L, int stat, const char *fname) {
}
else {
char buf[1024];
#if defined(__GLIBC__) || defined(_POSIX_VERSION)
#if defined(__GLIBC__) || defined(_POSIX_VERSION) || defined(__APPLE__)
strerror_r(en, buf, 1024);
#else
strerror_s(buf, 1024, en);
@ -6679,6 +6679,9 @@ namespace sol {
template <typename Arg, meta::enable<std::is_base_of<Real, meta::unqualified_t<Arg>>> = meta::enabler>
static int push(lua_State* L, Arg&& arg) {
if (unique_usertype_traits<T>::is_null(arg)) {
return stack::push(L, lua_nil);
}
return push_deep(L, std::forward<Arg>(arg));
}

View File

@ -143,6 +143,9 @@ namespace sol {
template <typename Arg, meta::enable<std::is_base_of<Real, meta::unqualified_t<Arg>>> = meta::enabler>
static int push(lua_State* L, Arg&& arg) {
if (unique_usertype_traits<T>::is_null(arg)) {
return stack::push(L, lua_nil);
}
return push_deep(L, std::forward<Arg>(arg));
}

View File

@ -1140,7 +1140,171 @@ TEST_CASE("functions/set_function-already-wrapped", "setting a function returned
}
}
TEST_CASE("functions/unique-overloading", "make sure overloading can work with ptr vs. specifically asking for a unique usertype") {
TEST_CASE("functions/pointer-nil", "ensure specific semantics for handling pointer-nils passed through sol") {
struct nil_test {
static void f(nil_test* p) {
REQUIRE(p == nullptr);
}
static void g(std::unique_ptr<nil_test>& p) {
REQUIRE(p == nullptr);
}
static void h(std::shared_ptr<nil_test>& p) {
REQUIRE(p == nullptr);
}
};
std::shared_ptr<nil_test> sptr;
std::unique_ptr<nil_test> uptr;
std::unique_ptr<nil_test> ruptr;
nil_test* rptr = ruptr.get();
nil_test* vptr = nullptr;
SECTION("ptr") {
sol::state lua;
lua["v1"] = sptr;
lua["v2"] = std::unique_ptr<nil_test>();
lua["v3"] = rptr;
lua["v4"] = vptr;
REQUIRE_NOTHROW([&]() {
nil_test* v1 = lua["v1"];
nil_test* v2 = lua["v2"];
nil_test* v3 = lua["v3"];
nil_test* v4 = lua["v4"];
REQUIRE(v1 == sptr.get());
REQUIRE(v1 == nullptr);
REQUIRE(v2 == uptr.get());
REQUIRE(v2 == nullptr);
REQUIRE(v3 == rptr);
REQUIRE(v3 == nullptr);
REQUIRE(v4 == vptr);
REQUIRE(v4 == nullptr);
}());
}
SECTION("ptr") {
sol::state lua;
lua.open_libraries();
lua["v1"] = sptr;
lua["v2"] = std::unique_ptr<nil_test>();
lua["v3"] = rptr;
lua["v4"] = vptr;
lua["f"] = &nil_test::f;
lua["g"] = &nil_test::g;
lua["h"] = &nil_test::h;
REQUIRE_NOTHROW([&]() {
lua.script("f(v1)");
lua.script("f(v2)");
lua.script("f(v3)");
lua.script("f(v4)");
lua.script("assert(v1 == nil)");
lua.script("assert(v2 == nil)");
lua.script("assert(v3 == nil)");
lua.script("assert(v4 == nil)");
}());
}
SECTION("throw unique argument") {
sol::state lua;
lua["v2"] = std::unique_ptr<nil_test>();
lua["g"] = &nil_test::g;
REQUIRE_THROWS([&]() {
lua.script("g(v2)");
}());
}
SECTION("throw shared argument") {
sol::state lua;
lua["v1"] = sptr;
lua["h"] = &nil_test::h;
REQUIRE_THROWS([&]() {
lua.script("h(v1)");
}());
}
SECTION("throw ref") {
REQUIRE_THROWS([&]() {
sol::state lua;
lua["v1"] = sptr;
nil_test& v1 = lua["v1"];
(void)(&v1 == sptr.get());
}());
REQUIRE_THROWS([&]() {
sol::state lua;
lua["v2"] = std::unique_ptr<nil_test>();
nil_test& v2 = lua["v2"];
(void)(&v2 == uptr.get());
}());
REQUIRE_THROWS([&]() {
sol::state lua;
lua["v3"] = rptr;
nil_test& v3 = lua["v3"];
(void)(&v3 == rptr);
}());
REQUIRE_THROWS([&]() {
sol::state lua;
lua["v4"] = vptr;
nil_test& v4 = lua["v4"];
(void)(&v4 == vptr);
}());
}
SECTION("throw unique") {
REQUIRE_THROWS([&]() {
sol::state lua;
lua["v1"] = sptr;
std::unique_ptr<nil_test>& v1 = lua["v1"];
(void)(v1.get() == sptr.get());
}());
REQUIRE_THROWS([&]() {
sol::state lua;
lua["v2"] = std::unique_ptr<nil_test>();
std::unique_ptr<nil_test>& v2 = lua["v2"];
(void)(v2.get() == uptr.get());
}());
REQUIRE_THROWS([&]() {
sol::state lua;
lua["v3"] = rptr;
std::unique_ptr<nil_test>& v3 = lua["v3"];
(void)(v3.get() == rptr);
}());
REQUIRE_THROWS([&]() {
sol::state lua;
lua["v4"] = vptr;
std::unique_ptr<nil_test>& v4 = lua["v4"];
(void)(v4.get() == vptr);
}());
}
SECTION("throw shared") {
REQUIRE_THROWS([&]() {
sol::state lua;
lua["v1"] = sptr;
std::shared_ptr<nil_test>& v1 = lua["v1"];
(void)(v1.get() == sptr.get());
}());
REQUIRE_THROWS([&]() {
sol::state lua;
lua["v2"] = std::unique_ptr<nil_test>();
std::shared_ptr<nil_test>& v2 = lua["v2"];
(void)(v2.get() == uptr.get());
}());
REQUIRE_THROWS([&]() {
sol::state lua;
lua["v3"] = rptr;
std::shared_ptr<nil_test>& v3 = lua["v3"];
(void)(v3.get() == rptr);
}());
REQUIRE_THROWS([&]() {
sol::state lua;
lua["v4"] = vptr;
std::shared_ptr<nil_test>& v4 = lua["v4"];
(void)(v4.get() == vptr);
}());
}
}
TEST_CASE("functions/unique_usertype-overloading", "make sure overloading can work with ptr vs. specifically asking for a unique_usertype") {
struct test {
int special_value = 17;
test() : special_value(17) {}