0

我正在编写一个日志类,它使用源位置作为默认参数。

我想要一个类似 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),主要需要防止不同的线程日志消息交错。

4

0 回答 0