Reputation: 4592
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?
Upvotes: 4
Views: 334
Reputation: 153929
It looks like the usual problem of trying to bind a temporary to a
non-const reference. CoffeeException() << "Exception text"
can't bind
to your operator<<
, because CoffeeException()
is a temporary. Just
make your operator<<
a member:
class CoffeeException : public Exception
{
// ...
public:
template <typename TData>
CoffeeException& operator<<( TData const& data )
{
stream( data );
return *this;
}
};
While I'm at it: you definitely don't want the reinterpret_cast
at the
end of Exception::stream
. Using the results of this cast is undefined
behavior. 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::stream
return void
); alternatively, use static_cast
here (which should be legal if the inheritance is defined at the point
of instantiation).
Upvotes: 8
Reputation: 1196
CoffeeException& operator<<(const CoffeeException& ex, const TData& data);
This reference must be const, because you try pass unnamed object. You can also create temporary object to avoid using const reference.
Upvotes: -1