Food for thought.
Code:
#include <cstring>
#include <boost/utility/result_of.hpp>
struct condition_violation_exception
{
condition_violation_exception(const char *file_p, int line_p)
: line(line_p)
{
std::strncpy(file, file_p, sizeof(file) - 1);
file[255] = '\0';
}
char file[256];
int line;
};
struct precondition_violation : public condition_violation_exception
{
precondition_violation(const char *file_p, int line_p)
: condition_violation_exception(file_p, line_p)
{
}
};
struct postcondition_violation : public condition_violation_exception
{
postcondition_violation(const char *file_p, int line_p)
: condition_violation_exception(file_p, line_p)
{
}
};
template <typename F, typename Pre, typename Post, typename Result>
struct eval_s
{
static Result eval(F func_p, Pre pre_p, Post post_p)
{
if(!pre_p()) throw precondition_violation(__FILE__, __LINE__);
Result r = func_p();
if(!post_p()) throw postcondition_violation(__FILE__, __LINE__);
return r;
}
};
template <typename F, typename Pre, typename Post>
struct eval_s<F, Pre, Post, void>
{
static void eval(F func_p, Pre pre_p, Post post_p)
{
if(!pre_p()) throw precondition_violation(__FILE__, __LINE__);
func_p();
if(!post_p()) throw postcondition_violation(__FILE__, __LINE__);
}
};
#ifndef NDEBUG
template <typename F, typename Pre, typename Post>
typename boost::result_of<F>::type eval(F func_p, Pre pre_p, Post post_p)
{
return eval_s<F, Pre, Post, typename boost::result_of<F>::type>::
eval(func_p, pre_p, post_p);
}
#else
template <typename F, typename Pre, typename Post>
typename boost::result_of<F>::type eval(F func_p, Pre pre_p, Post post_p)
{
return func_p();
}
#endif
inline bool no_conditions()
{
return true;
}
Questions to ask yourself:
1. Why have two classes: precondition_violation and postcondition_violation, which are identical?
2. Why is there a need for the eval_s indirection? What am I trying to do that I cannot do with a template function?
3. What happens to the condition checks if NDEBUG is defined?
4. After answering #2, how come the same problem doesn't crop up in eval<F, Pre, Post>() when NDEBUG is defined?
5. Are there any bugs?
6. Is there any point?