/* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * Copyright 2010-2019 Danny Robson */ #pragma once #include "./assert.hpp" /////////////////////////////////////////////////////////////////////////////// namespace cruft::debug { /////////////////////////////////////////////////////////////////////////// // returns true if an instance of type `T' appears to be in a valid state. // // written as a struct rather than a function so that behaviour may be // partially specialised. all users are free to specialise this struct // with an user types. // // all specialisations must be safe to call on arbitrary data without // exceptions or faults as this mechanism is used to control some // debugging paths which themselves are the configuration points for // throwing/logging/etc behaviour. // // ArgsT is an optional set of auxiliary values that are required to // validate the target value. template struct validator { static bool is_valid (T const&, ArgsT const&...) noexcept; }; //------------------------------------------------------------------------- template bool is_valid (const T &t, const ArgsT &...args) noexcept { return validator::is_valid (t, args...); } //------------------------------------------------------------------------- // forwarding validator from a pointer type to a reference type. // // null pointers are assumed to be invalid template struct validator { static bool is_valid (const T *val, ArgsT const &...args) noexcept { return val && ::cruft::debug::is_valid (*val, args...); } }; /////////////////////////////////////////////////////////////////////////// // asserts that an instance of type `T' is in a valid state. // // behaviour will be controlled by NDEBUG and other assertion machinery and // so may be optimised out entirely in optimised builds. template void sanity (const T &t) { (void)t; CHECK (is_valid (t)); } //------------------------------------------------------------------------- template < template class T, typename ...Args > void sanity (const T &t) { (void)t; CHECK (is_valid (t)); } template class scoped_sanity { public: scoped_sanity (ValueT &_value): m_value (_value) { sanity (m_value); } ~scoped_sanity () { sanity (m_value); } private: const ValueT& m_value; }; };