Skip to content

Commit

Permalink
Make has_tag work with adapted templates
Browse files Browse the repository at this point in the history
Previously has_tag reported true, even if the specified template
had members (depending on the template arguments) that did not have
a tag.
  • Loading branch information
erenon authored and spektrof committed Jun 24, 2022
1 parent 2de2fa0 commit 7bb21fc
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 0 deletions.
17 changes: 17 additions & 0 deletions include/mserialize/make_template_tag.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,12 +78,25 @@
// MSERIALIZE_UNTUPLE((Tuple<A,B,C>)) = Tuple<A,B,C>
// MSERIALIZE_STRINGIZE_LIST(Tuple<A,B,C>) ~= "Tuple<A,B,C>"
//
// tag_guard: to make has_tag report correctly if T<A> has a tag or not,
// (that depends on the template parameter), we first check if every member
// has a tag (see conjunction), then either create a constructible member
// (true_type, if every member has a tag), or a not-constructible member,
// (BuiltinTag), making this spec also non-constructible - has_tag
// checks constructibility.
#define MSERIALIZE_MAKE_TEMPLATE_TAG(TemplateArgs, ...) \
namespace mserialize { \
template <MSERIALIZE_UNTUPLE(TemplateArgs)> \
struct CustomTag<MSERIALIZE_UNTUPLE(MSERIALIZE_FIRST(__VA_ARGS__)), void> \
{ \
using T = MSERIALIZE_UNTUPLE(MSERIALIZE_FIRST(__VA_ARGS__)); \
std::conditional_t< \
mserialize::detail::conjunction< \
MSERIALIZE_FOREACH(MSERIALIZE_HAS_TAG, _, __VA_ARGS__) \
std::true_type>::value, \
std::true_type, \
mserialize::detail::BuiltinTag<void> \
> tag_guard; \
static constexpr auto tag_string() \
{ \
return cx_strcat( \
Expand All @@ -108,4 +121,8 @@

#define MSERIALIZE_STRINGIZE_LIST_I(_, a) "," #a

#define MSERIALIZE_HAS_TAG(_, m) \
mserialize::detail::has_tag<decltype(mserialize::serializable_member_type(&T::m))>, \
/**/

#endif // MSERIALIZE_MAKE_TEMPLATE_TAG_HPP
20 changes: 20 additions & 0 deletions test/unit/mserialize/tag.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -188,3 +188,23 @@ MSERIALIZE_MAKE_DERIVED_STRUCT_TAG(Derived2, (Derived1))
static_assert(mserialize::tag<Derived2>() == "{Derived2`'{Derived1`'{Base2`'{Base1`a'i}`b'i}`'{Base3`c'[c}`d'i`e'i}}", "");
#endif // _WIN32
// test has_tag
// This is a private method, but still useful sometimes,
// e.g: user wants to check if a template with a random member is loggable or not.
struct Adapted{};
MSERIALIZE_MAKE_STRUCT_TAG(Adapted)
struct NotAdapted{};
template <typename Nested>
struct Nest
{
Nested n;
};
MSERIALIZE_MAKE_TEMPLATE_TAG((typename Nested), (Nest<Nested>), n)
static_assert(mserialize::detail::has_tag<Nest<Adapted>>::value, "");
static_assert(!mserialize::detail::has_tag<Nest<NotAdapted>>::value, "");

0 comments on commit 7bb21fc

Please sign in to comment.