cppython
cppython

Reputation: 1279

reduce code duplication in c++

Can I reduce the following code to one function? the most part of them are the same. Thanks

void info(StreamLog &streamLog)
{
    streamLog.ss << "info:";
    streamLog.mFilter->setLogLevel("info");
}
void debug(StreamLog &streamLog)
{
    streamLog.ss << "debug:";
    streamLog.mFilter->setLogLevel("debug");
}
void warning(StreamLog &streamLog)
{
    streamLog.ss << "warning:";
    streamLog.mFilter->setLogLevel("warning");
}
void error(StreamLog &streamLog)
{
    streamLog.ss << "error:";
    streamLog.mFilter->setLogLevel("error");
}
void critical(StreamLog &streamLog)
{
    streamLog.ss << "critical:";
    streamLog.mFilter->setLogLevel("critical");
}

if you need more info,let me know

1st edited: sorry ! I didnt explain my situation clearly. I use those function as manipulator. therefore, i can do

clog << info << ...

clog << warning<<...

I dont want to use

clog << log(info) <<...

any better way? thanks

Upvotes: 0

Views: 210

Answers (3)

Xornand
Xornand

Reputation: 190

Here is an alternative to Mark's & Rémi's solutions using templates. This solution could be useful in areas where high performance is critical. The templates let the compiler bake in a lot of information into each templated function already so there should be a smaller run time cost especially when compared to the map lookup method.

Additionally this will constrain the values for the log_level being used at compile time rather than at run time.

enum class log_level { info, debug, warning, error, critical };
template<log_level> struct log_helper{ static const char* const text; };

template<> const char* const log_helper<log_level::info>::text = "info";
template<> const char* const log_helper<log_level::debug>::text = "debug";
template<> const char* const log_helper<log_level::warning>::text = "warning";
template<> const char* const log_helper<log_level::error>::text = "error";
template<> const char* const log_helper<log_level::critical>::text = "critical";

template<log_level level> void set_log_level(StreamLog& streamLog)
{
    streamLog.ss<< log_helper<level>::text << ":";
    streamLog.mFilter->setLogLevel(log_helper<level>::text);
}

Upvotes: 0

R&#233;mi Benoit
R&#233;mi Benoit

Reputation: 1346

void log(StreamLog &streamLog, const string& level)
{
    streamLog.ss << level << ":";
    streamLog.mFilter->setLogLevel(level);
}

Always try to see the common operation and abstract it in a different function.

Upvotes: 10

Mark Garcia
Mark Garcia

Reputation: 17708

I'm with @Rémi Benoit, though to provide you with an alternative, you can use an enum and a map:

enum log_level {
   info, debug, warning, error, critical
}

void log(StreamLog& streamLog, log_level level) {
   static const std::map<log_level, std::string> levels = {
       { info, "info" }, { debug, "debug" }, { warning, "warning" },
       { error, "error" }, { critical, "critical" }
   };

   auto iter = levels.find(level);
   if(iter == levels.end()) return;

   streamLog.ss << iter->second;
   streamLog.mFilter->setLogLevel(iter->second);
}

The benefit of this is that your log level is limited only to what is in the enum (and the map), though if you do not require this constraint, it is better to use @Rémi's solution.

Upvotes: 2

Related Questions