I have a Exception base class which defines a stream function:
class Exception
{
public:
template <typename TData, typename TException>
TException& stream(const TData& data)
{
stream_ << data;
return *reinterpret_cast<TException*>(this);
}
};
I have a free function overloading operator<<:
template <typename TData>
Exception& operator<<(Exception& ex, const TData& data) {
return ex.stream<TData, Exception>(data);
}
I also have dervied exceptions overloading operator<<:
template <typename TData>
CoffeeException& operator<<(CoffeeException& ex, const TData& data) {
return ex.stream<TData, CoffeeException>(data);
}
I use this like so:
else {
throw CoffeeException() << "Exception text";
}
When I try to use the class the compiler doesn’t see the function, it just suggests the standard stream operators avaiable but doesn’t note my Exception or CoffeeException free functions. Does this implementation look correct?
It looks like the usual problem of trying to bind a temporary to a
non-const reference.
CoffeeException() << "Exception text"can’t bindto your
operator<<, becauseCoffeeException()is a temporary. Justmake your
operator<<a member:While I’m at it: you definitely don’t want the
reinterpret_castat theend of
Exception::stream. Using the results of this cast is undefinedbehavior. It will typically work in cases of single inheritance, but
fail where multiple inheritance is involved (but even that isn’t
guaranteed). The simplest solution is what I’ve done above (and make
Exception::streamreturnvoid); alternatively, usestatic_casthere (which should be legal if the inheritance is defined at the point
of instantiation).