diff --git a/include/mserialize/make_template_tag.hpp b/include/mserialize/make_template_tag.hpp
index 6e7e621..d58be3c 100644
--- a/include/mserialize/make_template_tag.hpp
+++ b/include/mserialize/make_template_tag.hpp
@@ -78,12 +78,25 @@
// MSERIALIZE_UNTUPLE((Tuple)) = Tuple
// MSERIALIZE_STRINGIZE_LIST(Tuple) ~= "Tuple"
//
+// tag_guard: to make has_tag report correctly if T 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 \
struct CustomTag \
{ \
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 \
+ > tag_guard; \
static constexpr auto tag_string() \
{ \
return cx_strcat( \
@@ -108,4 +121,8 @@
#define MSERIALIZE_STRINGIZE_LIST_I(_, a) "," #a
+#define MSERIALIZE_HAS_TAG(_, m) \
+ mserialize::detail::has_tag, \
+ /**/
+
#endif // MSERIALIZE_MAKE_TEMPLATE_TAG_HPP
diff --git a/test/unit/mserialize/tag.cpp b/test/unit/mserialize/tag.cpp
index 593fd18..4478995 100644
--- a/test/unit/mserialize/tag.cpp
+++ b/test/unit/mserialize/tag.cpp
@@ -188,3 +188,23 @@ MSERIALIZE_MAKE_DERIVED_STRUCT_TAG(Derived2, (Derived1))
static_assert(mserialize::tag() == "{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
+struct Nest
+{
+ Nested n;
+};
+MSERIALIZE_MAKE_TEMPLATE_TAG((typename Nested), (Nest), n)
+
+static_assert(mserialize::detail::has_tag>::value, "");
+static_assert(!mserialize::detail::has_tag>::value, "");