2727#include < list>
2828#include < map>
2929#include < memory>
30+ #include < new>
3031#include < optional>
3132#include < ranges>
3233#include < set>
182183#endif
183184#endif
184185
185- #if !defined(LUABRIDGE_HAS_CXX20_CONCEPTS)
186- #if !defined(LUABRIDGE_DISABLE_CXX20_CONCEPTS) && LUABRIDGE_CXX20_OR_GREATER && defined(__cpp_concepts) && __cpp_concepts >= 201907L
187- #define LUABRIDGE_HAS_CXX20_CONCEPTS 1
188- #else
189- #define LUABRIDGE_HAS_CXX20_CONCEPTS 0
190- #endif
191- #endif
192-
193186#if !defined(LUABRIDGE_HAS_CXX20_RANGES)
194187#if !defined(LUABRIDGE_DISABLE_CXX20_RANGES) && LUABRIDGE_CXX20_OR_GREATER && defined(__cpp_lib_ranges)
195188#define LUABRIDGE_HAS_CXX20_RANGES 1
@@ -7111,19 +7104,69 @@ class LuaRef;
71117104namespace detail {
71127105
71137106template <class T >
7114- auto unwrap_argument_or_error (lua_State* L, std::size_t index, std::size_t start)
7107+ using stack_value_t = remove_cvref_t <
7108+ decltype (*std::declval<decltype (Stack<T>::get(std::declval<lua_State*>(), 0 ))>())>;
7109+
7110+ template <class T >
7111+ struct ArgStorage
71157112{
7116- auto result = Stack<T>::get (L, static_cast <int >(index + start));
7113+ using StoredType = stack_value_t <T>;
7114+
7115+ alignas (StoredType) std::byte data[sizeof (StoredType)];
7116+ bool constructed = false ;
7117+
7118+ StoredType* ptr () noexcept { return std::launder (reinterpret_cast <StoredType*>(data)); }
7119+
7120+ void destroy () noexcept
7121+ {
7122+ if (constructed)
7123+ {
7124+ std::destroy_at (ptr ());
7125+ constructed = false ;
7126+ }
7127+ }
7128+ };
7129+
7130+ template <std::size_t I, class ArgsPack , std::size_t Start, class StorageTuple >
7131+ void decode_arg (lua_State* L, StorageTuple& storage, int & error_arg, const char *& error_msg)
7132+ {
7133+ using T = std::tuple_element_t <I, ArgsPack>;
7134+ using StoredType = typename std::tuple_element_t <I, StorageTuple>::StoredType;
7135+
7136+ if (error_arg)
7137+ return ;
7138+
7139+ auto result = Stack<T>::get (L, static_cast <int >(I + Start));
71177140 if (! result)
7118- raise_lua_error (L, " Error decoding argument #%d: %s" , static_cast <int >(index + 1 ), result.error_cstr ());
7141+ {
7142+ error_arg = static_cast <int >(I + 1 );
7143+ error_msg = result.error_cstr ();
7144+ return ;
7145+ }
71197146
7120- return std::move (*result);
7147+ ::new (std::get<I>(storage).data ) StoredType (std::move (*result));
7148+ std::get<I>(storage).constructed = true ;
71217149}
71227150
71237151template <class ArgsPack , std::size_t Start, std::size_t ... Indices>
71247152auto make_arguments_list_impl ([[maybe_unused]] lua_State* L, std::index_sequence<Indices...>)
71257153{
7126- return tupleize (unwrap_argument_or_error<std::tuple_element_t <Indices, ArgsPack>>(L, Indices, Start)...);
7154+ std::tuple<ArgStorage<std::tuple_element_t <Indices, ArgsPack>>...> storage;
7155+
7156+ int error_arg = 0 ;
7157+ const char * error_msg = nullptr ;
7158+
7159+ (decode_arg<Indices, ArgsPack, Start>(L, storage, error_arg, error_msg), ...);
7160+
7161+ if (error_arg)
7162+ {
7163+ (std::get<Indices>(storage).destroy (), ...);
7164+ raise_lua_error (L, " Error decoding argument #%d: %s" , error_arg, error_msg);
7165+ }
7166+
7167+ auto result = tupleize (std::move (*std::get<Indices>(storage).ptr ())...);
7168+ (std::get<Indices>(storage).destroy (), ...);
7169+ return result;
71277170}
71287171
71297172template <class ArgsPack , std::size_t Start>
@@ -8435,40 +8478,18 @@ inline void add_property_setter(lua_State* L, const char* name, int tableIndex)
84358478 lua_pop (L, 2 );
84368479}
84378480
8438- template <class ArgsPack , std::size_t Start, class F , std::size_t ... Indices>
8439- decltype (auto ) invoke_callable_from_stack_impl (lua_State* L, F&& func, std::index_sequence<Indices...>)
8440- {
8441- return std::invoke (
8442- std::forward<F>(func),
8443- unwrap_argument_or_error<std::tuple_element_t <Indices, ArgsPack>>(L, Indices, Start)...);
8444- }
8445-
84468481template <class ArgsPack , std::size_t Start, class F >
84478482decltype (auto ) invoke_callable_from_stack (lua_State* L, F&& func)
84488483{
8449- return invoke_callable_from_stack_impl<ArgsPack, Start>(
8450- L,
8451- std::forward<F>(func),
8452- std::make_index_sequence<std::tuple_size_v<ArgsPack>>());
8453- }
8454-
8455- template <class ArgsPack , std::size_t Start, class T , class F , std::size_t ... Indices>
8456- decltype (auto ) invoke_member_callable_from_stack_impl (lua_State* L, T* ptr, F&& func, std::index_sequence<Indices...>)
8457- {
8458- return std::invoke (
8459- std::forward<F>(func),
8460- ptr,
8461- unwrap_argument_or_error<std::tuple_element_t <Indices, ArgsPack>>(L, Indices, Start)...);
8484+ return std::apply (std::forward<F>(func), make_arguments_list<ArgsPack, Start>(L));
84628485}
84638486
84648487template <class ArgsPack , std::size_t Start, class T , class F >
84658488decltype (auto ) invoke_member_callable_from_stack (lua_State* L, T* ptr, F&& func)
84668489{
8467- return invoke_member_callable_from_stack_impl<ArgsPack, Start>(
8468- L,
8469- ptr,
8490+ return std::apply (
84708491 std::forward<F>(func),
8471- std::make_index_sequence< std::tuple_size_v< ArgsPack>>( ));
8492+ std::tuple_cat ( std::tuple<T*>(ptr), make_arguments_list< ArgsPack, Start>(L) ));
84728493}
84738494
84748495template <class ReturnType , class ArgsPack , std::size_t Start = 1u >
@@ -9527,7 +9548,7 @@ int constructor_container_proxy(lua_State* L)
95279548 try
95289549 {
95299550#endif
9530- object = constructor<T, Args>::construct (detail:: make_arguments_list<Args, 2 >(L));
9551+ object = constructor<T, Args>::construct (make_arguments_list<Args, 2 >(L));
95319552
95329553#if LUABRIDGE_HAS_EXCEPTIONS
95339554 }
@@ -9568,7 +9589,7 @@ int constructor_placement_proxy(lua_State* L)
95689589 raise_lua_error (L, " %s" , e.what ());
95699590 }
95709591#endif
9571-
9592+
95729593 value->commit ();
95739594
95749595 return 1 ;
@@ -9595,7 +9616,7 @@ struct constructor_forwarder
95959616 raise_lua_error (L, " %s" , detail::ErrorCategory::errorString (ec.value ()));
95969617
95979618 T* object = nullptr ;
9598-
9619+
95999620#if LUABRIDGE_HAS_EXCEPTIONS
96009621 try
96019622 {
@@ -9696,27 +9717,56 @@ struct container_forwarder
96969717 using FnTraits = function_traits<F>;
96979718 using FnArgs = typename FnTraits::argument_types;
96989719
9699- C object;
9700-
9720+ alignas (C) std::byte object_storage[sizeof (C)];
9721+ C* object = nullptr ;
9722+
9723+ #if LUABRIDGE_HAS_EXCEPTIONS
9724+ try
9725+ {
9726+ #endif
9727+ object = ::new (object_storage) C (
9728+ container_constructor<C>::construct (m_func, make_arguments_list<FnArgs, 2 >(L)));
9729+
9730+ #if LUABRIDGE_HAS_EXCEPTIONS
9731+ }
9732+ catch (const std::exception& e)
9733+ {
9734+ if (object != nullptr )
9735+ std::destroy_at (object);
9736+
9737+ raise_lua_error (L, " %s" , e.what ());
9738+ }
9739+ #endif
9740+
9741+ LUABRIDGE_ASSERT (object != nullptr );
9742+
9743+ Result result;
9744+
97019745#if LUABRIDGE_HAS_EXCEPTIONS
97029746 try
97039747 {
97049748#endif
9705- object = container_constructor<C >::construct (m_func, make_arguments_list<FnArgs, 2 >(L) );
9749+ result = UserdataSharedHelper<C, false >::push (L, *object );
97069750
97079751#if LUABRIDGE_HAS_EXCEPTIONS
97089752 }
97099753 catch (const std::exception& e)
97109754 {
9755+ std::destroy_at (object);
9756+
97119757 raise_lua_error (L, " %s" , e.what ());
97129758 }
97139759#endif
97149760
9715- auto result = UserdataSharedHelper<C, false >::push (L, object);
97169761 if (! result)
9762+ {
9763+ std::destroy_at (object);
97179764 raise_lua_error (L, " %s" , result.error_cstr ());
9765+ }
97189766
9719- return object;
9767+ C ret = std::move (*object);
9768+ std::destroy_at (object);
9769+ return ret;
97209770 }
97219771
97229772private:
0 commit comments