 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Gregory Guest
|
Posted: Fri Dec 29, 2006 2:00 am Post subject: Enforcements are even more convenient |
|
|
In their article published in C/C++ Users Journal, June 2003 Andrei
Alexandrescu and Petru Marginean
(http://www.ddj.com/dept/cpp/184403864) elaborated ENFORCE
macro that exploits policy-based paradigm. The ENFORCE macro enables to
write
error checking code, error message formatting and exception throwing
all in a single line.
Using this macro one can write the following code:
Widget* pWidget = MakeWidget();
ENFORCE(pWidget);
Or even more powerful:
int n = ...;
Widget* pWidget = MakeWidget(n);
ENFORCE(pWidget)("Widget number ")(n)(" is null and it shouldn't!");
The last one will check whether the pWidget is null and if so will
accumulate the formatted error message and finally throw the exception
using the entire message. All this is done behind the scene.
Everything is very cool besides one thing that writing the formatted
string using the templated
operator() is not very convenient and intuitive. I was looking for a
way of re-writing the above ENFORCE code in the more usual and
intuitive way:
ENFORCE(pWidget) << "Widget number " << n << " is null and it
shouldn't!";
It turns out that very small changes to the code presented in the
article and very small overhead
can make the life more happy :-)
Andrei and Petru used the following ENFORCE macro in the article:
#define ENFORCE(exp) \
*MakeEnforcer<DefaultPredicate, DefaultRaiser>(\
(exp), "Expression '" #exp "' failed in '" \
__FILE__ "', line: " STRINGIZE(__LINE__))
In brief (more details can be found in the article) the MakeEnforcer
templated function creates and returns Enforcer object then if error
messages are added with Enforcer::operator() they will be accumulated
within the Enforcer object (only if the exp macro parameter specifies
errorneous expression) and finally Enforcer::operator*() will throw an
exception (again only if necessary).
I suggest small changes to the above macro to achieve the convenience
of << error message formatting. The modified ENFORCE macro and one
small additional class look this way:
class Thrower
{
public:
template<typename Ref, typename P, typename R>
Thrower& operator = (const Enforcer<Ref, P, R>& enforcer)
{
*enforcer;
return *this;
}
};
#define ENFORCE(exp) \
Thrower() = MakeEnforcer<DefaultPredicate, DefaultRaiser>(\
(exp), "Expression '" #exp "' failed in '" \
__FILE__ "', line: " STRINGIZE(__LINE__))
I also replace the templated Enforce::operator() that accumulates error
messages with the templated Enforce::operator<<() that does exactly the
same.
template <class MsgType>
Enforcer& operator<<(const MsgType& msg)
{
// The same code as for former Enforce::operator()
}
The new ENFORCE macro as before will first create Enforcer object then
if error messages are added with Enforcer::operator<<() (that was my
goal) they will be accumulated within the Enforcer object and finally
the Enforcer object is passed to the assignment operator of the Thrower
object (that was created) which in turn will invoke
Enforcer::operator*() to throw an exception (if necessary).
The small overhead in this suggested solution is the creation of an
empty Thrower class and calling its assignment operator. Many of us can
live with it in favour of better readability and convenience of using
operator << instead of () to express error message formatting.
By the way Thrower::operator=() above can be replaced with any binary
operator that has precedence lower than operator << (like <=, +=, *=,
<<= and so on), so to enforce (not the same as above ) the right
operators ordering in the ENFORCE macro evaluation.
Regards,
Gregory
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ] |
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|