Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor luaw::function, Do not support non-const lvalue reference as… #53

Merged
merged 1 commit into from
Oct 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@

## Currently Unreleased - TBD

* Add static assertion to explicitly forbid using reference type as return type
or argument type in `luaw::function`.
* Add static assertion to explicitly forbid using non-const lvalue reference
as argument or using any reference as return for `luaw::function`.
* Add new class `subluaw`, and add method `luaw::make_subluaw`.
* add method `luaw::function::unref`, `luaw::function::ref_id` etc.
* Add method `luavalueref::setglobal`, `luavalueref::unref` etc.
Expand Down
27 changes: 15 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1906,24 +1906,27 @@ if (f.failed()) {

#### 3.3 Type of argument and return

Do not support using C++ reference type as function's argument or return type.

If using reference as argument, it will make a copy of the referenced
argument into Lua, won't implicitly take its address, meaning that it
will not share the same object in Lua with that in C++, and this
behaves differently with that in C++. This may confuse users, so
explicitly forbid it.
##### Argument

Do not support non-const lvalue reference as luaw::function's argument.

Directly using the underlying type if you want to make a copy of the
argument into Lua.
If using this kind of reference, it will make a copy of the referenced
argument into Lua, won't implicitly take its address, meaning that it
will not share the same object in Lua with C++.
And this behaves differently with that in C++. This may confuse users,
so explicitly forbid it.

Or if you want to share the same argument objects in Lua with C++,
If you want to share the same argument objects in Lua with C++,
so you can modify them in Lua, you can use raw pointer type if there is
only one kind of raw pointer type in all arguments, or use smart
pointer type or `luaw::ptrw` type, and these are safer and more reassuring.
pointer type or `peacalm::luaw::ptrw` type, and these two are safer and
more reassuring.

##### Return

Since we cannot make C++ reference type of reference to values in Lua,
so using C++ reference type as return type is also forbidden.
so using any C++ reference type as return type is forbidden.

To get a reference of a Lua value, can use type
[`luaw::luavalueref`](https://github.com/peacalm/cpp-luaw?tab=readme-ov-file#9-reference-of-lua-values-in-c).

Expand Down
51 changes: 35 additions & 16 deletions include/peacalm/luaw.h
Original file line number Diff line number Diff line change
Expand Up @@ -3931,7 +3931,8 @@ struct luaw::convertor<luaw::placeholder_tag> {

namespace luaw_detail {

// Has any reference type in a std::tuple
// Whether the type T is a std::tuple and has element of reference type.

template <typename T>
struct tuple_has_ref : std::false_type {};

Expand All @@ -3945,31 +3946,47 @@ struct tuple_has_ref<std::tuple<T, Ts...>>
template <>
struct tuple_has_ref<std::tuple<>> : std::false_type {};

// Has any reference type in Ts
// Whether the type T is a std::tuple and has element of non-const lvalue
// reference type.

template <typename T>
struct tuple_has_non_const_lvalue_ref : std::false_type {};

template <typename T, typename... Ts>
struct tuple_has_non_const_lvalue_ref<std::tuple<T, Ts...>>
: public std::integral_constant<
bool,
(std::is_lvalue_reference<T>::value &&
!std::is_const<std::remove_reference_t<T>>::value) ||
tuple_has_non_const_lvalue_ref<std::tuple<Ts...>>::value> {};

template <>
struct tuple_has_non_const_lvalue_ref<std::tuple<>> : std::false_type {};

// Whether have any non-const lvalue reference type in Ts
template <typename... Ts>
struct has_ref : public tuple_has_ref<std::tuple<Ts...>> {};
struct has_non_const_lvalue_ref
: public tuple_has_non_const_lvalue_ref<std::tuple<Ts...>> {};

} // namespace luaw_detail

template <typename Return, typename... Args>
class luaw::function<Return(Args...)> {
static_assert(
!luaw_detail::has_ref<Args...>::value,
"Do not support reference type as luaw::function's argument. "
!luaw_detail::has_non_const_lvalue_ref<Args...>::value,
"Do not support non-const lvalue reference as luaw::function's argument. "
""
"If using reference as argument, it will make a copy of the referenced "
"If using this kind of reference, it will make a copy of the referenced "
"argument into Lua, won't implicitly take its address, meaning that it "
"will not share the same object in Lua with that in C++, and this "
"behaves differently with that in C++. This may confuse users, so "
"explicitly forbid it. "
"will not share the same object in Lua with C++. "
"And this behaves differently with that in C++. This may confuse users, "
"so explicitly forbid it. "
""
"Directly using the underlying type if you want to make a copy of the "
"argument into Lua. "
"Or if you want to share the same argument objects in Lua with C++, "
"If you want to share the same argument objects in Lua with C++, "
"so you can modify them in Lua, you can use raw pointer type if there is "
"only one kind of raw pointer type in all arguments, or use smart "
"pointer type or peacalm::luaw::ptrw type, and these are safer and more "
"reassuring.");
"pointer type or peacalm::luaw::ptrw type, and these two are safer and "
"more reassuring.");
static_assert(!std::is_reference<Return>::value &&
!luaw_detail::tuple_has_ref<Return>::value,
"Do not support reference type as luaw::function's result. "
Expand Down Expand Up @@ -4090,7 +4107,7 @@ class luaw::function<Return(Args...)> {
return luaw::pusher_for_return<std::decay_t<Return>>::size;
}

Return operator()(const Args&... args) const {
Return operator()(Args... args) const {
// reset all states first
function_failed_ = false;
function_exists_ = false;
Expand Down Expand Up @@ -4127,7 +4144,9 @@ class luaw::function<Return(Args...)> {
function_exists_ = true;
}

int narg = push_args(l, args...);
// push args by copy or move
int narg = push_args(l, std::forward<Args>(args)...);

int pcall_ret = l.pcall(narg, LUA_MULTRET, 0);
PEACALM_LUAW_ASSERT(l.gettop() >= sz);

Expand Down