Skip to content

Commit 4177ea1

Browse files
committed
Updated amalgama
1 parent e6d660f commit 4177ea1

5 files changed

Lines changed: 132 additions & 92 deletions

File tree

‎Distribution/LuaBridge/LuaBridge.h‎

Lines changed: 96 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include <list>
2828
#include <map>
2929
#include <memory>
30+
#include <new>
3031
#include <optional>
3132
#include <ranges>
3233
#include <set>
@@ -182,14 +183,6 @@
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;
71117104
namespace detail {
71127105

71137106
template <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

71237151
template <class ArgsPack, std::size_t Start, std::size_t... Indices>
71247152
auto 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

71297172
template <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-
84468481
template <class ArgsPack, std::size_t Start, class F>
84478482
decltype(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

84648487
template <class ArgsPack, std::size_t Start, class T, class F>
84658488
decltype(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

84748495
template <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

97229772
private:

‎Manual.md‎

Lines changed: 8 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -90,11 +90,10 @@ Contents
9090
* [6.6 - LUABRIDGE_HAS_CXX17_FILESYSTEM / LUABRIDGE_DISABLE_CXX17_FILESYSTEM](#66---luabridge-has-cxx17-filesystem--luabridge-disable-cxx17-filesystem)
9191
* [6.7 - LUABRIDGE_HAS_CXX17_ANY / LUABRIDGE_DISABLE_CXX17_ANY](#67---luabridge-has-cxx17-any--luabridge-disable-cxx17-any)
9292
* [6.8 - LUABRIDGE_HAS_CXX20_SPAN / LUABRIDGE_DISABLE_CXX20_SPAN](#68---luabridge-has-cxx20-span--luabridge-disable-cxx20-span)
93-
* [6.9 - LUABRIDGE_HAS_CXX20_CONCEPTS / LUABRIDGE_DISABLE_CXX20_CONCEPTS](#69---luabridge-has-cxx20-concepts--luabridge-disable-cxx20-concepts)
94-
* [6.10 - LUABRIDGE_HAS_CXX20_RANGES / LUABRIDGE_DISABLE_CXX20_RANGES](#610---luabridge-has-cxx20-ranges--luabridge-disable-cxx20-ranges)
95-
* [6.11 - LUABRIDGE_HAS_CXX23_EXPECTED / LUABRIDGE_DISABLE_CXX23_EXPECTED](#611---luabridge-has-cxx23-expected--luabridge-disable-cxx23-expected)
96-
* [6.12 - LUABRIDGE_HAS_CXX23_FLAT_CONTAINERS / LUABRIDGE_DISABLE_CXX23_FLAT_CONTAINERS](#612---luabridge-has-cxx23-flat-containers--luabridge-disable-cxx23-flat-containers)
97-
* [6.13 - LUABRIDGE_HAS_CXX23_MOVE_ONLY_FUNCTION / LUABRIDGE_DISABLE_CXX23_MOVE_ONLY_FUNCTION](#613---luabridge-has-cxx23-move-only-function--luabridge-disable-cxx23-move-only-function)
93+
* [6.9 - LUABRIDGE_HAS_CXX20_RANGES / LUABRIDGE_DISABLE_CXX20_RANGES](#69---luabridge-has-cxx20-ranges--luabridge-disable-cxx20-ranges)
94+
* [6.10 - LUABRIDGE_HAS_CXX23_EXPECTED / LUABRIDGE_DISABLE_CXX23_EXPECTED](#610---luabridge-has-cxx23-expected--luabridge-disable-cxx23-expected)
95+
* [6.11 - LUABRIDGE_HAS_CXX23_FLAT_CONTAINERS / LUABRIDGE_DISABLE_CXX23_FLAT_CONTAINERS](#611---luabridge-has-cxx23-flat-containers--luabridge-disable-cxx23-flat-containers)
96+
* [6.12 - LUABRIDGE_HAS_CXX23_MOVE_ONLY_FUNCTION / LUABRIDGE_DISABLE_CXX23_MOVE_ONLY_FUNCTION](#612---luabridge-has-cxx23-move-only-function--luabridge-disable-cxx23-move-only-function)
9897

9998
* [Appendix - API Reference](#appendix---api-reference)
10099

@@ -2404,21 +2403,7 @@ To force the feature off:
24042403
#include <LuaBridge/LuaBridge.h>
24052404
```
24062405

2407-
6.9 - LUABRIDGE_HAS_CXX20_CONCEPTS / LUABRIDGE_DISABLE_CXX20_CONCEPTS
2408-
----------------------------------------------------------------------
2409-
2410-
**`LUABRIDGE_HAS_CXX20_CONCEPTS` - auto-detected when C++20 is enabled, override allowed**
2411-
2412-
When a C++20 compiler with concepts support is detected, LuaBridge uses concept constraints internally to improve compiler diagnostics and template resolution.
2413-
2414-
To force the feature off:
2415-
2416-
```cpp
2417-
#define LUABRIDGE_DISABLE_CXX20_CONCEPTS
2418-
#include <LuaBridge/LuaBridge.h>
2419-
```
2420-
2421-
6.10 - LUABRIDGE_HAS_CXX20_RANGES / LUABRIDGE_DISABLE_CXX20_RANGES
2406+
6.9 - LUABRIDGE_HAS_CXX20_RANGES / LUABRIDGE_DISABLE_CXX20_RANGES
24222407
-------------------------------------------------------------------
24232408

24242409
**`LUABRIDGE_HAS_CXX20_RANGES` - auto-detected when C++20 is enabled, override allowed**
@@ -2438,7 +2423,7 @@ To force the feature off:
24382423
#include <LuaBridge/LuaBridge.h>
24392424
```
24402425

2441-
6.11 - LUABRIDGE_HAS_CXX23_EXPECTED / LUABRIDGE_DISABLE_CXX23_EXPECTED
2426+
6.10 - LUABRIDGE_HAS_CXX23_EXPECTED / LUABRIDGE_DISABLE_CXX23_EXPECTED
24422427
-----------------------------------------------------------------------
24432428

24442429
**`LUABRIDGE_HAS_CXX23_EXPECTED` - auto-detected when C++23 is enabled, override allowed**
@@ -2452,7 +2437,7 @@ To force the feature off:
24522437
#include <LuaBridge/LuaBridge.h>
24532438
```
24542439

2455-
6.12 - LUABRIDGE_HAS_CXX23_FLAT_CONTAINERS / LUABRIDGE_DISABLE_CXX23_FLAT_CONTAINERS
2440+
6.11 - LUABRIDGE_HAS_CXX23_FLAT_CONTAINERS / LUABRIDGE_DISABLE_CXX23_FLAT_CONTAINERS
24562441
-------------------------------------------------------------------------------------
24572442

24582443
**`LUABRIDGE_HAS_CXX23_FLAT_CONTAINERS` - auto-detected when C++23 is enabled, override allowed**
@@ -2466,7 +2451,7 @@ To force the feature off:
24662451
#include <LuaBridge/LuaBridge.h>
24672452
```
24682453

2469-
6.13 - LUABRIDGE_HAS_CXX23_MOVE_ONLY_FUNCTION / LUABRIDGE_DISABLE_CXX23_MOVE_ONLY_FUNCTION
2454+
6.12 - LUABRIDGE_HAS_CXX23_MOVE_ONLY_FUNCTION / LUABRIDGE_DISABLE_CXX23_MOVE_ONLY_FUNCTION
24702455
-------------------------------------------------------------------------------------------
24712456

24722457
**`LUABRIDGE_HAS_CXX23_MOVE_ONLY_FUNCTION` - auto-detected when C++23 is enabled, override allowed**

‎README.md‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,6 @@ LuaBridge3 auto-detects available C++ standard library features and activates th
136136
| `LUABRIDGE_HAS_CXX17_FILESYSTEM` | `std::filesystem::path` ↔ string | C++17 |
137137
| `LUABRIDGE_HAS_CXX17_ANY` | `std::any` push registry | C++17 |
138138
| `LUABRIDGE_HAS_CXX20_SPAN` | `std::span` push support | C++20 |
139-
| `LUABRIDGE_HAS_CXX20_CONCEPTS` | Concept constraints in templates | C++20 |
140139
| `LUABRIDGE_HAS_CXX20_RANGES` | `Iterator`/`Range` satisfy `std::ranges` concepts | C++20 |
141140
| `LUABRIDGE_HAS_CXX20_COROUTINES` | `CppCoroutine<R>` / `LuaCoroutine` | C++20 |
142141
| `LUABRIDGE_HAS_CXX23_EXPECTED` | `std::expected<T,E>` conversion | C++23 |

‎Source/LuaBridge/detail/Config.h‎

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -183,20 +183,6 @@
183183
#endif
184184
#endif
185185

186-
/**
187-
* @brief Enable C++20 concepts library support.
188-
*
189-
* Requires C++20 and concepts to be available.
190-
* Define LUABRIDGE_DISABLE_CXX20_CONCEPTS to force-disable even when available.
191-
*/
192-
#if !defined(LUABRIDGE_HAS_CXX20_CONCEPTS)
193-
#if !defined(LUABRIDGE_DISABLE_CXX20_CONCEPTS) && LUABRIDGE_CXX20_OR_GREATER && defined(__cpp_concepts) && __cpp_concepts >= 201907L
194-
#define LUABRIDGE_HAS_CXX20_CONCEPTS 1
195-
#else
196-
#define LUABRIDGE_HAS_CXX20_CONCEPTS 0
197-
#endif
198-
#endif
199-
200186
/**
201187
* @brief Enable C++20 ranges library support.
202188
*

‎amalgamate.py‎

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,20 @@
1616
INCLUDE_FILE_MATCHER = re.compile(r'#include\s*[<\"]([\w.\\/]*)[>\"]')
1717
LOCAL_INCLUDE_FILE_MATCHER = re.compile(r'#include\s*\"([\w.\\/]*)\"')
1818

19-
GUARDED_INCLUDES = set(["coroutine", "span", "flat_map", "flat_set", "expected", "move_only_function"])
20-
19+
GUARDED_INCLUDES = [
20+
{ "header": "coroutine", "condition": "(__cplusplus >= 202002L || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L))" },
21+
{ "header": "span" },
22+
{ "header": "flat_map" },
23+
{ "header": "flat_set" },
24+
{ "header": "expected" },
25+
{ "header": "move_only_function" },
26+
]
27+
28+
def GetGuardedInclude(header):
29+
for guarded in GUARDED_INCLUDES:
30+
if guarded["header"] == header:
31+
return guarded
32+
return None
2133

2234
def IsCppHeaderFile(ext):
2335
return ext in CPP_HEADER_FILE_EXT
@@ -198,14 +210,22 @@ def WriteAlgamationFiles(self):
198210
headerAmalgamation.write(f"// clang-format off\n\n")
199211
headerAmalgamation.write(f"#pragma once\n\n")
200212

201-
for header in sorted(filter(lambda h: h not in GUARDED_INCLUDES, list(self.systemHeaders))):
202-
headerAmalgamation.write(f"#include <{header}>\n")
213+
systemHeaders = sorted(list(self.systemHeaders))
214+
for header in systemHeaders:
215+
if GetGuardedInclude(header) is None:
216+
headerAmalgamation.write(f"#include <{header}>\n")
203217
headerAmalgamation.write("\n")
204218

205-
for header in sorted(filter(lambda h: h in GUARDED_INCLUDES, list(self.systemHeaders))):
206-
headerAmalgamation.write(f"#if defined(__has_include) && __has_include(<{header}>)\n")
207-
headerAmalgamation.write(f"#include <{header}>\n")
208-
headerAmalgamation.write(f"#endif\n\n")
219+
for header in systemHeaders:
220+
guard = GetGuardedInclude(header)
221+
if guard is not None:
222+
headerAmalgamation.write(f"#if defined(__has_include) && __has_include(<{header}>)")
223+
if "condition" in guard and guard["condition"] is not None:
224+
headerAmalgamation.write(f" && {guard['condition']}\n")
225+
else:
226+
headerAmalgamation.write("\n")
227+
headerAmalgamation.write(f"#include <{header}>\n")
228+
headerAmalgamation.write(f"#endif\n\n")
209229
headerAmalgamation.write("\n")
210230

211231
self.AmalgamateQueue(self.headerQueue, headerAmalgamation)

0 commit comments

Comments
 (0)