3434#include < type_traits>
3535#include < unordered_map>
3636#include < utility>
37+ #include < variant>
3738#include < vector>
3839
3940
@@ -299,8 +300,32 @@ struct function_traits_impl<R (__fastcall C::*)(Args...) const noexcept, true> :
299300};
300301#endif
301302
303+ template <class F , class = void >
304+ struct has_call_operator : std::false_type
305+ {
306+ };
307+
302308template <class F >
303- struct functor_traits_impl : function_traits_impl<decltype (&F::operator ()), true>
309+ struct has_call_operator <F, std::void_t <decltype (&F::operator ())>> : std::true_type
310+ {
311+ };
312+
313+ template <class F >
314+ inline static constexpr bool has_call_operator_v = has_call_operator<F>::value;
315+
316+ template <class F , class = void >
317+ struct functor_traits_impl
318+ {
319+ };
320+
321+ template <class F >
322+ struct functor_traits_impl <F, std::enable_if_t <has_call_operator_v<F>>> : function_traits_impl<decltype (&F::operator ()), true>
323+ {
324+ };
325+
326+ template <class F >
327+ struct functor_traits_impl <F, std::enable_if_t <!has_call_operator_v<F> && std::is_invocable_v<F&>>>
328+ : function_traits_base<false , false , std::invoke_result_t <F&>>
304329{
305330};
306331
@@ -311,6 +336,19 @@ struct function_traits : std::conditional_t<std::is_class_v<F>,
311336{
312337};
313338
339+ template <class T , bool IsClass = std::is_class_v<T>, class = void >
340+ struct has_function_traits : std::false_type
341+ {
342+ };
343+
344+ template <class T >
345+ struct has_function_traits <T, true , std::void_t <typename function_traits<T>::result_type, typename function_traits<T>::argument_types>> : std::true_type
346+ {
347+ };
348+
349+ template <class T >
350+ inline static constexpr bool has_function_traits_v = has_function_traits<T>::value;
351+
314352template <std::size_t I, class F , class = void >
315353struct function_argument_or_void
316354{
@@ -356,6 +394,12 @@ struct is_callable<T, std::void_t<decltype(&T::operator())>>
356394 static constexpr bool value = true ;
357395};
358396
397+ template <class T >
398+ struct is_callable <T, std::enable_if_t <std::is_class_v<T> && !has_call_operator_v<T> && has_function_traits_v<T>>>
399+ {
400+ static constexpr bool value = true ;
401+ };
402+
359403template <class T >
360404struct is_callable <T, std::enable_if_t <std::is_pointer_v<T> && std::is_function_v<std::remove_pointer_t <T>>>>
361405{
@@ -539,7 +583,172 @@ struct remove_first_type<std::tuple<T, Ts...>>
539583template <class T >
540584using remove_first_type_t = typename remove_first_type<T>::type;
541585
586+ template <std::size_t N, class Tuple >
587+ struct tuple_drop_first
588+ {
589+ using type = typename tuple_drop_first<N - 1 , remove_first_type_t <Tuple>>::type;
590+ };
591+
592+ template <class Tuple >
593+ struct tuple_drop_first <0 , Tuple>
594+ {
595+ using type = Tuple;
596+ };
597+
598+ template <std::size_t N, class Tuple >
599+ using tuple_drop_first_t = typename tuple_drop_first<N, Tuple>::type;
600+
601+ template <class T , class Tuple >
602+ struct tuple_prepend ;
603+
604+ template <class T , class ... Ts>
605+ struct tuple_prepend <T, std::tuple<Ts...>>
606+ {
607+ using type = std::tuple<T, Ts...>;
608+ };
609+
610+ template <class T , class Tuple >
611+ using tuple_prepend_t = typename tuple_prepend<T, Tuple>::type;
612+
613+ template <std::size_t N, class Tuple , class Accum = std::tuple<>>
614+ struct tuple_take_first_impl
615+ {
616+ using type = Accum;
617+ };
618+
619+ template <std::size_t N, class T , class ... Ts, class ... Acc>
620+ struct tuple_take_first_impl <N, std::tuple<T, Ts...>, std::tuple<Acc...>>
621+ {
622+ using type = typename tuple_take_first_impl<N - 1 , std::tuple<Ts...>, std::tuple<Acc..., T>>::type;
623+ };
624+
625+ template <class T , class ... Ts, class ... Acc>
626+ struct tuple_take_first_impl <0 , std::tuple<T, Ts...>, std::tuple<Acc...>>
627+ {
628+ using type = std::tuple<Acc...>;
629+ };
630+
631+ template <std::size_t N, class Tuple >
632+ using tuple_take_first_t = typename tuple_take_first_impl<N, Tuple>::type;
633+
634+ template <class F >
635+ struct member_function_class ;
636+
637+ template <class C , class R , class ... Args>
638+ struct member_function_class <R (C::*)(Args...)> { using type = C; };
639+
640+ template <class C , class R , class ... Args>
641+ struct member_function_class <R (C::*)(Args...) const > { using type = const C; };
642+
643+ template <class C , class R , class ... Args>
644+ struct member_function_class <R (C::*)(Args...) noexcept > { using type = C; };
645+
646+ template <class C , class R , class ... Args>
647+ struct member_function_class <R (C::*)(Args...) const noexcept > { using type = const C; };
648+
649+ template <class F >
650+ using member_function_class_t = typename member_function_class<F>::type;
651+
652+ template <class Fn , class ExplicitRemaining , bool IsMember>
653+ struct bind_back_leading_impl
654+ {
655+ using type = ExplicitRemaining;
656+ };
657+
658+ template <class Fn , class ExplicitRemaining >
659+ struct bind_back_leading_impl <Fn, ExplicitRemaining, true >
660+ {
661+ using type = tuple_prepend_t <member_function_class_t <Fn>*, ExplicitRemaining>;
662+ };
663+
664+ template <class Fn , class ExplicitRemaining >
665+ using bind_back_leading_t =
666+ typename bind_back_leading_impl<Fn, ExplicitRemaining, std::is_member_function_pointer_v<Fn>>::type;
667+
668+ template <class R , class RemainingArgsTuple , class Fn , class ... BoundArgs>
669+ struct bind_front_wrapper ;
670+
671+ template <class R , class ... Remaining, class Fn , class ... BoundArgs>
672+ struct bind_front_wrapper <R, std::tuple<Remaining...>, Fn, BoundArgs...>
673+ {
674+ Fn fn_;
675+ std::tuple<BoundArgs...> bound_;
676+
677+ template <class F , class ... BA >
678+ bind_front_wrapper (F&& f, BA &&... ba)
679+ : fn_(std::forward<F>(f)), bound_(std::forward<BA >(ba)...)
680+ {
681+ }
682+
683+ R operator ()(Remaining... args) const
684+ {
685+ return std::apply ([&](const auto &... ba) { return std::invoke (fn_, ba..., args...); }, bound_);
686+ }
687+ };
688+
542689}
690+
691+ template <class F , class ... BoundArgs>
692+ auto bind_front (F&& f, BoundArgs&&... args)
693+ {
694+ using Fn = std::decay_t <F>;
695+ using FnTraits = detail::function_traits<Fn>;
696+
697+ static constexpr std::size_t skip = std::is_member_function_pointer_v<Fn> ? 1u : 0u ;
698+ static constexpr std::size_t num_effective_bound = sizeof ...(BoundArgs) - skip;
699+
700+ using remaining = detail::tuple_drop_first_t <num_effective_bound, typename FnTraits::argument_types>;
701+ using R = typename FnTraits::result_type;
702+
703+ return detail::bind_front_wrapper<R, remaining, Fn, std::decay_t <BoundArgs>...>(
704+ std::forward<F>(f), std::forward<BoundArgs>(args)...);
705+ }
706+
707+ namespace detail {
708+
709+ template <class R , class LeadingArgsTuple , class Fn , class ... BoundArgs>
710+ struct bind_back_wrapper ;
711+
712+ template <class R , class ... Leading, class Fn , class ... BoundArgs>
713+ struct bind_back_wrapper <R, std::tuple<Leading...>, Fn, BoundArgs...>
714+ {
715+ Fn fn_;
716+ std::tuple<BoundArgs...> bound_;
717+
718+ template <class F , class ... BA >
719+ bind_back_wrapper (F&& f, BA &&... ba)
720+ : fn_(std::forward<F>(f)), bound_(std::forward<BA >(ba)...)
721+ {
722+ }
723+
724+ R operator ()(Leading... args) const
725+ {
726+ return std::apply ([&](const auto &... ba) { return std::invoke (fn_, args..., ba...); }, bound_);
727+ }
728+ };
729+
730+ }
731+
732+ template <class F , class ... BoundArgs>
733+ auto bind_back (F&& f, BoundArgs&&... args)
734+ {
735+ using Fn = std::decay_t <F>;
736+ using FnTraits = detail::function_traits<Fn>;
737+
738+ static constexpr std::size_t num_explicit = FnTraits::arity;
739+ static constexpr std::size_t num_bound = sizeof ...(BoundArgs);
740+ static constexpr std::size_t num_remaining = num_explicit - num_bound;
741+
742+ using explicit_remaining = detail::tuple_take_first_t <num_remaining, typename FnTraits::argument_types>;
743+
744+ using leading = detail::bind_back_leading_t <Fn, explicit_remaining>;
745+
746+ using R = typename FnTraits::result_type;
747+
748+ return detail::bind_back_wrapper<R, leading, Fn, std::decay_t <BoundArgs>...>(
749+ std::forward<F>(f), std::forward<BoundArgs>(args)...);
750+ }
751+
543752}
544753
545754
@@ -6066,10 +6275,10 @@ inline void dumpState(lua_State* L, unsigned maxDepth = 1, std::ostream& stream
60666275
60676276namespace luabridge {
60686277
6069- template <class T >
6070- struct Stack <std::list<T>>
6278+ template <class T , class Allocator >
6279+ struct Stack <std::list<T, Allocator >>
60716280{
6072- using Type = std::list<T>;
6281+ using Type = std::list<T, Allocator >;
60736282
60746283 [[nodiscard]] static Result push (lua_State* L, const Type& list)
60756284 {
@@ -12663,10 +12872,10 @@ ScopeGuard(F&&) -> ScopeGuard<F>;
1266312872
1266412873namespace luabridge {
1266512874
12666- template <class K, class V>
12667- struct Stack<std::map<K, V>>
12875+ template <class K, class V, class Compare, class Allocator >
12876+ struct Stack<std::map<K, V, Compare, Allocator >>
1266812877{
12669- using Type = std::map<K, V>;
12878+ using Type = std::map<K, V, Compare, Allocator >;
1267012879
1267112880 [[nodiscard]] static Result push(lua_State* L, const Type& map)
1267212881 {
@@ -12740,10 +12949,10 @@ struct Stack<std::map<K, V>>
1274012949
1274112950namespace luabridge {
1274212951
12743- template <class K>
12744- struct Stack<std::set<K>>
12952+ template <class K, class Compare, class Allocator >
12953+ struct Stack<std::set<K, Compare, Allocator >>
1274512954{
12746- using Type = std::set<K>;
12955+ using Type = std::set<K, Compare, Allocator >;
1274712956
1274812957 [[nodiscard]] static Result push(lua_State* L, const Type& set)
1274912958 {
@@ -12812,10 +13021,10 @@ struct Stack<std::set<K>>
1281213021
1281313022namespace luabridge {
1281413023
12815- template <class K, class V>
12816- struct Stack<std::unordered_map<K, V>>
13024+ template <class K, class V, class Hash, class KeyEqual, class Allocator >
13025+ struct Stack<std::unordered_map<K, V, Hash, KeyEqual, Allocator >>
1281713026{
12818- using Type = std::unordered_map<K, V>;
13027+ using Type = std::unordered_map<K, V, Hash, KeyEqual, Allocator >;
1281913028
1282013029 [[nodiscard]] static Result push(lua_State* L, const Type& map)
1282113030 {
@@ -12885,14 +13094,87 @@ struct Stack<std::unordered_map<K, V>>
1288513094
1288613095// End File: Source/LuaBridge/UnorderedMap.h
1288713096
13097+ // Begin File: Source/LuaBridge/Variant.h
13098+
13099+ namespace luabridge {
13100+
13101+ template <class... Args>
13102+ struct Stack<std::variant<Args...>>
13103+ {
13104+ using Type = std::variant<Args...>;
13105+
13106+ [[nodiscard]] static Result push(lua_State* L, const Type& variant)
13107+ {
13108+ return std::visit([L](const auto& value) { return Stack<std::decay_t<decltype(value)>>::push(L, value); }, variant);
13109+ }
13110+
13111+ [[nodiscard]] static TypeResult<Type> get(lua_State* L, int index)
13112+ {
13113+ return tryGet<Args...>(L, index);
13114+ }
13115+
13116+ [[nodiscard]] static bool isInstance(lua_State* L, int index)
13117+ {
13118+ return (Stack<Args>::isInstance(L, index) || ...);
13119+ }
13120+
13121+ private:
13122+ template <class T, class... Rest>
13123+ [[nodiscard]] static TypeResult<Type> tryGet(lua_State* L, int index)
13124+ {
13125+ if (auto value = Stack<T>::get(L, index))
13126+ return Type{ std::in_place_type<T>, std::move(*value) };
13127+
13128+ if constexpr (sizeof...(Rest) > 0)
13129+ return tryGet<Rest...>(L, index);
13130+
13131+ return makeErrorCode(ErrorCode::InvalidTypeCast);
13132+ }
13133+ };
13134+
13135+ template <>
13136+ struct Stack<std::monostate>
13137+ {
13138+ using Type = std::monostate;
13139+
13140+ [[nodiscard]] static Result push(lua_State* L, const Type&)
13141+ {
13142+ #if LUABRIDGE_SAFE_STACK_CHECKS
13143+ if (! lua_checkstack(L, 1))
13144+ return makeErrorCode(ErrorCode::LuaStackOverflow);
13145+ #endif
13146+
13147+ lua_pushnil(L);
13148+ return {};
13149+ }
13150+
13151+ [[nodiscard]] static TypeResult<Type> get(lua_State* L, int index)
13152+ {
13153+ if (lua_isnoneornil(L, index))
13154+ return Type{};
13155+
13156+ return makeErrorCode(ErrorCode::InvalidTypeCast);
13157+ }
13158+
13159+ [[nodiscard]] static bool isInstance(lua_State* L, int index)
13160+ {
13161+ return lua_isnoneornil(L, index);
13162+ }
13163+ };
13164+
13165+ }
13166+
13167+
13168+ // End File: Source/LuaBridge/Variant.h
13169+
1288813170// Begin File: Source/LuaBridge/Vector.h
1288913171
1289013172namespace luabridge {
1289113173
12892- template <class T>
12893- struct Stack<std::vector<T>>
13174+ template <class T, class Allocator >
13175+ struct Stack<std::vector<T, Allocator >>
1289413176{
12895- using Type = std::vector<T>;
13177+ using Type = std::vector<T, Allocator >;
1289613178
1289713179 [[nodiscard]] static Result push(lua_State* L, const Type& vector)
1289813180 {
0 commit comments