简体   繁体   中英

How to store template variadic arguments into std::ofstream?

I'm implementing a small Log class in c++

class Log
    {
    public:
        enum LogLevel
        {
            TRACE,
            DEBUG,
            INFO,
            WARNING,
            ERROR,
            FATAL
        };

        Log(): m_log(DEBUG) {} ;
        ~Log() {};

        int SetLogFilePath(const std::string& p_directory, const std::string& p_prefix);

        void SetLogLevel(const LogLevel p_logLvl);

        LogLevel& GetLogLevel();

        template<typename... Args>
        int Logging(const std::string& p_logLevel, const std::string& p_srcFile, const std::string& p_function, const int& p_line,
            const Args&& ... p_args);

    private:
        LogLevel m_log;
        std::string m_logFilePath;
    };

This is my Log class, I store directory and prefix into std::string m_logFilePath

template <typename ... Args>
    int Log::Logging(const std::string& p_logLevel, const std::string& p_srcFile, const std::string& p_function, const int& p_line,
        const Args&&... p_args)
    {
        std::ofstream log;
        log.open(m_logFilePath.c_str(), std::ios::out);
        if(!log.good())
        {
            std::cout << "Couldn't create file : " << m_logFilePath.c_str() << std::endl;
            return 0;
        }
        switch(p_logLevel)
        {
        case "TRACE":
            log << "(TRACE) ";
            break;

        case "DEBUG":
            log << "(DEBUG) ";
            break;

        case "INFO":
            log << "(INFO) ";
            break;

        case "WARNING":
            log << "(WARNING) ";
            break;

        case "ERROR":
            log << "(ERROR) ";
            break;

        case "FATAL":
            log << "(FATAL) ";
            break;

        default: break;
        }
        log << "Log Created at (Local Time): " << std::put_time(std::localtime(std::chrono::system_clock::to_time_t(std::chrono::system_clock::now())), "%c") << " ";
        log << "File Name: " << p_srcFile.c_str() << " " << "Function Name: " << p_function.c_str() << " " << "Line: " << p_line << " " << std::forward<Args>(p_args) << std::endl;
        log.close();
        return 1;
    }

Above is my implementation of int Logging(...) function.

Basically, I store the logging level, current time, source file path, function name , line from code, and some variadic arguments.

I've been searching for a way to store multiple variadic arguments into my std::ostream log but couldn't find any answer.

Please Help!

If I understand correctly, your problem is that you don't know how to manage (in this case: send to an output stream) a variadic list (variadic template based) of arguments.

I propose an example of use that use the power of comma operator in the context of an (unused) array initialization

using unused = int[];

int  cnt { -1 };

(void)unused { 0, (oss << ", extra val "
                       << ++cnt << " [" << args << ']', 0)... };

The following is a simplified, but full working, example

#include <sstream>
#include <iostream>

template <typename ... Args>
std::string  logging (std::string const & valA, std::string const & valB,
                      std::string const & valC, Args const & ... args)
 {
   std::ostringstream oss;

   using unused = int[];

   oss << "valA [" << valA << "], "
       << "valB [" << valB << "], "
       << "valC [" << valC << ']';

   int  cnt { -1 };

   (void)unused { 0, (oss << ", extra val "
                          << ++cnt << " [" << args << ']', 0)... };

   return oss.str();
 }

int main()
 {
   auto l = logging("val1", "val2", "val3", 0, 1L, 2LL, 3U, 4UL, 5ULL,
                    6.0, 7.0f, "eight");

   std::cout << l << std::endl;
 }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM