c++verbosity

What is good practice for generating verbose output?


what is good practice for generating verbose output? currently, i have a function

bool verbose;
int setVerbose(bool v)
{
    errormsg = "";
    verbose = v;
    if (verbose == v)
        return 0;
    else
        return -1;
}

and whenever i want to generate output, i do something like

if (debug)
     std::cout << "deleting interp" << std::endl;

however, i don't think that's very elegant. so i wonder what would be a good way to implement this verbosity switch?


Solution

  • The simplest way is to create small class as follows(here is Unicode version, but you can easily change it to single-byte version):

    #include <sstream>
    #include <boost/format.hpp>
    #include <iostream>
    using namespace std;
    
    enum log_level_t {
        LOG_NOTHING,
        LOG_CRITICAL,
        LOG_ERROR,
        LOG_WARNING,
        LOG_INFO,
        LOG_DEBUG
    };
    
    namespace log_impl {
    class formatted_log_t {
    public:
        formatted_log_t( log_level_t level, const wchar_t* msg ) : fmt(msg), level(level) {}
        ~formatted_log_t() {
            // GLOBAL_LEVEL is a global variable and could be changed at runtime
            // Any customization could be here
            if ( level <= GLOBAL_LEVEL ) wcout << level << L" " << fmt << endl;
        }        
        template <typename T> 
        formatted_log_t& operator %(T value) {
            fmt % value;
            return *this;
        }    
    protected:
        log_level_t     level;
        boost::wformat      fmt;
    };
    }//namespace log_impl
    // Helper function. Class formatted_log_t will not be used directly.
    template <log_level_t level>
    log_impl::formatted_log_t log(const wchar_t* msg) {
        return log_impl::formatted_log_t( level, msg );
    }
    

    Helper function log was made template to get nice call syntax. Then it could be used in the following way:

    int main ()
    {
        // Log level is clearly separated from the log message
        log<LOG_DEBUG>(L"TEST %3% %2% %1%") % 5 % 10 % L"privet";
        return 0;
    }
    

    You could change verbosity level at runtime by changing global GLOBAL_LEVEL variable.