Reputation: 1664
I am rolling my own logging library. The idea is to have an interface class which must be derived from so that an object is able to be logged from.
class LoggedType
{
public:
virtual std::ostream &log (std::ostream &) const = 0;
};
Then the Log class will implement operator<< and for LoggedType use the log method. For everything else will use the normal operator<<.:
typedef std::basic_ostream<char, std::char_traits<char> > CoutType;
typedef CoutType &(*StandardEndLine)(CoutType&);
class Log
{
public:
Log (std::ostream &);
Log (const std::string &);
~Log ();
private:
std::ostream *os;
bool file_p;
friend Log &operator<< (Log &l, const LoggedType &t)
{
t.log (*l.os);
return l;
}
template <typename T>
friend Log &operator<< (Log &l, const T &t)
{
*l.os << t;
return l;
}
friend Log &operator<< (Log &log, StandardEndLine manip)
{
manip (*(log.os));
return log;
}
};
I am getting errors as LoggedType classes are also being matched to the templated operator<<, when only non LoggedType classes should use that template.
How to best fix this?
Upvotes: 0
Views: 175
Reputation: 217930
You may change your template function to use SFINAE:
template <typename T>
friend
typename std::enable_if<!std::is_base_of<LoggedType, T>::value, Log &>::type
operator<< (Log &l, const T &t);
Upvotes: 1