mirror of
https://github.com/ThePhD/sol2.git
synced 2024-03-22 13:10:44 +08:00
Baby you construct me in all the right ways, let's spend our lifetimes together in this wonderful scope.~
Closes #168
This commit is contained in:
parent
7280668de7
commit
0338b7d18f
|
@ -20,8 +20,12 @@ members
|
||||||
template <typename T>
|
template <typename T>
|
||||||
object(T&&);
|
object(T&&);
|
||||||
object(lua_State* L, int index = -1);
|
object(lua_State* L, int index = -1);
|
||||||
|
template <typename T, typename... Args>
|
||||||
|
object(lua_State* L, in_place_t, T&& arg, Args&&... args);
|
||||||
|
template <typename T, typename... Args>
|
||||||
|
object(lua_State* L, in_place_type_t<T>, Args&&... args);
|
||||||
|
|
||||||
There are 2 kinds of constructors here. One allows construction of a object from other reference types such as :doc:`table<table>` and :doc:`stack_reference`. The other creates an object which references the specific element at the given index in the specified ``lua_State*``.
|
There are 4 kinds of constructors here. One allows construction of a object from other reference types such as :doc:`sol::table<table>` and :doc:`sol::stack_reference<stack_reference>`. The secon creates an object which references the specific element at the given index in the specified ``lua_State*``. The more advanced ``in_place...`` constructors create a single object by pushing the specified type ``T`` onto the stack and then setting it as the object. It gets popped from the stack afterwards (unless this is an instance of ``sol::stack_object``, in which case it is left on the stack).
|
||||||
|
|
||||||
.. code-block:: cpp
|
.. code-block:: cpp
|
||||||
:caption: function: type conversion
|
:caption: function: type conversion
|
||||||
|
|
|
@ -28,6 +28,27 @@
|
||||||
#include "variadic_args.hpp"
|
#include "variadic_args.hpp"
|
||||||
|
|
||||||
namespace sol {
|
namespace sol {
|
||||||
|
|
||||||
|
template <typename R = reference, bool should_pop = !std::is_base_of<stack_reference, R>::value, typename T>
|
||||||
|
R make_reference(lua_State* L, T&& value) {
|
||||||
|
int backpedal = stack::push(L, std::forward<T>(value));
|
||||||
|
R r = stack::get<R>(L, -backpedal);
|
||||||
|
if (should_pop) {
|
||||||
|
lua_pop(L, backpedal);
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, typename R = reference, bool should_pop = !std::is_base_of<stack_reference, R>::value, typename... Args>
|
||||||
|
R make_reference(lua_State* L, Args&&... args) {
|
||||||
|
int backpedal = stack::push<T>(L, std::forward<Args>(args)...);
|
||||||
|
R r = stack::get<R>(L, -backpedal);
|
||||||
|
if (should_pop) {
|
||||||
|
lua_pop(L, backpedal);
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
template <typename base_t>
|
template <typename base_t>
|
||||||
class basic_object : public base_t {
|
class basic_object : public base_t {
|
||||||
private:
|
private:
|
||||||
|
@ -52,6 +73,12 @@ namespace sol {
|
||||||
auto pp = stack::push_pop(*this);
|
auto pp = stack::push_pop(*this);
|
||||||
return stack::check<T>(base_t::lua_state(), -1, no_panic);
|
return stack::check<T>(base_t::lua_state(), -1, no_panic);
|
||||||
}
|
}
|
||||||
|
template <bool invert_and_pop = false>
|
||||||
|
basic_object(std::integral_constant<bool, invert_and_pop>, lua_State* L, int index = -1) noexcept : base_t(L, index) {
|
||||||
|
if (invert_and_pop) {
|
||||||
|
lua_pop(L, -index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
basic_object() noexcept = default;
|
basic_object() noexcept = default;
|
||||||
|
@ -65,6 +92,10 @@ namespace sol {
|
||||||
basic_object(const stack_reference& r) noexcept : basic_object(r.lua_state(), r.stack_index()) {}
|
basic_object(const stack_reference& r) noexcept : basic_object(r.lua_state(), r.stack_index()) {}
|
||||||
basic_object(stack_reference&& r) noexcept : basic_object(r.lua_state(), r.stack_index()) {}
|
basic_object(stack_reference&& r) noexcept : basic_object(r.lua_state(), r.stack_index()) {}
|
||||||
basic_object(lua_State* L, int index = -1) noexcept : base_t(L, index) {}
|
basic_object(lua_State* L, int index = -1) noexcept : base_t(L, index) {}
|
||||||
|
template <typename T, typename... Args>
|
||||||
|
basic_object(lua_State* L, in_place_type_t<T>, Args&&... args) noexcept : basic_object(std::integral_constant<bool, !std::is_base_of<stack_reference, base_t>::value>(), L, -stack::push<T>(L, std::forward<Args>(args)...)) {}
|
||||||
|
template <typename T, typename... Args>
|
||||||
|
basic_object(lua_State* L, in_place_t, T&& arg, Args&&... args) noexcept : basic_object(L, in_place<T>, std::forward<T>(arg), std::forward<Args>(args)...) {}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
decltype(auto) as() const {
|
decltype(auto) as() const {
|
||||||
|
@ -79,26 +110,6 @@ namespace sol {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename R = reference, bool should_pop = !std::is_base_of<stack_reference, R>::value, typename T>
|
|
||||||
R make_reference(lua_State* L, T&& value) {
|
|
||||||
int backpedal = stack::push(L, std::forward<T>(value));
|
|
||||||
R r = stack::get<R>(L, -backpedal);
|
|
||||||
if (should_pop) {
|
|
||||||
lua_pop(L, backpedal);
|
|
||||||
}
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T, typename R = reference, bool should_pop = !std::is_base_of<stack_reference, R>::value, typename... Args>
|
|
||||||
object make_reference(lua_State* L, Args&&... args) {
|
|
||||||
int backpedal = stack::push<T>(L, std::forward<Args>(args)...);
|
|
||||||
object r = stack::get<sol::object>(L, -backpedal);
|
|
||||||
if (should_pop) {
|
|
||||||
lua_pop(L, backpedal);
|
|
||||||
}
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
object make_object(lua_State* L, T&& value) {
|
object make_object(lua_State* L, T&& value) {
|
||||||
return make_reference<object, true>(L, std::forward<T>(value));
|
return make_reference<object, true>(L, std::forward<T>(value));
|
||||||
|
|
|
@ -22,28 +22,46 @@
|
||||||
#ifndef SOL_OPTIONAL_HPP
|
#ifndef SOL_OPTIONAL_HPP
|
||||||
#define SOL_OPTIONAL_HPP
|
#define SOL_OPTIONAL_HPP
|
||||||
|
|
||||||
#if __cplusplus > 201402L
|
#if defined(SOL_USE_BOOST)
|
||||||
#include <optional>
|
|
||||||
#elif defined(SOL_USE_BOOST)
|
|
||||||
#include <boost/optional.hpp>
|
#include <boost/optional.hpp>
|
||||||
#else
|
#else
|
||||||
#include "../Optional/optional.hpp"
|
#include "../Optional/optional.hpp"
|
||||||
#endif // C++ 14
|
#endif // Boost vs. Better optional
|
||||||
|
|
||||||
namespace sol {
|
namespace sol {
|
||||||
|
|
||||||
#if __cplusplus > 201402L
|
#if defined(SOL_USE_BOOST)
|
||||||
template <typename T>
|
|
||||||
using optional = sol::optional<T>;
|
|
||||||
using nullopt_t = std::nullopt_t;
|
|
||||||
constexpr nullopt_t nullopt = std::nullopt;
|
|
||||||
#elif defined(SOL_USE_BOOST)
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
using optional = boost::optional<T>;
|
using optional = boost::optional<T>;
|
||||||
using nullopt_t = boost::none_t;
|
using nullopt_t = boost::none_t;
|
||||||
const nullopt_t nullopt = boost::none;
|
const nullopt_t nullopt = boost::none;
|
||||||
#else
|
|
||||||
#endif // C++ 14
|
namespace detail {
|
||||||
}
|
struct in_place_of {};
|
||||||
|
} // 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()); }
|
||||||
|
using in_place_t = in_place_tag(&)(detail::in_place_of);
|
||||||
|
#endif // Boost vs. Better optional
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
template <std::size_t I>
|
||||||
|
struct in_place_of_i {};
|
||||||
|
template <typename T>
|
||||||
|
struct in_place_of_t {};
|
||||||
|
}
|
||||||
|
|
||||||
|
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()); }
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
#endif // SOL_OPTIONAL_HPP
|
#endif // SOL_OPTIONAL_HPP
|
||||||
|
|
|
@ -135,7 +135,7 @@ namespace sol {
|
||||||
}
|
}
|
||||||
|
|
||||||
// overload allows to use a pusher of a specific type, but pass in any kind of args
|
// overload allows to use a pusher of a specific type, but pass in any kind of args
|
||||||
template<typename T, typename Arg, typename... Args>
|
template<typename T, typename Arg, typename... Args, typename = std::enable_if_t<!std::is_same<T, Arg>::value>>
|
||||||
inline int push(lua_State* L, Arg&& arg, Args&&... args) {
|
inline int push(lua_State* L, Arg&& arg, Args&&... args) {
|
||||||
return pusher<meta::unqualified_t<T>>{}.push(L, std::forward<Arg>(arg), std::forward<Args>(args)...);
|
return pusher<meta::unqualified_t<T>>{}.push(L, std::forward<Arg>(arg), std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
|
|
|
@ -143,7 +143,7 @@ namespace sol {
|
||||||
tracking.use(1);
|
tracking.use(1);
|
||||||
std::size_t len;
|
std::size_t len;
|
||||||
auto str = lua_tolstring(L, index, &len);
|
auto str = lua_tolstring(L, index, &len);
|
||||||
return{ str, len };
|
return std::string( str, len );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -358,13 +358,18 @@ namespace sol {
|
||||||
lua_pushlstring(L, str, N - 1);
|
lua_pushlstring(L, str, N - 1);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int push(lua_State* L, const char(&str)[N], std::size_t sz) {
|
||||||
|
lua_pushlstring(L, str, sz);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct pusher<char> {
|
struct pusher<char> {
|
||||||
static int push(lua_State* L, char c) {
|
static int push(lua_State* L, char c) {
|
||||||
const char str[2] = { c, '\0' };
|
const char str[2] = { c, '\0' };
|
||||||
return stack::push(L, str);
|
return stack::push(L, str, 1);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -374,6 +379,11 @@ namespace sol {
|
||||||
lua_pushlstring(L, str.c_str(), str.size());
|
lua_pushlstring(L, str.c_str(), str.size());
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int push(lua_State* L, const std::string& str, std::size_t sz) {
|
||||||
|
lua_pushlstring(L, str.c_str(), sz);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
|
|
|
@ -92,3 +92,14 @@ TEST_CASE("detail/demangling", "test some basic demangling cases") {
|
||||||
REQUIRE(nsteststr == "ns_test");
|
REQUIRE(nsteststr == "ns_test");
|
||||||
REQUIRE(nsateststr == "ns_anon_test");
|
REQUIRE(nsateststr == "ns_anon_test");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("object/string-pushers", "test some basic string pushers with in_place constructor") {
|
||||||
|
sol::state lua;
|
||||||
|
|
||||||
|
sol::object ocs(lua, sol::in_place, "bark\0bark", 9);
|
||||||
|
sol::object os(lua, sol::in_place<std::string>, std::string("bark\0bark", 9), 8);
|
||||||
|
bool test1 = os.as<std::string>() == std::string("bark\0bar", 8);
|
||||||
|
bool test2 = ocs.as<std::string>() == std::string("bark\0bark", 9);
|
||||||
|
REQUIRE(test1);
|
||||||
|
REQUIRE(test2);
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user