Skip to content

Commit

Permalink
Fix #968, #969 (nice).
Browse files Browse the repository at this point in the history
  • Loading branch information
ThePhD committed May 22, 2020
1 parent d9c034d commit 465b472
Show file tree
Hide file tree
Showing 10 changed files with 226 additions and 229 deletions.
18 changes: 9 additions & 9 deletions include/sol/bind_traits.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,11 @@ namespace meta {
using first_type = meta::conditional_t<std::is_void<T>::value, int, T>&;

public:
static const bool is_noexcept = it_is_noexcept;
static const bool is_member_function = std::is_void<T>::value;
static const bool has_c_var_arg = has_c_variadic;
static const std::size_t arity = sizeof...(Args);
static const std::size_t free_arity = sizeof...(Args) + static_cast<std::size_t>(!std::is_void<T>::value);
inline static constexpr const bool is_noexcept = it_is_noexcept;
inline static constexpr bool is_member_function = std::is_void<T>::value;
inline static constexpr bool has_c_var_arg = has_c_variadic;
inline static constexpr std::size_t arity = sizeof...(Args);
inline static constexpr std::size_t free_arity = sizeof...(Args) + static_cast<std::size_t>(!std::is_void<T>::value);
typedef types<Args...> args_list;
typedef std::tuple<Args...> args_tuple;
typedef T object_type;
Expand Down Expand Up @@ -512,10 +512,10 @@ namespace meta {
typedef return_type Arg;
typedef T object_type;
using signature_type = R(T::*);
static const bool is_noexcept = false;
static const bool is_member_function = false;
static const std::size_t arity = 1;
static const std::size_t free_arity = 2;
inline static constexpr bool is_noexcept = false;
inline static constexpr bool is_member_function = false;
inline static constexpr std::size_t arity = 1;
inline static constexpr std::size_t free_arity = 2;
typedef std::tuple<Arg> args_tuple;
typedef types<Arg> args_list;
typedef types<T, Arg> free_args_list;
Expand Down
3 changes: 3 additions & 0 deletions include/sol/function_types.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,9 @@ namespace sol {
if constexpr (std::is_same_v<meta::unqualified_t<Arg0>, detail::yield_tag_t>) {
push<true>(L, std::forward<Args>(args)...);
}
else if constexpr (meta::is_specialization_of_v<meta::unqualified_t<Arg0>, yielding_t>) {
push<true>(L, std::forward<Arg0>(arg0).func, std::forward<Args>(args)...);
}
else {
push<false>(L, std::forward<Arg0>(arg0), std::forward<Args>(args)...);
}
Expand Down
5 changes: 3 additions & 2 deletions include/sol/function_types_stateless.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,14 @@

#include "stack.hpp"
#include "call.hpp"
#include "bind_traits.hpp"

namespace sol {
namespace function_detail {
template <typename Function, bool is_yielding>
struct upvalue_free_function {
typedef std::remove_pointer_t<std::decay_t<Function>> function_type;
typedef meta::bind_traits<function_type> traits_type;
using function_type = std::remove_pointer_t<std::decay_t<Function>>;
using traits_type = meta::bind_traits<function_type>;

static int real_call(lua_State* L) noexcept(traits_type::is_noexcept) {
auto udata = stack::stack_detail::get_as_upvalues<function_type*>(L);
Expand Down
74 changes: 36 additions & 38 deletions include/sol/load_result.hpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// sol3
// sol3

// The MIT License (MIT)

Expand Down Expand Up @@ -38,49 +38,14 @@ namespace sol {
int popcount;
load_status err;

template <typename T>
decltype(auto) tagged_get(types<optional<T>>) const {
if (!valid()) {
return optional<T>(nullopt);
}
return stack::get<optional<T>>(L, index);
}

template <typename T>
decltype(auto) tagged_get(types<T>) const {
#if defined(SOL_SAFE_PROXIES) && SOL_SAFE_PROXIES != 0
if (!valid()) {
type_panic_c_str(L, index, type_of(L, index), type::none);
}
#endif // Check Argument Safety
return stack::get<T>(L, index);
}

optional<error> tagged_get(types<optional<error>>) const {
if (valid()) {
return nullopt;
}
return error(detail::direct_error, stack::get<std::string>(L, index));
}

error tagged_get(types<error>) const {
#if defined(SOL_SAFE_PROXIES) && SOL_SAFE_PROXIES != 0
if (valid()) {
type_panic_c_str(L, index, type_of(L, index), type::none, "expecting an error type (a string, from Lua)");
}
#endif // Check Argument Safety
return error(detail::direct_error, stack::get<std::string>(L, index));
}

public:
load_result() = default;
load_result(lua_State* Ls, int stackindex = -1, int retnum = 0, int popnum = 0, load_status lerr = load_status::ok) noexcept
: L(Ls), index(stackindex), returncount(retnum), popcount(popnum), err(lerr) {
}
load_result(const load_result&) = default;
load_result& operator=(const load_result&) = default;
load_result(load_result&& o) noexcept
: L(o.L), index(o.index), returncount(o.returncount), popcount(o.popcount), err(o.err) {
load_result(load_result&& o) noexcept : L(o.L), index(o.index), returncount(o.returncount), popcount(o.popcount), err(o.err) {
// Must be manual, otherwise destructor will screw us
// return count being 0 is enough to keep things clean
// but we will be thorough
Expand Down Expand Up @@ -117,7 +82,40 @@ namespace sol {

template <typename T>
T get() const {
return tagged_get(types<meta::unqualified_t<T>>());
using UT = meta::unqualified_t<T>;
if constexpr (meta::is_optional_v<UT>) {
using ValueType = typename UT::value_type;
if constexpr (std::is_same_v<ValueType, error>) {
if (valid()) {
return UT(nullopt);
}
return error(detail::direct_error, stack::get<std::string>(L, index));
}
else {
if (!valid()) {
return UT(nullopt);
}
return stack::get<UT>(L, index);
}
}
else {
if constexpr (std::is_same_v<T, error>) {
#if defined(SOL_SAFE_PROXIES) && SOL_SAFE_PROXIES != 0
if (valid()) {
type_panic_c_str(L, index, type_of(L, index), type::none, "expecting an error type (a string, from Lua)");
}
#endif // Check proxy type's safety
return error(detail::direct_error, stack::get<std::string>(L, index));
}
else {
#if defined(SOL_SAFE_PROXIES) && SOL_SAFE_PROXIES != 0
if (!valid()) {
type_panic_c_str(L, index, type_of(L, index), type::none);
}
#endif // Check proxy type's safety
return stack::get<T>(L, index);
}
}
}

template <typename... Ret, typename... Args>
Expand Down
22 changes: 10 additions & 12 deletions include/sol/optional_implementation.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
#include <type_traits>
#include <utility>
#include <cstdlib>
#include <optional>

#if (defined(_MSC_VER) && _MSC_VER == 1900)
#define SOL_TL_OPTIONAL_MSVC2015
Expand Down Expand Up @@ -321,7 +322,7 @@ namespace sol {
struct is_swappable : std::integral_constant<bool,
decltype(detail::swap_adl_tests::can_swap<T, U>(0))::value
&& (!decltype(detail::swap_adl_tests::uses_std<T, U>(0))::value
|| (std::is_move_assignable<T>::value && std::is_move_constructible<T>::value))> {};
|| (std::is_move_assignable<T>::value && std::is_move_constructible<T>::value))> {};

template <class T, std::size_t N>
struct is_swappable<T[N], T[N]> : std::integral_constant<bool,
Expand All @@ -333,7 +334,7 @@ namespace sol {
: std::integral_constant<bool,
is_swappable<T, U>::value
&& ((decltype(detail::swap_adl_tests::uses_std<T, U>(0))::value&& detail::swap_adl_tests::is_std_swap_noexcept<T>::value)
|| (!decltype(detail::swap_adl_tests::uses_std<T, U>(0))::value&& detail::swap_adl_tests::is_adl_swap_noexcept<T, U>::value))> {};
|| (!decltype(detail::swap_adl_tests::uses_std<T, U>(0))::value&& detail::swap_adl_tests::is_adl_swap_noexcept<T, U>::value))> {};
#endif

// The storage base manages the actual storage, and correctly propagates
Expand Down Expand Up @@ -638,11 +639,8 @@ namespace sol {
} // namespace detail

/// \brief A tag type to represent an empty optional
struct nullopt_t {
struct do_not_use {};
constexpr explicit nullopt_t(do_not_use, do_not_use) noexcept {
}
};
using nullopt_t = std::nullopt_t;

/// \brief Represents an empty optional
/// \synopsis static constexpr nullopt_t nullopt;
///
Expand All @@ -652,7 +650,7 @@ namespace sol {
/// void foo (sol::optional<int>);
/// foo(sol::nullopt); //pass an empty optional
/// ```
static constexpr nullopt_t nullopt{ nullopt_t::do_not_use{}, nullopt_t::do_not_use{} };
using std::nullopt;

class bad_optional_access : public std::exception {
public:
Expand Down Expand Up @@ -1010,7 +1008,7 @@ namespace sol {
template <class U>
constexpr optional<typename std::decay<U>::type> conjunction(U&& u) const {
using result = optional<detail::decay_t<U>>;
return has_value() ? result{ u } : result{ nullopt };
return has_value() ? result { u } : result { nullopt };
}

/// \returns `rhs` if `*this` is empty, otherwise the current value.
Expand Down Expand Up @@ -1644,7 +1642,7 @@ namespace sol {
auto optional_map_impl(Opt&& opt, F&& f) {
if (opt.has_value()) {
detail::invoke(std::forward<F>(f), *std::forward<Opt>(opt));
return make_optional(monostate{});
return make_optional(monostate {});
}

return optional<monostate>(nullopt);
Expand All @@ -1663,7 +1661,7 @@ namespace sol {
auto optional_map_impl(Opt&& opt, F&& f) -> optional<monostate> {
if (opt.has_value()) {
detail::invoke(std::forward<F>(f), *std::forward<Opt>(opt));
return monostate{};
return monostate {};
}

return nullopt;
Expand Down Expand Up @@ -2027,7 +2025,7 @@ namespace sol {
template <class U>
constexpr optional<typename std::decay<U>::type> conjunction(U&& u) const {
using result = optional<detail::decay_t<U>>;
return has_value() ? result{ u } : result{ nullopt };
return has_value() ? result { u } : result { nullopt };
}

/// \returns `rhs` if `*this` is empty, otherwise the current value.
Expand Down
79 changes: 37 additions & 42 deletions include/sol/protected_function_result.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,47 +43,6 @@ namespace sol {
int popcount;
call_status err;

template <typename T>
decltype(auto) tagged_get(types<optional<T>>, int index_offset) const {
typedef decltype(stack::get<optional<T>>(L, index)) ret_t;
int target = index + index_offset;
if (!valid()) {
return ret_t(nullopt);
}
return stack::get<optional<T>>(L, target);
}

template <typename T>
decltype(auto) tagged_get(types<T>, int index_offset) const {
int target = index + index_offset;
#if defined(SOL_SAFE_PROXIES) && SOL_SAFE_PROXIES
if (!valid()) {
type t = type_of(L, target);
type_panic_c_str(L, target, t, type::none, "bad get from protected_function_result (is not an error)");
}
#endif // Check Argument Safety
return stack::get<T>(L, target);
}

optional<error> tagged_get(types<optional<error>>, int index_offset) const {
int target = index + index_offset;
if (valid()) {
return nullopt;
}
return error(detail::direct_error, stack::get<std::string>(L, target));
}

error tagged_get(types<error>, int index_offset) const {
int target = index + index_offset;
#if defined(SOL_SAFE_PROXIES) && SOL_SAFE_PROXIES
if (valid()) {
type t = type_of(L, target);
type_panic_c_str(L, target, t, type::none, "bad get from protected_function_result (is an error)");
}
#endif // Check Argument Safety
return error(detail::direct_error, stack::get<std::string>(L, target));
}

public:
typedef stack_proxy reference_type;
typedef stack_proxy value_type;
Expand Down Expand Up @@ -136,7 +95,43 @@ namespace sol {

template <typename T>
decltype(auto) get(int index_offset = 0) const {
return tagged_get(types<meta::unqualified_t<T>>(), index_offset);
using UT = meta::unqualified_t<T>;
int target = index + index_offset;
if constexpr (meta::is_optional_v<UT>) {
using ValueType = typename UT::value_type;
if constexpr (std::is_same_v<ValueType, error>) {
if (valid()) {
return UT(nullopt);
}
return UT(error(detail::direct_error, stack::get<std::string>(L, target)));
}
else {
if (!valid()) {
return UT();
}
return UT(stack::get<ValueType>(L, target));
}
}
else {
if constexpr (std::is_same_v<T, error>) {
#if defined(SOL_SAFE_PROXIES) && SOL_SAFE_PROXIES
if (valid()) {
type t = type_of(L, target);
type_panic_c_str(L, target, t, type::none, "bad get from protected_function_result (is an error)");
}
#endif // Check Argument Safety
return error(detail::direct_error, stack::get<std::string>(L, target));
}
else {
#if defined(SOL_SAFE_PROXIES) && SOL_SAFE_PROXIES
if (!valid()) {
type t = type_of(L, target);
type_panic_c_str(L, target, t, type::none, "bad get from protected_function_result (is not an error)");
}
#endif // Check Argument Safety
return stack::get<T>(L, target);
}
}
}

type get_type(int index_offset = 0) const noexcept {
Expand Down
Loading

0 comments on commit 465b472

Please sign in to comment.