All exception functionalities are inside this namespace
.
More...
Classes | |
class | Exception |
Base protocol class for all exceptions. More... | |
class | ExceptionImpl |
Concrete template class which implements Exception's pure virtual methods. More... | |
Typedefs | |
typedef ExceptionImpl < ::std::runtime_error, Error > | RuntimeError |
typedef ExceptionImpl < ::std::logic_error, Logic > | LogicError |
Functions | |
::std::ostream & | operator<< (::std::ostream &os, const Exception &exception) |
ostream operator<<() for Exception. | |
template<typename LhsType , typename RhsType > | |
LhsType & | operator& (const LhsType &lhs, const RhsType &rhs) |
Non member operator& for exceptions. |
All exception functionalities are inside this namespace
.
This namespace was created mainly to surround operator& which, otherwise, could conflict with the standard bitwise and operator, &
.
The main class
es inside this namespace
are exception::Exception, exception::RuntimeError and exception::LogicError. They are all exported to the outer namespace
, namely, keyvalue.
::std::ostream& keyvalue::exception::operator<< | ( | ::std::ostream & | os, | |
const Exception & | exception | |||
) |
ostream operator<<() for Exception.
LhsType& keyvalue::exception::operator& | ( | const LhsType & | lhs, | |
const RhsType & | rhs | |||
) |
Non member operator& for exceptions.
This function appends data to an ExceptionImpl by forwarding the call to ExceptionImpl::operator&. Additionally, this function provides two services:
const
-ness away: Consider this typical use of operator&:
throw RuntimeError() & "Invalid price."
Notice that the RuntimeError object is a temporary and, thus, automatically qualified as const
. This const
-ness must be casted away inside this function since the 'temporary' must change.
class
es derived from any instantiation of ExceptionImpl inherit ExceptionImpl::operator& which returns a reference to the base class
. This causes a problem when throwing derived objects which make use of ExceptionImpl::operator&. For instance, recall that Repository::NotFound derives from RuntimeError which is an instantiation of ExceptionImpl and consider the following piece of code:try { throw Repository::NotFound() & "Foo"; } catch(Repository::NotFound&) { // do something }
If the operator& above is the ExceptionImpl's member, then the result of Repository::NotFound() & "Foo"
is an ExceptionImpl and not a Repository::NotFound. Hence, the catch
block will not be executed.
The type of the left operand of operator& given here is a template
parameter. Hence, this function provides a better type match to Repository::NotFound than ExceptionImpl::operator& because the latter needs to up cast the left operand. Moreover, this function can return the same type of its left operand. We conclude that this function takes precedence over ExceptionImpl::operator& and its result has same type as its left operand. Therefore, the issue described above vanishes.
Last but not least. This class
is inside the namespace
exception. Thanks to Koenig look-up (a.k.a. ADL), it prevents name clashes with the bitwise 'AND' operator &.
LhsType | : (template parameter) Type of left operand; | |
RhsType | : (template parameter) Type of right operand; | |
lhs | : Left operand; | |
rhs | : Left operand. |
const
reference to the result of lhs.operator&(rhs).