util: partial support for abstract types in NDN_LOG_MEMBER_* macros
Change-Id: I6b2a0e8fb86cb83040d24e3d4d5ba8a872ca031c
diff --git a/ndn-cxx/util/logger.hpp b/ndn-cxx/util/logger.hpp
index 30b8779..81c1076 100644
--- a/ndn-cxx/util/logger.hpp
+++ b/ndn-cxx/util/logger.hpp
@@ -113,7 +113,13 @@
struct ExtractArgument;
template<class T, class U>
-struct ExtractArgument<T(U)>
+struct ExtractArgument<T(U&)>
+{
+ using type = U;
+};
+
+template<class T, class U>
+struct ExtractArgument<T(U)&>
{
using type = U;
};
@@ -190,9 +196,9 @@
* a dot (`.`), or contain multiple consecutive dots.
*/
#define NDN_LOG_MEMBER_INIT(cls, name) \
- const bool ::ndn::util::detail::ArgumentType<void(cls)>::ndn_cxx_loggerRegistration = \
+ const bool ::ndn::util::detail::ArgumentType<void(cls&)>::ndn_cxx_loggerRegistration = \
NDN_LOG_REGISTER_NAME(name); \
- ::ndn::util::Logger& ::ndn::util::detail::ArgumentType<void(cls)>::ndn_cxx_getLogger() \
+ ::ndn::util::Logger& ::ndn::util::detail::ArgumentType<void(cls&)>::ndn_cxx_getLogger() \
NDN_LOG_INIT_FUNCTION_BODY(name) \
struct ndn_cxx_allow_trailing_semicolon
@@ -202,9 +208,9 @@
*/
#define NDN_LOG_MEMBER_DECL_SPECIALIZED(cls) \
template<> \
- const bool ::ndn::util::detail::ArgumentType<void(cls)>::ndn_cxx_loggerRegistration; \
+ const bool ::ndn::util::detail::ArgumentType<void(cls&)>::ndn_cxx_loggerRegistration; \
template<> \
- ::ndn::util::Logger& ::ndn::util::detail::ArgumentType<void(cls)>::ndn_cxx_getLogger()
+ ::ndn::util::Logger& ::ndn::util::detail::ArgumentType<void(cls&)>::ndn_cxx_getLogger()
/** \brief Define an explicit specialization of a member log module of a class template.
*
@@ -219,10 +225,10 @@
*/
#define NDN_LOG_MEMBER_INIT_SPECIALIZED(cls, name) \
template<> \
- const bool ::ndn::util::detail::ArgumentType<void(cls)>::ndn_cxx_loggerRegistration = \
+ const bool ::ndn::util::detail::ArgumentType<void(cls&)>::ndn_cxx_loggerRegistration = \
NDN_LOG_REGISTER_NAME(name); \
template<> \
- ::ndn::util::Logger& ::ndn::util::detail::ArgumentType<void(cls)>::ndn_cxx_getLogger() \
+ ::ndn::util::Logger& ::ndn::util::detail::ArgumentType<void(cls&)>::ndn_cxx_getLogger() \
NDN_LOG_INIT_FUNCTION_BODY(name) \
struct ndn_cxx_allow_trailing_semicolon
diff --git a/tests/unit/util/logging.t.cpp b/tests/unit/util/logging.t.cpp
index e051cce..b8034b8 100644
--- a/tests/unit/util/logging.t.cpp
+++ b/tests/unit/util/logging.t.cpp
@@ -103,6 +103,38 @@
NDN_LOG_MEMBER_INIT(ClassWithLogger, ndn.util.tests.ClassWithLogger);
+class AbstractClassWithLogger
+{
+public:
+ virtual
+ ~AbstractClassWithLogger() = default;
+
+ void
+ logFromConstMemberFunction() const
+ {
+ NDN_LOG_INFO("const member function");
+ }
+
+ virtual void
+ logFromVirtualFunction() = 0;
+
+protected:
+ NDN_LOG_MEMBER_DECL();
+};
+
+// Check that the macro can cope with abstract types
+NDN_LOG_MEMBER_INIT(AbstractClassWithLogger, ndn.util.tests.AbstractClassWithLogger);
+
+class DerivedClass : public AbstractClassWithLogger
+{
+public:
+ void
+ logFromVirtualFunction() final
+ {
+ NDN_LOG_INFO("overridden virtual function");
+ }
+};
+
template<class T, class U>
class ClassTemplateWithLogger
{
@@ -301,11 +333,13 @@
BOOST_AUTO_TEST_CASE(MemberLogger)
{
Logging::setLevel("ndn.util.tests.ClassWithLogger", LogLevel::INFO);
+ Logging::setLevel("ndn.util.tests.AbstractClassWithLogger", LogLevel::INFO);
Logging::setLevel("ndn.util.tests.Specialized1", LogLevel::INFO);
// ndn.util.tests.Specialized2 is not enabled
const auto& names = Logging::getLoggerNames();
BOOST_CHECK_EQUAL(names.count("ndn.util.tests.ClassWithLogger"), 1);
+ BOOST_CHECK_EQUAL(names.count("ndn.util.tests.AbstractClassWithLogger"), 1);
BOOST_CHECK_EQUAL(names.count("ndn.util.tests.Specialized1"), 1);
BOOST_CHECK_EQUAL(names.count("ndn.util.tests.Specialized2"), 1);
@@ -318,6 +352,15 @@
LOG_SYSTIME_STR + " INFO: [ndn.util.tests.ClassWithLogger] const member function\n"
));
+ DerivedClass{}.logFromConstMemberFunction();
+ DerivedClass{}.logFromVirtualFunction();
+
+ Logging::flush();
+ BOOST_CHECK(os.is_equal(
+ LOG_SYSTIME_STR + " INFO: [ndn.util.tests.AbstractClassWithLogger] const member function\n" +
+ LOG_SYSTIME_STR + " INFO: [ndn.util.tests.AbstractClassWithLogger] overridden virtual function\n"
+ ));
+
ClassTemplateWithLogger<int, double>::logFromStaticMemberFunction();
ClassTemplateWithLogger<int, double>{}.logFromMemberFunction();
ClassTemplateWithLogger<int, std::string>::logFromStaticMemberFunction();
@@ -646,7 +689,7 @@
BOOST_CHECK(os2weak.expired());
}
-BOOST_AUTO_TEST_CASE(SetNullptrDestination)
+BOOST_AUTO_TEST_CASE(NullDestination)
{
Logging::setDestination(nullptr);
logFromModule1();