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>
|
||||
object(T&&);
|
||||
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
|
||||
:caption: function: type conversion
|
||||
|
|
|
@ -28,6 +28,27 @@
|
|||
#include "variadic_args.hpp"
|
||||
|
||||
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>
|
||||
class basic_object : public base_t {
|
||||
private:
|
||||
|
@ -52,6 +73,12 @@ namespace sol {
|
|||
auto pp = stack::push_pop(*this);
|
||||
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:
|
||||
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(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) {}
|
||||
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>
|
||||
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>
|
||||
object make_object(lua_State* L, T&& value) {
|
||||
return make_reference<object, true>(L, std::forward<T>(value));
|
||||
|
|
|
@ -22,28 +22,46 @@
|
|||
#ifndef SOL_OPTIONAL_HPP
|
||||
#define SOL_OPTIONAL_HPP
|
||||
|
||||
#if __cplusplus > 201402L
|
||||
#include <optional>
|
||||
#elif defined(SOL_USE_BOOST)
|
||||
#if defined(SOL_USE_BOOST)
|
||||
#include <boost/optional.hpp>
|
||||
#else
|
||||
#include "../Optional/optional.hpp"
|
||||
#endif // C++ 14
|
||||
#endif // Boost vs. Better optional
|
||||
|
||||
namespace sol {
|
||||
|
||||
#if __cplusplus > 201402L
|
||||
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)
|
||||
#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;
|
||||
#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
|
||||
|
|
|
@ -135,7 +135,7 @@ namespace sol {
|
|||
}
|
||||
|
||||
// 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) {
|
||||
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);
|
||||
std::size_t 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);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int push(lua_State* L, const char(&str)[N], std::size_t sz) {
|
||||
lua_pushlstring(L, str, sz);
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct pusher<char> {
|
||||
static int push(lua_State* L, char c) {
|
||||
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());
|
||||
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<>
|
||||
|
|
|
@ -92,3 +92,14 @@ TEST_CASE("detail/demangling", "test some basic demangling cases") {
|
|||
REQUIRE(nsteststr == "ns_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