mirror of
https://github.com/ThePhD/sol2.git
synced 2024-03-22 13:10:44 +08:00
Properly handle const value returns (and constness in general).
Keeps errors when trying to bind a const variables directly, but const returns should be forced to value-types, since lua has no concept of `const`.
This commit is contained in:
parent
14b1a3fe0c
commit
e25d4b4c02
@ -107,7 +107,7 @@ struct static_function {
|
||||
return_type r = stack::get_call(L, fx, t);
|
||||
std::ptrdiff_t nargs = sizeof...(Args);
|
||||
lua_pop(L, nargs);
|
||||
stack::push(L, std::forward<return_type>(r));
|
||||
stack::push(L, detail::return_forward<return_type>{}(r));
|
||||
return sizeof...(Ret);
|
||||
}
|
||||
|
||||
@ -149,7 +149,7 @@ struct static_member_function {
|
||||
return_type r = stack::get_call(L, fx, types<Args...>());
|
||||
std::ptrdiff_t nargs = sizeof...(Args);
|
||||
lua_pop(L, nargs);
|
||||
stack::push(L, std::move(r));
|
||||
stack::push(L, detail::return_forward<return_type>{}(r));
|
||||
return sizeof...(Ret);
|
||||
}
|
||||
|
||||
@ -384,7 +384,7 @@ struct userdata_function_core : public base_function {
|
||||
return_type r = stack::get_call(L, 2, fx, t);
|
||||
std::ptrdiff_t nargs = sizeof...(Args);
|
||||
lua_pop(L, nargs);
|
||||
push(L, std::forward<return_type>(r));
|
||||
push(L, detail::return_forward<return_type>{}(r));
|
||||
return sizeof...(Ret);
|
||||
}
|
||||
|
||||
|
@ -48,6 +48,28 @@ template<typename T>
|
||||
inline T* get_ptr(T* val) {
|
||||
return val;
|
||||
}
|
||||
|
||||
template <typename Decorated>
|
||||
struct return_forward {
|
||||
typedef Unqualified<Decorated> T;
|
||||
|
||||
T& operator()(T& value) const {
|
||||
return value;
|
||||
}
|
||||
|
||||
T&& operator()(T&& value) const {
|
||||
return std::move(value);
|
||||
}
|
||||
|
||||
T operator()(const T& value) const {
|
||||
return value;
|
||||
}
|
||||
|
||||
// handle retarded libraries
|
||||
T operator()(const T&& value) const {
|
||||
return value;
|
||||
}
|
||||
};
|
||||
} // detail
|
||||
|
||||
namespace stack {
|
||||
|
101
sol/userdata.hpp
101
sol/userdata.hpp
@ -38,12 +38,60 @@ inline std::unique_ptr<T> make_unique(Args&&... args) {
|
||||
}
|
||||
} // detail
|
||||
|
||||
const std::array<std::string, 2> meta_variable_names = {
|
||||
"__index",
|
||||
"__newindex"
|
||||
};
|
||||
|
||||
const std::array<std::string, 19> meta_function_names = {
|
||||
"__index",
|
||||
"__newindex",
|
||||
"__mode",
|
||||
"__call",
|
||||
"__metatable",
|
||||
"__tostring",
|
||||
"__len",
|
||||
"__unm",
|
||||
"__add",
|
||||
"__sub",
|
||||
"__mul",
|
||||
"__div",
|
||||
"__mod",
|
||||
"__pow",
|
||||
"__concat",
|
||||
"__eq",
|
||||
"__lt",
|
||||
"__le",
|
||||
"__gc",
|
||||
};
|
||||
|
||||
/* Too easy?
|
||||
enum class meta_function {
|
||||
index,
|
||||
new_index,
|
||||
mode,
|
||||
call,
|
||||
metatable,
|
||||
to_string,
|
||||
length,
|
||||
unary_minus,
|
||||
addition,
|
||||
subtraction,
|
||||
multiplication,
|
||||
division,
|
||||
modulus,
|
||||
power_of,
|
||||
involution = power_of,
|
||||
concatenation,
|
||||
equal_to,
|
||||
less_than,
|
||||
less_than_or_equal_to,
|
||||
};*/
|
||||
|
||||
template<typename T>
|
||||
class userdata {
|
||||
private:
|
||||
typedef std::unordered_map<std::string, std::pair<std::unique_ptr<base_function>, bool>> function_map_t;
|
||||
const static std::array<std::string, 2> metavariablenames;
|
||||
const static std::array<std::string, 19> metafunctionnames;
|
||||
function_map_t indexmetafunctions, newindexmetafunctions;
|
||||
std::vector<std::string> functionnames;
|
||||
std::vector<std::unique_ptr<base_function>> metafunctions;
|
||||
@ -177,15 +225,15 @@ private:
|
||||
bool build_function(std::false_type, function_map_t*& index, function_map_t*& newindex, std::string funcname, Ret TBase::* func) {
|
||||
static_assert(std::is_base_of<TBase, T>::value, "Any registered function must be part of the class");
|
||||
typedef typename std::decay<decltype(func)>::type function_type;
|
||||
auto metamethod = std::find(metafunctionnames.begin(), metafunctionnames.end(), funcname);
|
||||
if (metamethod != metafunctionnames.end()) {
|
||||
auto metamethod = std::find(meta_function_names.begin(), meta_function_names.end(), funcname);
|
||||
if (metamethod != meta_function_names.end()) {
|
||||
functionnames.push_back(std::move(funcname));
|
||||
std::string& name = functionnames.back();
|
||||
auto indexmetamethod = std::find(metavariablenames.begin(), metavariablenames.end(), name);
|
||||
auto indexmetamethod = std::find(meta_variable_names.begin(), meta_variable_names.end(), name);
|
||||
std::unique_ptr<base_function> ptr(nullptr);
|
||||
if (indexmetamethod != metavariablenames.end()) {
|
||||
if (indexmetamethod != meta_variable_names.end()) {
|
||||
auto idxptr = detail::make_unique<userdata_indexing_function<function_type, T>>(name, func);
|
||||
switch( std::distance(indexmetamethod, metavariablenames.end()) ) {
|
||||
switch( std::distance(indexmetamethod, meta_variable_names.end()) ) {
|
||||
case 0:
|
||||
index = &(idxptr->functions);
|
||||
break;
|
||||
@ -214,7 +262,7 @@ private:
|
||||
void build_function_tables(function_map_t*& index, function_map_t*& newindex, std::string funcname, Ret TBase::* func, Args&&... args) {
|
||||
typedef typename std::is_member_object_pointer<decltype(func)>::type is_variable;
|
||||
static const std::size_t V = static_cast<std::size_t>( !is_variable::value );
|
||||
if (build_function<N>(is_variable(), index, newindex, std::move(funcname), func)) {
|
||||
if (build_function<N>(is_variable(), index, newindex, std::move(funcname), std::move(func))) {
|
||||
build_function_tables<N + V>(index, newindex, std::forward<Args>(args)...);
|
||||
}
|
||||
else {
|
||||
@ -222,6 +270,14 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
/* Apparently there needs to be magic
|
||||
template<std::size_t N, typename TBase, typename Ret, typename... Args>
|
||||
void build_function_tables(function_map_t*& index, function_map_t*& newindex, meta_function metafunc, Ret TBase::* func, Args&&... args) {
|
||||
std::size_t idx = static_cast<std::size_t>(metafunc);
|
||||
const std::string& funcname = meta_function_names[idx];
|
||||
build_function_tables<N>(index, newindex, funcname, std::move(func), std::forward<Args>(args)...);
|
||||
}*/
|
||||
|
||||
public:
|
||||
template<typename... Args>
|
||||
userdata(Args&&... args): userdata(userdata_traits<T>::name, default_constructor, std::forward<Args>(args)...) {}
|
||||
@ -313,35 +369,6 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
const std::array<std::string, 2> userdata<T>::metavariablenames = {
|
||||
"__index",
|
||||
"__newindex"
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
const std::array<std::string, 19> userdata<T>::metafunctionnames = {
|
||||
"__index",
|
||||
"__newindex",
|
||||
"__mode",
|
||||
"__call",
|
||||
"__metatable",
|
||||
"__tostring",
|
||||
"__len",
|
||||
"__gc",
|
||||
"__unm",
|
||||
"__add",
|
||||
"__sub",
|
||||
"__mul",
|
||||
"__div",
|
||||
"__mod",
|
||||
"__pow",
|
||||
"__concat",
|
||||
"__eq",
|
||||
"__lt",
|
||||
"__le",
|
||||
};
|
||||
|
||||
namespace stack {
|
||||
template <typename T>
|
||||
struct pusher<userdata<T>> {
|
||||
|
Loading…
x
Reference in New Issue
Block a user