I have developed a library which is used in other libraries and applications. Its up for the application to provide the actual logging facility. The library shall only define a set of verbosity levels and pass the message to the application if something happened that should be logged. Hence my idea is to store a std::function
object in my library that actually points to some callback in the client application. Note in prior that C style variadic template arguments accessed via va_start, va_list
and va_end
are no option. This is because the client may use a non-printf based scheme such as spdlog
does as an example. I am aware of not providing a MWE but that is because the code does not even compile.
library:
.hpp
enum class severity_t
{
trace = 0,
debug = 1,
warn = 2,
error = 3,
critical = 4
};
template <typename ...args_t>
using logging_callback_t = std::function<void(severity_t, std::string, args_t...)>;
template <typename ...args_t>
extern logging_callback_t<args_t...> logging_callback;
template <typename ...args_t>
void log(severity_t level, const std::string& msg, args_t&& ...args)
{
logging_callback<args_t...>(level, msg, std::forward<args_t>(args)...);
}
template <typename ...args_t>
void set_logging_cbk(logging_callback_t<args_t...> func)
{
logging_callback<args_t...> = func;
}
.cpp
template <typename ...args_t>
logging_callback_t<args_t...> logging_callback;
std::string to_append("something");
log(severity_t::warn, "abc {}", to_append);
client application:
template <typename ...args_t)
void log_from_lib_a(severity_t level, const std::string& msg, args_t&& args...)
{
if(level == severity_t::warn)
{
spdlog::warn(msg, std::forward<args_t>(args)...);
}
}
int main()
{
set_logging_cbk<???>(boost::bind(&log_from_lib_a<???&...>,
boost::placeholders::_1,
boost::placeholders::_2,
???);
}
The only place in code I know about the actual type of the variadic template parameters is while logging from within the library. How can the client register for a callback he does not know the arguments for? This is the first time for me to use a parameter pack so I hope the code/idea is at least somehow reasonable. Apart from that why is it necessary to specify the variadic paramter type when calling a method on an instance of the std::function:
logging_callback<args_t...>(level, msg, std::forward<args_t>(args)...);
instead of
logging_callback(level, msg, std::forward<args_t>(args)...);
PS: cstd++11 is required, still if there is a better solution with a more recent version I am happy to hear about it too!
Aucun commentaire:
Enregistrer un commentaire