X3J16/94-0085, WG21/N0472 1 Doc No: X3J16/94-0085, WG21/N0472 Date: 27 May 94 Project: Programming Language C++ Reply to: Michael J. Vilot ObjectCraft, Inc. 7 Colby Ct., suite #4P321 Bedford NH USA 03110P6427 mjv@objects.mv.com Standard Assertion Component 1. Introduction This proposal is for a standard assertion template. This component standardizes a consistent approach to error detection and reporting. It encourages the use of preconditions and invariants in C++ programs, and works well with the standard exceptions in the Standard C++ library. This proposal is a simpler alternative to 92P0030/N0107, RA Proposal for an Assertion Mechanism based on Exceptions,S by Philippe Gautron. It specifies no interaction, nor conflict, with the assert and NDEBUG macros from the Standard C library. 2. Proposal Add the header to the list of C++ headers. Add the following subclause: 17.3. Diagnostics [lib.diagnostics] This subclause describes diagnostic facilities available to C++ programs. Summary: Header Name Type assertion class template NDEBUG macro assert macro 17.3.1. Header [lib.header.assertion] The class assertion is an applicative template class (_lib.utilities_). template< class B = bool, class E = exception, class S = string > class assertion { public: void operator()( B expr, const S& msg) const throw( E ); }; Template arguments: B: Type of expression to evaluate. Shall be convertable to bool.(_conv.bool_). E: Type of exception to throw. Shall accept type const S& as a constructor argument. S: Type of messageto include in the exception. Observer functions:1 template void assertion::operator()(B expr, const S& msg) const throw(E); Requires: expr to evaluate true. Effects: evaluates expr and returns. Throws: E(msg) if expr evaluates false. 3. Discussion A typical implementation would be: template inline void assertion::operator()(B expr, const S& msg) throw(E) { if (!expr) throw E(msg); } A typical use might be: template void dyn_array::put(size_t pos, const T& obj) { assertion(pos(posrep[pos] = obj; } Another use might be: #include class invariant_error; class invariant : std::assertion {}; void my_f() throw (invariant_error) { invariant(i!=0, "i == 0"); // ... } Assertions are usually thought of as functions. However, $14.6 (_temp.param_) &5 states: RA function template may not have default template arguments.S Therefore, we use an applicative class. This assertion template addresses one concern with 92P0030/N0107: In that proposal, the exception object had to be constructed before, and referenced by, the assertion P even if the exception was never needed. In this proposal, the exception object is only constructed if it must be thrown. On the other hand, this proposal causes a temporary (albeit specious) assertion object to be constructed for each operator() call. One issue not addressed by this proposal was suppressing assertions via the NDEBUG macro. This issue is part of the larger discussion on exception suppression (see: 94-0081/N0468, ROn Suppressing ExceptionsS). 1This proposal does not specify a default constructor, destructor, copy constructor, nor assignment operator. These can be generated by the implementation ($12.1, _class.ctor_, $12.8, _class.copy_). Since this applicative template class is stateless, copying and assignment are harmless, and this proposal does not specify them as private members.