Program Listing for File Contract.h

↰ Return to documentation for file (ADS/Contract.h)

/*--------------------------------------------------------------------------*/
/*---------------------------- File Contract.h -----------------------------*/
/*--------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------*/
/*----------------------------- DEFINITIONS --------------------------------*/
/*--------------------------------------------------------------------------*/

#ifndef __ADS_Contract
 #define __ADS_Contract
                      /* self-identification: #endif constant */

/*--------------------------------------------------------------------------*/
/*------------------------------ INCLUDES ----------------------------------*/
/*--------------------------------------------------------------------------*/

#include <concepts>
#include <optional>
#include <stdexcept>
#include <string>

/*--------------------------------------------------------------------------*/
/*--------------------------- NAMESPACE ------------------------------------*/
/*--------------------------------------------------------------------------*/

namespace ADS {

#ifndef ADS_CONTRACTS
 #ifdef NDEBUG
  #define ADS_CONTRACTS 0
 #else
  #define ADS_CONTRACTS 1
 #endif
#endif

class contract_violation : public std::logic_error {
 public:
  using std::logic_error::logic_error;
 };

namespace detail {

[[noreturn]] inline void violated( const char * kind , const char * cond ,
                                   const char * func , const char * file ,
                                   int line )
{
 throw( contract_violation( std::string( "ADS: " ) + kind + " ( " + cond +
                            " ) violated in " + func + ", " + file + ":" +
                            std::to_string( line ) ) );
 }

}  // end( namespace detail )

#define ADS_CONTRACT_CHECK( level , kind , cond )                         \
 do {                                                                     \
  if constexpr( ADS_CONTRACTS >= ( level ) )                              \
   if( !( cond ) )                                                        \
    ::ADS::detail::violated( kind , #cond , __func__ , __FILE__ ,         \
                             __LINE__ );                                  \
  } while( false )

#define ADS_PRE( cond ) ADS_CONTRACT_CHECK( 1 , "precondition" , cond )

#define ADS_POST( cond ) ADS_CONTRACT_CHECK( 2 , "postcondition" , cond )

#define ADS_INVARIANT( cond ) ADS_CONTRACT_CHECK( 3 , "invariant" , cond )

#define ADS_AUDIT( cond ) ADS_CONTRACT_CHECK( 3 , "audit" , cond )

/*--------------------------------------------------------------------------*/
/*----------------------- HELPERS OF THE CONDITIONS ------------------------*/
/*--------------------------------------------------------------------------*/

namespace detail {

template< class T >
bool equal( const T & a , const T & b )
{
 if constexpr( std::equality_comparable< T > )
  return( ( a == b ) || ( !( a == a ) && !( b == b ) ) );
 else
  return( true );
 }

template< class X >
std::optional< X > snapshot( const X & x )
{
 if constexpr( ADS_CONTRACTS >= 3 )
  return( x );
 else
  return( std::nullopt );
 }

}  // end( namespace detail )

/*--------------------------------------------------------------------------*/

}  // end( namespace ADS )

/*--------------------------------------------------------------------------*/

#endif  /* Contract.h included */

/*--------------------------------------------------------------------------*/
/*-------------------------- End File Contract.h ---------------------------*/
/*--------------------------------------------------------------------------*/