Skip to content

Commit f9615b8

Browse files
authored
Merge pull request #51 from peacalm/dev
refactor pusher<class_tag>: push with user specified Target
2 parents 175457a + 5396026 commit f9615b8

File tree

1 file changed

+75
-59
lines changed

1 file changed

+75
-59
lines changed

include/peacalm/luaw.h

Lines changed: 75 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -3053,6 +3053,56 @@ struct luaw::pusher<luaw::function_tag> {
30533053
}
30543054
};
30553055

3056+
// class_tag: push as an user defined custom class type.
3057+
// Only works on class type or it's pointer.
3058+
// Push class as full userdata, push pointer to class as light userdata.
3059+
template <>
3060+
struct luaw::pusher<luaw::class_tag> {
3061+
static const size_t size = 1;
3062+
3063+
template <typename Y>
3064+
static int push(luaw& l, Y&& v) {
3065+
using SolidY = std::remove_reference_t<Y>;
3066+
static_assert(std::is_class<std::remove_pointer_t<SolidY>>::value,
3067+
"Only class or it's pointer");
3068+
__push<SolidY>(l, std::forward<Y>(v), std::is_pointer<SolidY>{});
3069+
return 1;
3070+
}
3071+
3072+
// Construct TargetT by Y at the moment of creating userdata.
3073+
template <typename TargetT, typename Y>
3074+
static std::enable_if_t<!std::is_same<TargetT, Y>::value &&
3075+
!std::is_reference<TargetT>::value,
3076+
int>
3077+
push(luaw& l, Y&& v) {
3078+
static_assert(std::is_class<std::remove_pointer_t<TargetT>>::value,
3079+
"Only class or it's pointer");
3080+
static_assert(std::is_convertible<Y, TargetT>::value,
3081+
"Y should convertible to TargetT");
3082+
__push<TargetT>(l, std::forward<Y>(v), std::is_pointer<TargetT>{});
3083+
return 1;
3084+
}
3085+
3086+
private:
3087+
// TargetT is pointer type
3088+
template <typename TargetT, typename Y>
3089+
static void __push(luaw& l, Y&& v, std::true_type) {
3090+
l.pushlightuserdata(reinterpret_cast<void*>(
3091+
const_cast<std::remove_cv_t<std::remove_pointer_t<TargetT>>*>(v)));
3092+
luaw::metatable_factory<TargetT>::push_shared_metatable(l);
3093+
l.setmetatable(-2);
3094+
}
3095+
3096+
// TargetT is not pointer type
3097+
template <typename TargetT, typename Y>
3098+
static void __push(luaw& l, Y&& v, std::false_type) {
3099+
void* p = l.newuserdata(sizeof(TargetT));
3100+
new (p) TargetT(std::forward<Y>(v)); // construct TargetT by Y
3101+
luaw::metatable_factory<TargetT>::push_shared_metatable(l);
3102+
l.setmetatable(-2);
3103+
}
3104+
};
3105+
30563106
// primary pusher. guess whether it may be a lambda, push as function if true,
30573107
// otherwise push as an user defined custom object.
30583108
template <typename T, typename>
@@ -3066,41 +3116,44 @@ struct luaw::pusher {
30663116

30673117
template <typename Y>
30683118
static int push(luaw& l, Y&& v) {
3069-
static_assert(std::is_convertible<std::decay_t<Y>, T>::value,
3070-
"Y should convertible to T");
3119+
static_assert(std::is_same<std::decay_t<Y>, T>::value,
3120+
"DecayY should same to T");
3121+
using SolidY = std::remove_reference_t<Y>;
30713122

30723123
// Guess whether it may be a lambda object, if it is, then push as a
30733124
// function, otherwise push as custom class.
3074-
return __push(l, std::forward<Y>(v), luaw_detail::decay_maybe_lambda<Y>{});
3125+
return __push<SolidY>(
3126+
l, std::forward<Y>(v), luaw_detail::decay_maybe_lambda<Y>{});
3127+
}
3128+
3129+
// Construct TargetT by Y at the moment of creating userdata.
3130+
template <typename TargetT, typename Y>
3131+
static std::enable_if_t<!std::is_same<TargetT, Y>::value &&
3132+
!std::is_reference<TargetT>::value,
3133+
int>
3134+
push(luaw& l, Y&& v) {
3135+
static_assert(std::is_class<TargetT>::value &&
3136+
std::is_same<std::remove_cv_t<TargetT>, T>::value,
3137+
"TargetT should be class T or cv- qualified T");
3138+
static_assert(std::is_convertible<Y, TargetT>::value,
3139+
"Y should convertible to TargetT");
3140+
__push<TargetT>(
3141+
l, std::forward<Y>(v), luaw_detail::decay_maybe_lambda<Y>{});
3142+
return 1;
30753143
}
30763144

30773145
private:
30783146
// Push as a function.
3079-
template <typename Y>
3147+
template <typename _Nouse, typename Y>
30803148
static int __push(luaw& l, Y&& v, std::true_type) {
30813149
return luaw::pusher<luaw::function_tag>::push(l, std::forward<Y>(v));
30823150
}
30833151

30843152
// Push as a full userdata.
3085-
template <typename Y>
3153+
template <typename TargetT, typename Y>
30863154
static int __push(luaw& l, Y&& v, std::false_type) {
3087-
using SolidY = std::remove_reference_t<Y>;
3088-
using T0 = T;
3089-
using T1 = std::
3090-
conditional_t<std::is_const<SolidY>::value, std::add_const_t<T0>, T0>;
3091-
using T2 = std::conditional_t<std::is_volatile<SolidY>::value,
3092-
std::add_volatile_t<T1>,
3093-
T1>;
3094-
static_assert(std::is_same<T, std::decay_t<Y>>::value
3095-
? std::is_same<T2, SolidY>::value
3096-
: true,
3097-
"Never happen");
3098-
3099-
void* p = l.newuserdata(sizeof(T2));
3100-
new (p) T2(std::forward<Y>(v)); // construct T by Y
3101-
luaw::metatable_factory<T2>::push_shared_metatable(l);
3102-
l.setmetatable(-2);
3103-
return 1;
3155+
return luaw::pusher<luaw::class_tag>::template push<TargetT>(
3156+
l, std::forward<Y>(v));
31043157
}
31053158
};
31063159

@@ -3223,43 +3276,6 @@ struct luaw::pusher<
32233276
}
32243277
};
32253278

3226-
// class_tag: push as an user defined custom class type.
3227-
// only work on type class or pointer to class.
3228-
template <>
3229-
struct luaw::pusher<luaw::class_tag> {
3230-
static const size_t size = 1;
3231-
3232-
template <typename Y>
3233-
static int push(luaw& l, Y&& v) {
3234-
using SolidY = std::remove_reference_t<Y>;
3235-
static_assert(std::is_class<std::remove_pointer_t<SolidY>>::value,
3236-
"Only class or it's pointer");
3237-
3238-
__push<SolidY, Y>(l, std::forward<Y>(v), std::is_pointer<SolidY>{});
3239-
3240-
return 1;
3241-
}
3242-
3243-
private:
3244-
// SolidY is pointer type
3245-
template <typename SolidY, typename Y>
3246-
static void __push(luaw& l, Y&& v, std::true_type) {
3247-
l.pushlightuserdata(reinterpret_cast<void*>(
3248-
const_cast<std::remove_cv_t<std::remove_pointer_t<SolidY>>*>(v)));
3249-
luaw::metatable_factory<SolidY>::push_shared_metatable(l);
3250-
l.setmetatable(-2);
3251-
}
3252-
3253-
// SolidY is not pointer type
3254-
template <typename SolidY, typename Y>
3255-
static void __push(luaw& l, Y&& v, std::false_type) {
3256-
void* p = l.newuserdata(sizeof(SolidY));
3257-
new (p) SolidY(std::forward<Y>(v));
3258-
luaw::metatable_factory<SolidY>::push_shared_metatable(l);
3259-
l.setmetatable(-2);
3260-
}
3261-
};
3262-
32633279
// newtable_tag: push a new empty table
32643280
template <>
32653281
struct luaw::pusher<luaw::newtable_tag> {

0 commit comments

Comments
 (0)