Logr::Priority d_priority; // (syslog) priority)
};
+// Warning: some meta-programming is going on. We define helper
+// templates that can be used to see if specific string output
+// functions are available. If so, we use those instead of << into an
+// ostringstream. Note that this decision happpens compile time.
+// Some hints taken from https://www.cppstories.com/2019/07/detect-overload-from-chars/
+// (I could not get function templates with enabled_if<> to work in this case)
+//
+// Default: std::string(T) is not available
+template <typename T, typename = void>
+struct is_to_string_available : std::false_type
+{
+};
+
+// If std::string(T) is available this template is used
+template <typename T>
+struct is_to_string_available<T, std::void_t<decltype(std::to_string(std::declval<T>()))>> : std::true_type
+{
+};
+
+// Same mechanism for t.toLogString()
+template <typename T, typename = void>
+struct is_toLogString_available : std::false_type
+{
+};
+
+template <typename T>
+struct is_toLogString_available<T, std::void_t<decltype(std::declval<T>().toLogString())>> : std::true_type
+{
+};
+
template <typename T>
struct Loggable : public Logr::Loggable
{
}
std::string to_string() const
{
- std::ostringstream oss;
- oss << _t;
- return oss.str();
+ if constexpr (std::is_same_v<T, std::string>) {
+ return _t;
+ }
+ else if constexpr (is_to_string_available<T>::value) {
+ return std::to_string(_t);
+ }
+ else if constexpr (is_toLogString_available<T>::value) {
+ return _t.toLogString();
+ }
+ else {
+ std::ostringstream oss;
+ oss << _t;
+ return oss.str();
+ }
}
};
-template <>
-inline std::string Loggable<DNSName>::to_string() const
-{
- return _t.toLogString();
-}
-template <>
-inline std::string Loggable<ComboAddress>::to_string() const
-{
- return _t.toLogString();
-}
-template <>
-inline std::string Loggable<std::string>::to_string() const
-{
- return _t;
-}
template <typename T>
struct IterLoggable : public Logr::Loggable
deferredAdds.emplace_back(fd, handleNewUDPQuestion);
g_listenSocketsAddresses[fd] = sin; // this is written to only from the startup thread, not from the workers
SLOG(g_log << Logger::Info << "Listening for UDP queries on " << sin.toStringWithPort() << endl,
- log->info(Logr::Info, "Listening for queries", "protocol", Logging::Loggable("UDP"), "address", Logging::Loggable(sin.toStringWithPort())));
+ log->info(Logr::Info, "Listening for queries", "protocol", Logging::Loggable("UDP"), "address", Logging::Loggable(sin)));
}
}
g_log << Logger::Info << endl;
}
else {
- log->info(Logr::Info, "CPU affinity has been set", "thread", Logging::Loggable(n), "cpumap", Logging::IterLoggable(cpuMapping->second.begin(), cpuMapping->second.end()));
+ log->info(Logr::Info, "CPU affinity has been set", "thread", Logging::Loggable(n), "cpumap", Logging::IterLoggable(cpuMapping->second.begin(), cpuMapping->second.end()));
}
}
else {
// we don't need to update g_listenSocketsAddresses since it doesn't work for TCP/IP:
// - fd is not that which we know here, but returned from accept()
SLOG(g_log << Logger::Info << "Listening for TCP queries on " << sin.toStringWithPort() << endl,
- log->info(Logr::Info, "Listening for queries", "protocol", Logging::Loggable("TCP"), "address", Logging::Loggable(sin.toStringWithPort())));
+ log->info(Logr::Info, "Listening for queries", "protocol", Logging::Loggable("TCP"), "address", Logging::Loggable(sin)));
}
}