#include <iostream>
#include <sstream>
#include <cstdint>

struct Callback
{
	virtual void dosomething(uint8_t level, const char *msg) = 0;
};

Callback *callback = nullptr;

void log_impl(std::ostream&) {}

template<typename T, typename ... Args>
void log_impl(std::ostream &os, const T &first_arg, const Args&... args)
{
    os << first_arg;
    log_impl(os, args...);
}

template<typename ... Args>
void log(uint8_t level, const Args&... args)
{
    std::ostringstream msg;
    log_impl(msg, args...);
    callback->dosomething(level, msg.str().c_str()); // some api
}

struct MyCallback : Callback
{
	void dosomething(uint8_t level, const char *msg) override { std::cout << "[" << int(level) << "]: " << msg << std::endl; }
};

int main()
{
	MyCallback cb;
	callback = &cb;

	log(1, "Hello ", "World", '!', " ", 12345);

	return 0;
}