mirror of
https://github.com/ThePhD/sol2.git
synced 2024-03-22 13:10:44 +08:00
Improve unique_usertype handling to avoid needing the rebind_base typedef
This commit is contained in:
parent
d17f967e66
commit
6282ed4bf0
|
@ -29,14 +29,14 @@ This is a customization point for users who need to *work with special kinds of
|
||||||
typedef boost::shared_ptr<T> actual_type;
|
typedef boost::shared_ptr<T> actual_type;
|
||||||
static const bool value = true;
|
static const bool value = true;
|
||||||
|
|
||||||
static bool is_null(const actual_type& value) {
|
static bool is_null(const actual_type& ptr) {
|
||||||
return value == nullptr;
|
return ptr == nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static type* get (const actual_type& p) {
|
static type* get (const actual_type& ptr) {
|
||||||
return p.get();
|
return ptr.get();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
This will allow the library to properly handle ``boost::shared_ptr<T>``, with ref-counting and all. The ``type`` is the type that lua and sol will interact with, and will allow you to pull out a non-owning reference / pointer to the data when you just ask for a plain ``T*`` or ``T&`` or ``T`` using the getter functions and properties of Sol. The ``actual_type`` is just the "real type" that controls the semantics (shared, unique, ``CComPtr``, ``ComPtr``, OpenGL handles, DirectX objects, the list goes on).
|
This will allow the library to properly handle ``boost::shared_ptr<T>``, with ref-counting and all. The ``type`` is the type that lua and sol will interact with, and will allow you to pull out a non-owning reference / pointer to the data when you just ask for a plain ``T*`` or ``T&`` or ``T`` using the getter functions and properties of Sol. The ``actual_type`` is just the "real type" that controls the semantics (shared, unique, ``CComPtr``, ``ComPtr``, OpenGL handles, DirectX objects, the list goes on).
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
#include "trampoline.hpp"
|
#include "trampoline.hpp"
|
||||||
#include "filters.hpp"
|
#include "filters.hpp"
|
||||||
#include "stack.hpp"
|
#include "stack.hpp"
|
||||||
|
#include "unique_usertype_traits.hpp"
|
||||||
|
|
||||||
namespace sol {
|
namespace sol {
|
||||||
namespace u_detail {
|
namespace u_detail {
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
|
|
||||||
#include "types.hpp"
|
#include "types.hpp"
|
||||||
#include "usertype_traits.hpp"
|
#include "usertype_traits.hpp"
|
||||||
|
#include "unique_usertype_traits.hpp"
|
||||||
|
|
||||||
namespace sol {
|
namespace sol {
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
|
@ -108,8 +109,8 @@ namespace sol {
|
||||||
|
|
||||||
template <typename U, typename Base, typename... Args>
|
template <typename U, typename Base, typename... Args>
|
||||||
static int type_unique_cast_bases(types<Base, Args...>, void* source_data, void* target_data, const string_view& ti) {
|
static int type_unique_cast_bases(types<Base, Args...>, void* source_data, void* target_data, const string_view& ti) {
|
||||||
typedef unique_usertype_traits<U> uu_traits;
|
using uu_traits = unique_usertype_traits<U>;
|
||||||
typedef typename uu_traits::template rebind_base<Base> base_ptr;
|
using base_ptr = typename uu_traits::template rebind_base<Base>;
|
||||||
string_view base_ti = usertype_traits<Base>::qualified_name();
|
string_view base_ti = usertype_traits<Base>::qualified_name();
|
||||||
if (base_ti == ti) {
|
if (base_ti == ti) {
|
||||||
if (target_data != nullptr) {
|
if (target_data != nullptr) {
|
||||||
|
@ -126,6 +127,7 @@ namespace sol {
|
||||||
template <typename U>
|
template <typename U>
|
||||||
static int type_unique_cast(void* source_data, void* target_data, const string_view& ti, const string_view& rebind_ti) {
|
static int type_unique_cast(void* source_data, void* target_data, const string_view& ti, const string_view& rebind_ti) {
|
||||||
typedef unique_usertype_traits<U> uu_traits;
|
typedef unique_usertype_traits<U> uu_traits;
|
||||||
|
if constexpr (is_base_rebindable_v<uu_traits>) {
|
||||||
typedef typename uu_traits::template rebind_base<void> rebind_t;
|
typedef typename uu_traits::template rebind_base<void> rebind_t;
|
||||||
typedef meta::conditional_t<std::is_void<rebind_t>::value, types<>, bases_t> cond_bases_t;
|
typedef meta::conditional_t<std::is_void<rebind_t>::value, types<>, bases_t> cond_bases_t;
|
||||||
string_view this_rebind_ti = usertype_traits<rebind_t>::qualified_name();
|
string_view this_rebind_ti = usertype_traits<rebind_t>::qualified_name();
|
||||||
|
@ -140,13 +142,24 @@ namespace sol {
|
||||||
}
|
}
|
||||||
return type_unique_cast_bases<U>(cond_bases_t(), source_data, target_data, ti);
|
return type_unique_cast_bases<U>(cond_bases_t(), source_data, target_data, ti);
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
(void)rebind_ti;
|
||||||
|
string_view this_ti = usertype_traits<T>::qualified_name();
|
||||||
|
if (ti == this_ti) {
|
||||||
|
// direct match, return 1
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return type_unique_cast_bases<U>(types<>(), source_data, target_data, ti);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
template <typename U, typename... Bases>
|
template <typename U, typename... Bases>
|
||||||
static int type_unique_cast_with(void* source_data, void* target_data, const string_view& ti, const string_view& rebind_ti) {
|
static int type_unique_cast_with(void* source_data, void* target_data, const string_view& ti, const string_view& rebind_ti) {
|
||||||
using uc_bases_t = types<Bases...>;
|
using uc_bases_t = types<Bases...>;
|
||||||
typedef unique_usertype_traits<U> uu_traits;
|
typedef unique_usertype_traits<U> uu_traits;
|
||||||
typedef typename uu_traits::template rebind_base<void> rebind_t;
|
if constexpr (is_base_rebindable_v<uu_traits>) {
|
||||||
typedef meta::conditional_t<std::is_void<rebind_t>::value, types<>, uc_bases_t> cond_bases_t;
|
using rebind_t = typename uu_traits::template rebind_base<void>;
|
||||||
|
using cond_bases_t = meta::conditional_t<std::is_void<rebind_t>::value, types<>, uc_bases_t>;
|
||||||
string_view this_rebind_ti = usertype_traits<rebind_t>::qualified_name();
|
string_view this_rebind_ti = usertype_traits<rebind_t>::qualified_name();
|
||||||
if (rebind_ti != this_rebind_ti) {
|
if (rebind_ti != this_rebind_ti) {
|
||||||
// this is not even of the same unique type
|
// this is not even of the same unique type
|
||||||
|
@ -159,6 +172,16 @@ namespace sol {
|
||||||
}
|
}
|
||||||
return type_unique_cast_bases<U>(cond_bases_t(), source_data, target_data, ti);
|
return type_unique_cast_bases<U>(cond_bases_t(), source_data, target_data, ti);
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
(void)rebind_ti;
|
||||||
|
string_view this_ti = usertype_traits<T>::qualified_name();
|
||||||
|
if (ti == this_ti) {
|
||||||
|
// direct match, return 1
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return type_unique_cast_bases<U>(types<>(), source_data, target_data, ti);
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
using inheritance_check_function = decltype(&inheritance<void>::type_check);
|
using inheritance_check_function = decltype(&inheritance<void>::type_check);
|
||||||
|
|
|
@ -33,6 +33,9 @@
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#if defined(SOL_CXX17_FEATURES) && SOL_CXX17_FEATURES
|
#if defined(SOL_CXX17_FEATURES) && SOL_CXX17_FEATURES
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
#if defined(SOL_STD_VARIANT) && SOL_STD_VARIANT
|
||||||
|
#include <variant>
|
||||||
|
#endif // variant
|
||||||
#endif // C++17
|
#endif // C++17
|
||||||
|
|
||||||
|
|
||||||
|
@ -146,8 +149,8 @@ namespace stack {
|
||||||
};
|
};
|
||||||
|
|
||||||
#if defined(SOL_STD_VARIANT) && SOL_STD_VARIANT
|
#if defined(SOL_STD_VARIANT) && SOL_STD_VARIANT
|
||||||
template <typename... Tn>
|
template <typename... Tn, typename C>
|
||||||
struct unqualified_check_getter<std::variant<Tn...>> {
|
struct unqualified_check_getter<std::variant<Tn...>, C> {
|
||||||
typedef std::variant<Tn...> V;
|
typedef std::variant<Tn...> V;
|
||||||
typedef std::variant_size<V> V_size;
|
typedef std::variant_size<V> V_size;
|
||||||
typedef std::integral_constant<bool, V_size::value == 0> V_is_empty;
|
typedef std::integral_constant<bool, V_size::value == 0> V_is_empty;
|
||||||
|
|
|
@ -174,12 +174,10 @@ namespace sol { namespace stack {
|
||||||
return stack_detail::unchecked_unqualified_get<sol::nested<Tu>>(L, index, tracking);
|
return stack_detail::unchecked_unqualified_get<sol::nested<Tu>>(L, index, tracking);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if constexpr (!std::is_reference_v<
|
else if constexpr (!std::is_reference_v<X> && is_unique_usertype_v<Tu> && !is_base_rebindable_non_void_v<unique_usertype_traits<Tu>>) {
|
||||||
X> && is_unique_usertype_v<Tu> && !std::is_void_v<typename unique_usertype_traits<Tu>::template rebind_base<void>>) {
|
|
||||||
using u_traits = unique_usertype_traits<Tu>;
|
using u_traits = unique_usertype_traits<Tu>;
|
||||||
using T = typename u_traits::type;
|
using T = typename u_traits::type;
|
||||||
using Real = typename u_traits::actual_type;
|
using Real = typename u_traits::actual_type;
|
||||||
using rebind_t = typename u_traits::template rebind_base<void>;
|
|
||||||
tracking.use(1);
|
tracking.use(1);
|
||||||
void* memory = lua_touserdata(L, index);
|
void* memory = lua_touserdata(L, index);
|
||||||
memory = detail::align_usertype_unique_destructor(memory);
|
memory = detail::align_usertype_unique_destructor(memory);
|
||||||
|
@ -193,15 +191,23 @@ namespace sol { namespace stack {
|
||||||
Real r(nullptr);
|
Real r(nullptr);
|
||||||
if constexpr (!derive<T>::value) {
|
if constexpr (!derive<T>::value) {
|
||||||
// TODO: abort / terminate, maybe only in debug modes?
|
// TODO: abort / terminate, maybe only in debug modes?
|
||||||
return static_cast<Real>(r);
|
return static_cast<Real>(std::move(r));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
memory = detail::align_usertype_unique_tag<true, false>(memory);
|
memory = detail::align_usertype_unique_tag<true, false>(memory);
|
||||||
detail::unique_tag& ic = *reinterpret_cast<detail::unique_tag*>(memory);
|
detail::unique_tag& ic = *reinterpret_cast<detail::unique_tag*>(memory);
|
||||||
memory = detail::align_usertype_unique<Real, true, false>(memory);
|
memory = detail::align_usertype_unique<Real, true, false>(memory);
|
||||||
string_view ti = usertype_traits<T>::qualified_name();
|
string_view ti = usertype_traits<T>::qualified_name();
|
||||||
|
int cast_operation;
|
||||||
|
if constexpr (is_base_rebindable_v<u_traits>) {
|
||||||
|
using rebind_t = typename u_traits::template rebind_base<void>;
|
||||||
string_view rebind_ti = usertype_traits<rebind_t>::qualified_name();
|
string_view rebind_ti = usertype_traits<rebind_t>::qualified_name();
|
||||||
int cast_operation = ic(memory, &r, ti, rebind_ti);
|
cast_operation = ic(memory, &r, ti, rebind_ti);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
string_view rebind_ti("");
|
||||||
|
cast_operation = ic(memory, &r, ti, rebind_ti);
|
||||||
|
}
|
||||||
switch (cast_operation) {
|
switch (cast_operation) {
|
||||||
case 1: {
|
case 1: {
|
||||||
// it's a perfect match,
|
// it's a perfect match,
|
||||||
|
@ -974,8 +980,6 @@ namespace sol { namespace stack {
|
||||||
};
|
};
|
||||||
|
|
||||||
#if defined(SOL_CXX17_FEATURES) && SOL_CXX17_FEATURES
|
#if defined(SOL_CXX17_FEATURES) && SOL_CXX17_FEATURES
|
||||||
|
|
||||||
|
|
||||||
#if defined(SOL_STD_VARIANT) && SOL_STD_VARIANT
|
#if defined(SOL_STD_VARIANT) && SOL_STD_VARIANT
|
||||||
template <typename... Tn>
|
template <typename... Tn>
|
||||||
struct unqualified_getter<std::variant<Tn...>> {
|
struct unqualified_getter<std::variant<Tn...>> {
|
||||||
|
@ -1012,6 +1016,7 @@ namespace sol { namespace stack {
|
||||||
};
|
};
|
||||||
#endif // SOL_STD_VARIANT
|
#endif // SOL_STD_VARIANT
|
||||||
#endif // SOL_CXX17_FEATURES
|
#endif // SOL_CXX17_FEATURES
|
||||||
|
|
||||||
}} // namespace sol::stack
|
}} // namespace sol::stack
|
||||||
|
|
||||||
#endif // SOL_STACK_UNQUALIFIED_GET_HPP
|
#endif // SOL_STACK_UNQUALIFIED_GET_HPP
|
||||||
|
|
|
@ -196,7 +196,6 @@ namespace sol {
|
||||||
using u_traits = unique_usertype_traits<T>;
|
using u_traits = unique_usertype_traits<T>;
|
||||||
using P = typename u_traits::type;
|
using P = typename u_traits::type;
|
||||||
using Real = typename u_traits::actual_type;
|
using Real = typename u_traits::actual_type;
|
||||||
using rebind_t = typename u_traits::template rebind_base<void>;
|
|
||||||
|
|
||||||
template <typename Arg, typename... Args>
|
template <typename Arg, typename... Args>
|
||||||
static int push(lua_State* L, Arg&& arg, Args&&... args) {
|
static int push(lua_State* L, Arg&& arg, Args&&... args) {
|
||||||
|
|
|
@ -148,65 +148,6 @@ namespace sol {
|
||||||
|
|
||||||
typedef std::remove_pointer_t<lua_CFunction> lua_CFunction_ref;
|
typedef std::remove_pointer_t<lua_CFunction> lua_CFunction_ref;
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct unique_usertype_traits {
|
|
||||||
typedef T type;
|
|
||||||
typedef T actual_type;
|
|
||||||
template <typename X>
|
|
||||||
using rebind_base = void;
|
|
||||||
|
|
||||||
static const bool value = false;
|
|
||||||
|
|
||||||
template <typename U>
|
|
||||||
static bool is_null(U&&) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename U>
|
|
||||||
static auto get(U&& value) {
|
|
||||||
return std::addressof(detail::deref(value));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct unique_usertype_traits<std::shared_ptr<T>> {
|
|
||||||
typedef T type;
|
|
||||||
typedef std::shared_ptr<T> actual_type;
|
|
||||||
// rebind is non-void
|
|
||||||
// if and only if unique usertype
|
|
||||||
// is cast-capable
|
|
||||||
template <typename X>
|
|
||||||
using rebind_base = std::shared_ptr<X>;
|
|
||||||
|
|
||||||
static const bool value = true;
|
|
||||||
|
|
||||||
static bool is_null(const actual_type& p) {
|
|
||||||
return p == nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
static type* get(const actual_type& p) {
|
|
||||||
return p.get();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T, typename D>
|
|
||||||
struct unique_usertype_traits<std::unique_ptr<T, D>> {
|
|
||||||
typedef T type;
|
|
||||||
typedef std::unique_ptr<T, D> actual_type;
|
|
||||||
template <typename X>
|
|
||||||
using rebind_base = void;
|
|
||||||
|
|
||||||
static const bool value = true;
|
|
||||||
|
|
||||||
static bool is_null(const actual_type& p) {
|
|
||||||
return p == nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
static type* get(const actual_type& p) {
|
|
||||||
return p.get();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct non_null {};
|
struct non_null {};
|
||||||
|
|
||||||
|
@ -1176,12 +1117,6 @@ namespace sol {
|
||||||
struct accumulate_list<C, v, V, types<Args...>> : accumulate<C, v, V, Args...> {};
|
struct accumulate_list<C, v, V, types<Args...>> : accumulate<C, v, V, Args...> {};
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct is_unique_usertype : std::integral_constant<bool, unique_usertype_traits<T>::value> {};
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
inline constexpr bool is_unique_usertype_v = is_unique_usertype<T>::value;
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct lua_type_of : detail::lua_type_of<T> {
|
struct lua_type_of : detail::lua_type_of<T> {
|
||||||
typedef int SOL_INTERNAL_UNSPECIALIZED_MARKER_;
|
typedef int SOL_INTERNAL_UNSPECIALIZED_MARKER_;
|
||||||
|
|
124
include/sol/unique_usertype_traits.hpp
Normal file
124
include/sol/unique_usertype_traits.hpp
Normal file
|
@ -0,0 +1,124 @@
|
||||||
|
// sol3
|
||||||
|
|
||||||
|
// The MIT License (MIT)
|
||||||
|
|
||||||
|
// Copyright (c) 2013-2019 Rapptz, ThePhD and contributors
|
||||||
|
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
// this software and associated documentation files (the "Software"), to deal in
|
||||||
|
// the Software without restriction, including without limitation the rights to
|
||||||
|
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
// the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
// subject to the following conditions:
|
||||||
|
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
#ifndef SOL_UNIQUE_USERTYPE_TRAITS_HPP
|
||||||
|
#define SOL_UNIQUE_USERTYPE_TRAITS_HPP
|
||||||
|
|
||||||
|
#include "base_traits.hpp"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
namespace sol {
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct unique_usertype_traits {
|
||||||
|
typedef T type;
|
||||||
|
typedef T actual_type;
|
||||||
|
template <typename X>
|
||||||
|
using rebind_base = void;
|
||||||
|
|
||||||
|
static const bool value = false;
|
||||||
|
|
||||||
|
template <typename U>
|
||||||
|
static bool is_null(U&&) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename U>
|
||||||
|
static auto get(U&& value) {
|
||||||
|
return std::addressof(detail::deref(value));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct unique_usertype_traits<std::shared_ptr<T>> {
|
||||||
|
typedef T type;
|
||||||
|
typedef std::shared_ptr<T> actual_type;
|
||||||
|
// rebind is non-void
|
||||||
|
// if and only if unique usertype
|
||||||
|
// is cast-capable
|
||||||
|
template <typename X>
|
||||||
|
using rebind_base = std::shared_ptr<X>;
|
||||||
|
|
||||||
|
static const bool value = true;
|
||||||
|
|
||||||
|
static bool is_null(const actual_type& p) {
|
||||||
|
return p == nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static type* get(const actual_type& p) {
|
||||||
|
return p.get();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T, typename D>
|
||||||
|
struct unique_usertype_traits<std::unique_ptr<T, D>> {
|
||||||
|
using type = T;
|
||||||
|
using actual_type = std::unique_ptr<T, D>;
|
||||||
|
|
||||||
|
static const bool value = true;
|
||||||
|
|
||||||
|
static bool is_null(const actual_type& p) {
|
||||||
|
return p == nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static type* get(const actual_type& p) {
|
||||||
|
return p.get();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct is_unique_usertype : std::integral_constant<bool, unique_usertype_traits<T>::value> {};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline constexpr bool is_unique_usertype_v = is_unique_usertype<T>::value;
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
template <typename T>
|
||||||
|
using is_base_rebindable_test = decltype(T::rebind_base);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
using is_base_rebindable = meta::is_detected<detail::is_base_rebindable_test, T>;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline constexpr bool is_base_rebindable_v = is_base_rebindable<T>::value;
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
template <typename T, typename>
|
||||||
|
struct is_base_rebindable_non_void_sfinae : std::false_type {};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct is_base_rebindable_non_void_sfinae<T, std::enable_if_t<is_base_rebindable_v<T>>>
|
||||||
|
: std::integral_constant<bool, !std::is_void_v<typename T::template rebind_base<void>>> {};
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
using is_base_rebindable_non_void = meta::is_detected<detail::is_base_rebindable_test, T>;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline constexpr bool is_base_rebindable_non_void_v = is_base_rebindable_non_void<T>::value;
|
||||||
|
|
||||||
|
} // namespace sol
|
||||||
|
|
||||||
|
#endif // SOL_UNIQUE_USERTYPE_TRAITS_HPP
|
|
@ -20,8 +20,8 @@
|
||||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
// This file was generated with a script.
|
// This file was generated with a script.
|
||||||
// Generated 2019-04-08 03:11:15.372045 UTC
|
// Generated 2019-04-13 08:04:51.418277 UTC
|
||||||
// This header was generated with sol v3.0.1-beta2 (revision 7cce3e4)
|
// This header was generated with sol v3.0.1-beta2 (revision d17f967)
|
||||||
// https://github.com/ThePhD/sol2
|
// https://github.com/ThePhD/sol2
|
||||||
|
|
||||||
#ifndef SOL_SINGLE_INCLUDE_FORWARD_HPP
|
#ifndef SOL_SINGLE_INCLUDE_FORWARD_HPP
|
||||||
|
|
|
@ -20,8 +20,8 @@
|
||||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
// This file was generated with a script.
|
// This file was generated with a script.
|
||||||
// Generated 2019-04-08 03:11:10.821035 UTC
|
// Generated 2019-04-13 08:04:48.327520 UTC
|
||||||
// This header was generated with sol v3.0.1-beta2 (revision 7cce3e4)
|
// This header was generated with sol v3.0.1-beta2 (revision d17f967)
|
||||||
// https://github.com/ThePhD/sol2
|
// https://github.com/ThePhD/sol2
|
||||||
|
|
||||||
#ifndef SOL_SINGLE_INCLUDE_HPP
|
#ifndef SOL_SINGLE_INCLUDE_HPP
|
||||||
|
@ -6276,65 +6276,6 @@ namespace sol {
|
||||||
|
|
||||||
typedef std::remove_pointer_t<lua_CFunction> lua_CFunction_ref;
|
typedef std::remove_pointer_t<lua_CFunction> lua_CFunction_ref;
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct unique_usertype_traits {
|
|
||||||
typedef T type;
|
|
||||||
typedef T actual_type;
|
|
||||||
template <typename X>
|
|
||||||
using rebind_base = void;
|
|
||||||
|
|
||||||
static const bool value = false;
|
|
||||||
|
|
||||||
template <typename U>
|
|
||||||
static bool is_null(U&&) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename U>
|
|
||||||
static auto get(U&& value) {
|
|
||||||
return std::addressof(detail::deref(value));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct unique_usertype_traits<std::shared_ptr<T>> {
|
|
||||||
typedef T type;
|
|
||||||
typedef std::shared_ptr<T> actual_type;
|
|
||||||
// rebind is non-void
|
|
||||||
// if and only if unique usertype
|
|
||||||
// is cast-capable
|
|
||||||
template <typename X>
|
|
||||||
using rebind_base = std::shared_ptr<X>;
|
|
||||||
|
|
||||||
static const bool value = true;
|
|
||||||
|
|
||||||
static bool is_null(const actual_type& p) {
|
|
||||||
return p == nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
static type* get(const actual_type& p) {
|
|
||||||
return p.get();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T, typename D>
|
|
||||||
struct unique_usertype_traits<std::unique_ptr<T, D>> {
|
|
||||||
typedef T type;
|
|
||||||
typedef std::unique_ptr<T, D> actual_type;
|
|
||||||
template <typename X>
|
|
||||||
using rebind_base = void;
|
|
||||||
|
|
||||||
static const bool value = true;
|
|
||||||
|
|
||||||
static bool is_null(const actual_type& p) {
|
|
||||||
return p == nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
static type* get(const actual_type& p) {
|
|
||||||
return p.get();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct non_null {};
|
struct non_null {};
|
||||||
|
|
||||||
|
@ -7304,12 +7245,6 @@ namespace sol {
|
||||||
struct accumulate_list<C, v, V, types<Args...>> : accumulate<C, v, V, Args...> {};
|
struct accumulate_list<C, v, V, types<Args...>> : accumulate<C, v, V, Args...> {};
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct is_unique_usertype : std::integral_constant<bool, unique_usertype_traits<T>::value> {};
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
inline constexpr bool is_unique_usertype_v = is_unique_usertype<T>::value;
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct lua_type_of : detail::lua_type_of<T> {
|
struct lua_type_of : detail::lua_type_of<T> {
|
||||||
typedef int SOL_INTERNAL_UNSPECIALIZED_MARKER_;
|
typedef int SOL_INTERNAL_UNSPECIALIZED_MARKER_;
|
||||||
|
@ -7923,6 +7858,103 @@ namespace sol {
|
||||||
|
|
||||||
// end of sol/usertype_traits.hpp
|
// end of sol/usertype_traits.hpp
|
||||||
|
|
||||||
|
// beginning of sol/unique_usertype_traits.hpp
|
||||||
|
|
||||||
|
namespace sol {
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct unique_usertype_traits {
|
||||||
|
typedef T type;
|
||||||
|
typedef T actual_type;
|
||||||
|
template <typename X>
|
||||||
|
using rebind_base = void;
|
||||||
|
|
||||||
|
static const bool value = false;
|
||||||
|
|
||||||
|
template <typename U>
|
||||||
|
static bool is_null(U&&) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename U>
|
||||||
|
static auto get(U&& value) {
|
||||||
|
return std::addressof(detail::deref(value));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct unique_usertype_traits<std::shared_ptr<T>> {
|
||||||
|
typedef T type;
|
||||||
|
typedef std::shared_ptr<T> actual_type;
|
||||||
|
// rebind is non-void
|
||||||
|
// if and only if unique usertype
|
||||||
|
// is cast-capable
|
||||||
|
template <typename X>
|
||||||
|
using rebind_base = std::shared_ptr<X>;
|
||||||
|
|
||||||
|
static const bool value = true;
|
||||||
|
|
||||||
|
static bool is_null(const actual_type& p) {
|
||||||
|
return p == nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static type* get(const actual_type& p) {
|
||||||
|
return p.get();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T, typename D>
|
||||||
|
struct unique_usertype_traits<std::unique_ptr<T, D>> {
|
||||||
|
using type = T;
|
||||||
|
using actual_type = std::unique_ptr<T, D>;
|
||||||
|
|
||||||
|
static const bool value = true;
|
||||||
|
|
||||||
|
static bool is_null(const actual_type& p) {
|
||||||
|
return p == nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static type* get(const actual_type& p) {
|
||||||
|
return p.get();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct is_unique_usertype : std::integral_constant<bool, unique_usertype_traits<T>::value> {};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline constexpr bool is_unique_usertype_v = is_unique_usertype<T>::value;
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
template <typename T>
|
||||||
|
using is_base_rebindable_test = decltype(T::rebind_base);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
using is_base_rebindable = meta::is_detected<detail::is_base_rebindable_test, T>;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline constexpr bool is_base_rebindable_v = is_base_rebindable<T>::value;
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
template <typename T, typename>
|
||||||
|
struct is_base_rebindable_non_void_sfinae : std::false_type {};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct is_base_rebindable_non_void_sfinae<T, std::enable_if_t<is_base_rebindable_v<T>>>
|
||||||
|
: std::integral_constant<bool, !std::is_void_v<typename T::template rebind_base<void>>> {};
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
using is_base_rebindable_non_void = meta::is_detected<detail::is_base_rebindable_test, T>;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline constexpr bool is_base_rebindable_non_void_v = is_base_rebindable_non_void<T>::value;
|
||||||
|
|
||||||
|
} // namespace sol
|
||||||
|
|
||||||
|
// end of sol/unique_usertype_traits.hpp
|
||||||
|
|
||||||
namespace sol {
|
namespace sol {
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
struct base_list {};
|
struct base_list {};
|
||||||
|
@ -8004,8 +8036,8 @@ namespace sol {
|
||||||
|
|
||||||
template <typename U, typename Base, typename... Args>
|
template <typename U, typename Base, typename... Args>
|
||||||
static int type_unique_cast_bases(types<Base, Args...>, void* source_data, void* target_data, const string_view& ti) {
|
static int type_unique_cast_bases(types<Base, Args...>, void* source_data, void* target_data, const string_view& ti) {
|
||||||
typedef unique_usertype_traits<U> uu_traits;
|
using uu_traits = unique_usertype_traits<U>;
|
||||||
typedef typename uu_traits::template rebind_base<Base> base_ptr;
|
using base_ptr = typename uu_traits::template rebind_base<Base>;
|
||||||
string_view base_ti = usertype_traits<Base>::qualified_name();
|
string_view base_ti = usertype_traits<Base>::qualified_name();
|
||||||
if (base_ti == ti) {
|
if (base_ti == ti) {
|
||||||
if (target_data != nullptr) {
|
if (target_data != nullptr) {
|
||||||
|
@ -8022,6 +8054,7 @@ namespace sol {
|
||||||
template <typename U>
|
template <typename U>
|
||||||
static int type_unique_cast(void* source_data, void* target_data, const string_view& ti, const string_view& rebind_ti) {
|
static int type_unique_cast(void* source_data, void* target_data, const string_view& ti, const string_view& rebind_ti) {
|
||||||
typedef unique_usertype_traits<U> uu_traits;
|
typedef unique_usertype_traits<U> uu_traits;
|
||||||
|
if constexpr (is_base_rebindable_v<uu_traits>) {
|
||||||
typedef typename uu_traits::template rebind_base<void> rebind_t;
|
typedef typename uu_traits::template rebind_base<void> rebind_t;
|
||||||
typedef meta::conditional_t<std::is_void<rebind_t>::value, types<>, bases_t> cond_bases_t;
|
typedef meta::conditional_t<std::is_void<rebind_t>::value, types<>, bases_t> cond_bases_t;
|
||||||
string_view this_rebind_ti = usertype_traits<rebind_t>::qualified_name();
|
string_view this_rebind_ti = usertype_traits<rebind_t>::qualified_name();
|
||||||
|
@ -8036,13 +8069,24 @@ namespace sol {
|
||||||
}
|
}
|
||||||
return type_unique_cast_bases<U>(cond_bases_t(), source_data, target_data, ti);
|
return type_unique_cast_bases<U>(cond_bases_t(), source_data, target_data, ti);
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
(void)rebind_ti;
|
||||||
|
string_view this_ti = usertype_traits<T>::qualified_name();
|
||||||
|
if (ti == this_ti) {
|
||||||
|
// direct match, return 1
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return type_unique_cast_bases<U>(types<>(), source_data, target_data, ti);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
template <typename U, typename... Bases>
|
template <typename U, typename... Bases>
|
||||||
static int type_unique_cast_with(void* source_data, void* target_data, const string_view& ti, const string_view& rebind_ti) {
|
static int type_unique_cast_with(void* source_data, void* target_data, const string_view& ti, const string_view& rebind_ti) {
|
||||||
using uc_bases_t = types<Bases...>;
|
using uc_bases_t = types<Bases...>;
|
||||||
typedef unique_usertype_traits<U> uu_traits;
|
typedef unique_usertype_traits<U> uu_traits;
|
||||||
typedef typename uu_traits::template rebind_base<void> rebind_t;
|
if constexpr (is_base_rebindable_v<uu_traits>) {
|
||||||
typedef meta::conditional_t<std::is_void<rebind_t>::value, types<>, uc_bases_t> cond_bases_t;
|
using rebind_t = typename uu_traits::template rebind_base<void>;
|
||||||
|
using cond_bases_t = meta::conditional_t<std::is_void<rebind_t>::value, types<>, uc_bases_t>;
|
||||||
string_view this_rebind_ti = usertype_traits<rebind_t>::qualified_name();
|
string_view this_rebind_ti = usertype_traits<rebind_t>::qualified_name();
|
||||||
if (rebind_ti != this_rebind_ti) {
|
if (rebind_ti != this_rebind_ti) {
|
||||||
// this is not even of the same unique type
|
// this is not even of the same unique type
|
||||||
|
@ -8055,6 +8099,16 @@ namespace sol {
|
||||||
}
|
}
|
||||||
return type_unique_cast_bases<U>(cond_bases_t(), source_data, target_data, ti);
|
return type_unique_cast_bases<U>(cond_bases_t(), source_data, target_data, ti);
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
(void)rebind_ti;
|
||||||
|
string_view this_ti = usertype_traits<T>::qualified_name();
|
||||||
|
if (ti == this_ti) {
|
||||||
|
// direct match, return 1
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return type_unique_cast_bases<U>(types<>(), source_data, target_data, ti);
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
using inheritance_check_function = decltype(&inheritance<void>::type_check);
|
using inheritance_check_function = decltype(&inheritance<void>::type_check);
|
||||||
|
@ -11548,12 +11602,10 @@ namespace sol { namespace stack {
|
||||||
return stack_detail::unchecked_unqualified_get<sol::nested<Tu>>(L, index, tracking);
|
return stack_detail::unchecked_unqualified_get<sol::nested<Tu>>(L, index, tracking);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if constexpr (!std::is_reference_v<
|
else if constexpr (!std::is_reference_v<X> && is_unique_usertype_v<Tu> && !is_base_rebindable_non_void_v<unique_usertype_traits<Tu>>) {
|
||||||
X> && is_unique_usertype_v<Tu> && !std::is_void_v<typename unique_usertype_traits<Tu>::template rebind_base<void>>) {
|
|
||||||
using u_traits = unique_usertype_traits<Tu>;
|
using u_traits = unique_usertype_traits<Tu>;
|
||||||
using T = typename u_traits::type;
|
using T = typename u_traits::type;
|
||||||
using Real = typename u_traits::actual_type;
|
using Real = typename u_traits::actual_type;
|
||||||
using rebind_t = typename u_traits::template rebind_base<void>;
|
|
||||||
tracking.use(1);
|
tracking.use(1);
|
||||||
void* memory = lua_touserdata(L, index);
|
void* memory = lua_touserdata(L, index);
|
||||||
memory = detail::align_usertype_unique_destructor(memory);
|
memory = detail::align_usertype_unique_destructor(memory);
|
||||||
|
@ -11567,15 +11619,23 @@ namespace sol { namespace stack {
|
||||||
Real r(nullptr);
|
Real r(nullptr);
|
||||||
if constexpr (!derive<T>::value) {
|
if constexpr (!derive<T>::value) {
|
||||||
// TODO: abort / terminate, maybe only in debug modes?
|
// TODO: abort / terminate, maybe only in debug modes?
|
||||||
return static_cast<Real>(r);
|
return static_cast<Real>(std::move(r));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
memory = detail::align_usertype_unique_tag<true, false>(memory);
|
memory = detail::align_usertype_unique_tag<true, false>(memory);
|
||||||
detail::unique_tag& ic = *reinterpret_cast<detail::unique_tag*>(memory);
|
detail::unique_tag& ic = *reinterpret_cast<detail::unique_tag*>(memory);
|
||||||
memory = detail::align_usertype_unique<Real, true, false>(memory);
|
memory = detail::align_usertype_unique<Real, true, false>(memory);
|
||||||
string_view ti = usertype_traits<T>::qualified_name();
|
string_view ti = usertype_traits<T>::qualified_name();
|
||||||
|
int cast_operation;
|
||||||
|
if constexpr (is_base_rebindable_v<u_traits>) {
|
||||||
|
using rebind_t = typename u_traits::template rebind_base<void>;
|
||||||
string_view rebind_ti = usertype_traits<rebind_t>::qualified_name();
|
string_view rebind_ti = usertype_traits<rebind_t>::qualified_name();
|
||||||
int cast_operation = ic(memory, &r, ti, rebind_ti);
|
cast_operation = ic(memory, &r, ti, rebind_ti);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
string_view rebind_ti("");
|
||||||
|
cast_operation = ic(memory, &r, ti, rebind_ti);
|
||||||
|
}
|
||||||
switch (cast_operation) {
|
switch (cast_operation) {
|
||||||
case 1: {
|
case 1: {
|
||||||
// it's a perfect match,
|
// it's a perfect match,
|
||||||
|
@ -12348,7 +12408,6 @@ namespace sol { namespace stack {
|
||||||
};
|
};
|
||||||
|
|
||||||
#if defined(SOL_CXX17_FEATURES) && SOL_CXX17_FEATURES
|
#if defined(SOL_CXX17_FEATURES) && SOL_CXX17_FEATURES
|
||||||
|
|
||||||
#if defined(SOL_STD_VARIANT) && SOL_STD_VARIANT
|
#if defined(SOL_STD_VARIANT) && SOL_STD_VARIANT
|
||||||
template <typename... Tn>
|
template <typename... Tn>
|
||||||
struct unqualified_getter<std::variant<Tn...>> {
|
struct unqualified_getter<std::variant<Tn...>> {
|
||||||
|
@ -12385,6 +12444,7 @@ namespace sol { namespace stack {
|
||||||
};
|
};
|
||||||
#endif // SOL_STD_VARIANT
|
#endif // SOL_STD_VARIANT
|
||||||
#endif // SOL_CXX17_FEATURES
|
#endif // SOL_CXX17_FEATURES
|
||||||
|
|
||||||
}} // namespace sol::stack
|
}} // namespace sol::stack
|
||||||
|
|
||||||
// end of sol/stack_get_unqualified.hpp
|
// end of sol/stack_get_unqualified.hpp
|
||||||
|
@ -12410,6 +12470,8 @@ namespace stack {
|
||||||
// beginning of sol/stack_check_get_unqualified.hpp
|
// beginning of sol/stack_check_get_unqualified.hpp
|
||||||
|
|
||||||
#if defined(SOL_CXX17_FEATURES) && SOL_CXX17_FEATURES
|
#if defined(SOL_CXX17_FEATURES) && SOL_CXX17_FEATURES
|
||||||
|
#if defined(SOL_STD_VARIANT) && SOL_STD_VARIANT
|
||||||
|
#endif // variant
|
||||||
#endif // C++17
|
#endif // C++17
|
||||||
|
|
||||||
namespace sol {
|
namespace sol {
|
||||||
|
@ -12521,8 +12583,8 @@ namespace stack {
|
||||||
};
|
};
|
||||||
|
|
||||||
#if defined(SOL_STD_VARIANT) && SOL_STD_VARIANT
|
#if defined(SOL_STD_VARIANT) && SOL_STD_VARIANT
|
||||||
template <typename... Tn>
|
template <typename... Tn, typename C>
|
||||||
struct unqualified_check_getter<std::variant<Tn...>> {
|
struct unqualified_check_getter<std::variant<Tn...>, C> {
|
||||||
typedef std::variant<Tn...> V;
|
typedef std::variant<Tn...> V;
|
||||||
typedef std::variant_size<V> V_size;
|
typedef std::variant_size<V> V_size;
|
||||||
typedef std::integral_constant<bool, V_size::value == 0> V_is_empty;
|
typedef std::integral_constant<bool, V_size::value == 0> V_is_empty;
|
||||||
|
@ -12785,7 +12847,6 @@ namespace sol {
|
||||||
using u_traits = unique_usertype_traits<T>;
|
using u_traits = unique_usertype_traits<T>;
|
||||||
using P = typename u_traits::type;
|
using P = typename u_traits::type;
|
||||||
using Real = typename u_traits::actual_type;
|
using Real = typename u_traits::actual_type;
|
||||||
using rebind_t = typename u_traits::template rebind_base<void>;
|
|
||||||
|
|
||||||
template <typename Arg, typename... Args>
|
template <typename Arg, typename... Args>
|
||||||
static int push(lua_State* L, Arg&& arg, Args&&... args) {
|
static int push(lua_State* L, Arg&& arg, Args&&... args) {
|
||||||
|
|
26
tests/compile_tests/source/unique_usertype_traits.cpp
Normal file
26
tests/compile_tests/source/unique_usertype_traits.cpp
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
// sol3
|
||||||
|
|
||||||
|
// The MIT License (MIT)
|
||||||
|
|
||||||
|
// Copyright (c) 2013-2019 Rapptz, ThePhD and contributors
|
||||||
|
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
// this software and associated documentation files (the "Software"), to deal in
|
||||||
|
// the Software without restriction, including without limitation the rights to
|
||||||
|
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
// the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
// subject to the following conditions:
|
||||||
|
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
#include "sol_defines.hpp"
|
||||||
|
|
||||||
|
#include <sol/unique_usertype_traits.hpp>
|
Loading…
Reference in New Issue
Block a user