我正在编写一个日志类,它使用源位置作为默认参数。
我想要一个类似 printf 的函数调用,我希望它应该可以使用 CTAD,但在这种情况下,它是用于模板化函数而不是模板化类,因此显然vlog
不是类型(它是函数),因此错误。
不太确定我哪里出错了或者这是否真的可能?
log
采用基本的字符串视图并且工作正常。
vlog
是采用 printf 样式参数列表的“聪明”位,即const char*
不同类型的可变参数。我试图包含尽可能多的代码,以防有更好的方法来做到这一点!
C ++ 17 并提前致谢。
#include <chrono>
#include <experimental/source_location>
#include <mutex>
#include <string_view>
#include <string>
#include <iostream>
namespace LOGGING
{
class Logging
{
using Ms = std::chrono::milliseconds; ///< typename alias
using source_location = std::experimental::source_location; ///< typename alias
constexpr static Ms defalt_mutex_wait{100};
public:
static bool log(const std::string_view& msg,
const source_location& location = source_location::current())
{
if (mutx.try_lock_for(defalt_mutex_wait))
{
std::cout << location.file_name() << "[" << \
location.line() << ":" << \
location.function_name() << "]: " << \
msg;
std::cout << std::endl; // flush
mutx.unlock();
return true;
}
return false;
}
template <typename... T>
static bool vlog(const char*&& fmt, T&&... vars,
const source_location& location = source_location::current())
{
if (mutx.try_lock_for(defalt_mutex_wait))
{
char buf[100]{};
snprintf(buf, sizeof(buf), fmt, vars...);
std::cout << location.file_name() << "[" << \
location.line() << ":" << \
location.function_name() << "]: " << \
buf;
std::cout << std::endl; // flush
mutx.unlock();
return true;
}
return false;
}
template <typename... T>
vlog(const char*, T&&...) -> vlog<T...>;
template<class Rep, class Period>
[[nodiscard]] static bool lock(std::unique_lock<std::recursive_timed_mutex>& lock,
const std::chrono::duration<Rep, Period>& timeout_duration = Ms(100))
{
if (mutx.try_lock_for(timeout_duration))
{
lock = std::move(std::unique_lock<std::recursive_timed_mutex>(mutx));
mutx.unlock();
return true;
}
return false;
}
static bool lock(std::unique_lock<std::recursive_timed_mutex>& lock)
{
lock = std::move(std::unique_lock<std::recursive_timed_mutex>(mutx));
return true;
}
private:
Ms instance_mutex_wait{defalt_mutex_wait};
public:
Logging(void) noexcept = default;
private:
static std::recursive_timed_mutex mutx;
};
inline std::recursive_timed_mutex Logging::mutx{};
inline Logging LOG;
} // namespace LOGGING
int main()
{
using namespace LOGGING;
LOG.log("Hello world!");
LOG.vlog<int>("Value is %d", 42);
LOG.vlog("Value is %d", 42); // HERE
return 0;
}
<source>:58:34: error: 'vlog<T ...>' does not name a type
58 | vlog(const char*, T&&...) -> vlog<T...>;
| ^~~~~~~~~~
<source>:58:44: error: expected constructor, destructor, or type conversion before ';' token
58 | vlog(const char*, T&&...) -> vlog<T...>;
任何感兴趣的人的上下文;它适用于多线程和多核嵌入式系统(ESP32),主要需要防止不同的线程日志消息交错。