C++: How can i create a function that accepts concatenated strings as parameter?

前端 未结 4 1343
猫巷女王i
猫巷女王i 2021-01-18 14:34

Can i design my logging-function in a way, that it accepts concatenated strings of the following form using C++?

int i = 1;
customLoggFunction(\"My Integer i         


        
相关标签:
4条回答
  • 2021-01-18 14:51

    One approach is a simple utility class that uses a standard stream in a templated member function:

    class LogStream {
        public:
            template <class T> LogStream& operator << (const T& rhs) {
                stream << rhs;
                return *this;
            }
    
        private:
            std::stringstream stream;
    };
    

    The stream member doing all the work is then used in the destructor,

    ~LogStream() {
        std::cout << stream.str() << std::endl;
    }
    

    and you can create temporary objects for passing your arguments to be concatenated:

    LogStream() << "anything with std::ostream operator: " << 1.2345 << ' ' << std::hex << 12;
    

    Additional state (e.g. a log level) can be passed to the constructor, often accompagnied by convenience functions like LogStream debug() { return LogStream(...); }. When you reach a certain point of sophistication though, you might want to switch to a logging library of course.

    0 讨论(0)
  • 2021-01-18 15:05

    It's impossible to do with the exact syntax you asked for unless you resort to macros.

    But if you don't mind replacing << with ,, then you can do following:

    #include <iostream>
    #include <string>
    #include <sstream>
    
    void log_impl(const std::string &str)
    {
        std::cout << str;
    }
    
    template <typename ...P> void log(const P &... params)
    {
        std::stringstream stream;
    
        (stream << ... << params);
        // If you don't have C++17, use following instead of the above line:
        // using dummy_array = int[];
        // dummy_array{(void(stream << params), 0)..., 0};
    
        log_impl(stream.str());
    }
    
    int main()
    {
        log("1", 2, '3'); // prints 123
    }
    
    0 讨论(0)
  • 2021-01-18 15:07

    You could do it by defining a new operator<<. From vague memory, implementing functions with these three signatures will do the trick:

    std::string operator<<(const char * a, const std::string & b);
    std::string operator<<(const std::string & a, const char * b);
    std::string operator<<(const std::string & a, const std::string & b);
    

    Each of them has to concatenate its arguments and return a std::string.

    Howeever, it feels wrong. Goes against the grain of C++. I suggest a more C++-ish solution, namely to make your logger into a class, and write operator<<() members for that class, so you can run

    customLog << "My Integer i = " << i << "." << "\n";
    
    0 讨论(0)
  • 2021-01-18 15:14

    For trivial projects this is one of the few things I use a MACRO for. You can do something like this:

    #define LOG(m) do{ std::cout << timestamp() << ": " << m << '\n'; }while(0)
    
    // ...
    
    LOG("error: [" << errno "] " << filename << " does not exist.");
    

    Generally MACROS should be avoided but there is no other way to get precisely this with a standard function. So...

    Note: The empty condition do{...}while(0) enables you to place the MACRO in places that a MACRO usually can't go if it contains multiple statements.

    0 讨论(0)
提交回复
热议问题