I wrote a simple wrapper for the logging interface, so I can use left-shift operator<< to print log.
logger_wrapper.h
class LoggerWrapper
{
public:
LoggerWrapper(logging::LoggerInterface *logger, logging::LogPriority priority);
~LoggerWrapper();
bool log_enabled();
std::stringstream& get_stream();
private:
std::stringstream stream_;
logging::LoggerInterface *logger_;
logging::LogPriority priority_;
};
template <typename T>
LoggerWrapper& operator<<(LoggerWrapper& record, T&& t) {
if (record.log_enabled())
{
record.get_stream() << std::forward<T>(t);
}
return record;
}
template <typename T>
LoggerWrapper& operator<<(LoggerWrapper&& record, T&& t)
{
return record << std::forward<T>(t);
}
logger_wrapper.cpp
#include "logger_wrapper.h"
LoggerWrapper::LoggerWrapper(logging::LoggerInterface *logger, logging::LogPriority priority)
: logger_{ logger }
, priority_ { priority }
{
}
bool LoggerWrapper::log_enabled()
{
return (nullptr != logger_) && (logger_->isLogPriorityEnable(priority_));
}
std::stringstream& LoggerWrapper::get_stream()
{
return stream_;
}
LoggerWrapper::~LoggerWrapper()
{
if (log_enabled())
{
logger_->log(priority_, stream_.str());
}
}
The code was compiled successfully, but I had some MISRA warning:
M5.17.1 (required): Missing overload for corresponding assignment version of operator (operator<<<basic_string&>())
M5.17.1 (required): Missing overload for corresponding assignment version of operator (operator<<<basic_string<char,char_traits<char>,allocator<char>>>())
M5.17.1 (required): Missing overload for corresponding assignment version of operator (operator<<<const atomic&>())
M5.17.1 (required): Missing overload for corresponding assignment version of operator (operator<<<const basic_string&>())
M5.17.1 (required): Missing overload for corresponding assignment version of operator (operator<<<const char (&)[10]>())
...
According to MISRA C 2008, Rule M-5-17-1 states that:
The semantic equivalence between a binary operator and its assignment operator form shall be preserved.
I hope someone can explain me what the warnings mean and what I should do to remove it. Any reply is greatly appreciated. Thank you.
CodePudding user response:
The MISRA guideline essentially says that "For any binary operator (call it @
), if you overload operator@()
for your class then also overload the operator@=()
, and ensure they behave consistently". The purpose is to ensure that (where x
is an instance of your class).
x = x @ y; // @ may represent , - , <<, *, /, .....
has the same net effect as (i.e. is consistent with).
x @= y;
In your case, your class has (templated) overloads of operator<<()
but no corresponding overloads of operator<<=()
.
One way to stop the warnings is to provide corresponding overloads of operator<<=()
whenever you provide an operator<<()
(or vice versa).
For example, provide a operator<<=()
template <typename T>
LoggerWrapper& operator<<=(LoggerWrapper& record, T&& t)
{
if (record.log_enabled())
{
record.get_stream() << std::forward<T>(t);
}
return record;
}
and (to ensure the required consistency), use the approach of defining the operator<<()
so it calls the operator<<=()
.
template <typename T>
LoggerWrapper& operator<<(LoggerWrapper& record, T&& t)
{
return operator<<=(record, t);
}