123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327 |
- /*!
- @file
- Defines macros to perform different kinds of assertions.
- Copyright Louis Dionne 2013-2022
- Distributed under the Boost Software License, Version 1.0.
- (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
- */
- #ifndef BOOST_HANA_ASSERT_HPP
- #define BOOST_HANA_ASSERT_HPP
- #include <boost/hana/concept/constant.hpp>
- #include <boost/hana/config.hpp>
- #include <boost/hana/detail/preprocessor.hpp>
- #include <boost/hana/if.hpp>
- #include <boost/hana/value.hpp>
- #include <cstdio>
- #include <cstdlib>
- #if defined(BOOST_HANA_DOXYGEN_INVOKED)
- //! @ingroup group-assertions
- //! Expands to a runtime assertion.
- //!
- //! Given a condition known at runtime, this macro expands to a runtime
- //! assertion similar to the `assert` macro. The provided condition must
- //! be explicitly convertible to a `bool`, and it must not be a model of
- //! the `Constant` concept. If the condition is a `Constant`, a static
- //! assertion will be triggered, asking you to use the
- //! `BOOST_HANA_CONSTANT_ASSERT` macro instead.
- //!
- //! @note
- //! This macro may only be used at function scope.
- # define BOOST_HANA_RUNTIME_ASSERT(condition) unspecified
- //! @ingroup group-assertions
- //! Equivalent to `BOOST_HANA_RUNTIME_ASSERT`, but allows providing a
- //! custom failure message.
- //!
- //! @warning
- //! Conditions that contain multiple comma-separated elements should be
- //! parenthesized.
- # define BOOST_HANA_RUNTIME_ASSERT_MSG(condition, message) unspecified
- //! @ingroup group-assertions
- //! Compile-time assertion for `Constant`s.
- //!
- //! Given a condition known at compile-time in the form of a `Constant`,
- //! this macro expands to a compile-time assertion similar to a `static_assert`.
- //! The provided condition must be a model of the `Constant` concept, in
- //! which case its value is retrieved using `hana::value` and then converted
- //! to a `bool`. If the condition is not a `Constant`, a static assertion
- //! will be triggered, asking you to use the `BOOST_HANA_RUNTIME_ASSERT`
- //! macro instead.
- //!
- //! This macro may be used at global/namespace scope and function scope
- //! only; it may not be used at class scope. Note that the condition may
- //! never be evaluated at runtime. Hence, any side effect may not take
- //! place (but you shouldn't rely on side effects inside assertions anyway).
- # define BOOST_HANA_CONSTANT_ASSERT(condition) unspecified
- //! @ingroup group-assertions
- //! Equivalent to `BOOST_HANA_CONSTANT_ASSERT`, but allows providing a
- //! custom failure message.
- //!
- //! @warning
- //! Conditions that contain multiple comma-separated elements should be
- //! parenthesized.
- # define BOOST_HANA_CONSTANT_ASSERT_MSG(condition, message) unspecified
- //! @ingroup group-assertions
- //! Expands to the strongest form of assertion possible for the given
- //! condition.
- //!
- //! Given a condition, `BOOST_HANA_ASSERT` expands either to a compile-time
- //! or to a runtime assertion, depending on whether the value of the
- //! condition is known at compile-time or at runtime. Compile-time
- //! assertions are always preferred over runtime assertions. If the
- //! condition is a model of the `Constant` concept, its value (retrievable
- //! with `hana::value`) is assumed to be explicitly convertible to `bool`,
- //! and a compile-time assertion is performed on it. Otherwise, the
- //! condition itself is assumed to be explicitly convertible to `bool`,
- //! and a runtime assertion is performed on it.
- //!
- //! If the assertion can be carried out at compile-time, the condition
- //! is not guaranteed to be evaluated at runtime at all (but it may).
- //! Hence, in general, you shouldn't rely on side effects that take place
- //! inside an assertion.
- //!
- //! @note
- //! This macro may only be used at function scope.
- # define BOOST_HANA_ASSERT(condition) unspecified
- //! @ingroup group-assertions
- //! Equivalent to `BOOST_HANA_ASSERT`, but allows providing a custom
- //! failure message.
- //!
- //! @warning
- //! Conditions that contain multiple comma-separated elements should be
- //! parenthesized.
- # define BOOST_HANA_ASSERT_MSG(condition, message) unspecified
- //! @ingroup group-assertions
- //! Expands to a static assertion or a runtime assertion, depending on
- //! whether `constexpr` lambdas are supported.
- //!
- //! This macro is used to assert on a condition that would be a constant
- //! expression if constexpr lambdas were supported. Right now, constexpr
- //! lambdas are not supported, and this is always a runtime assertion.
- //! Specifically, this is equivalent to `BOOST_HANA_RUNTIME_ASSERT`.
- # define BOOST_HANA_CONSTEXPR_ASSERT(condition) unspecified
- //! @ingroup group-assertions
- //! Equivalent to `BOOST_HANA_CONSTEXPR_ASSERT`, but allows providing a
- //! custom failure message.
- # define BOOST_HANA_CONSTEXPR_ASSERT_MSG(condition, message) unspecified
- #elif defined(BOOST_HANA_CONFIG_DISABLE_ASSERTIONS)
- # define BOOST_HANA_CONSTANT_ASSERT(...) /* nothing */
- # define BOOST_HANA_CONSTANT_ASSERT_MSG(condition, message) /* nothing */
- # define BOOST_HANA_RUNTIME_ASSERT(...) /* nothing */
- # define BOOST_HANA_RUNTIME_ASSERT_MSG(condition, message) /* nothing */
- # define BOOST_HANA_ASSERT(...) /* nothing */
- # define BOOST_HANA_ASSERT_MSG(condition, message) /* nothing */
- # define BOOST_HANA_CONSTEXPR_ASSERT(...) /* nothing */
- # define BOOST_HANA_CONSTEXPR_ASSERT_MSG(condition, message) /* nothing */
- #else
- //////////////////////////////////////////////////////////////////////////////
- // BOOST_HANA_RUNTIME_ASSERT and BOOST_HANA_RUNTIME_ASSERT_MSG
- //////////////////////////////////////////////////////////////////////////////
- # define BOOST_HANA_RUNTIME_ASSERT_MSG(condition, message) \
- BOOST_HANA_RUNTIME_CHECK_MSG(condition, message) \
- /**/
- # define BOOST_HANA_RUNTIME_ASSERT(...) \
- BOOST_HANA_RUNTIME_CHECK(__VA_ARGS__) \
- /**/
- //////////////////////////////////////////////////////////////////////////////
- // BOOST_HANA_CONSTANT_ASSERT and BOOST_HANA_CONSTANT_ASSERT_MSG
- //////////////////////////////////////////////////////////////////////////////
- # define BOOST_HANA_CONSTANT_ASSERT_MSG(condition, message) \
- BOOST_HANA_CONSTANT_CHECK_MSG(condition, message) \
- /**/
- # define BOOST_HANA_CONSTANT_ASSERT(...) \
- BOOST_HANA_CONSTANT_CHECK(__VA_ARGS__) \
- /**/
- //////////////////////////////////////////////////////////////////////////////
- // BOOST_HANA_ASSERT and BOOST_HANA_ASSERT_MSG
- //////////////////////////////////////////////////////////////////////////////
- # define BOOST_HANA_ASSERT_MSG(condition, message) \
- BOOST_HANA_CHECK_MSG(condition, message) \
- /**/
- # define BOOST_HANA_ASSERT(...) \
- BOOST_HANA_CHECK(__VA_ARGS__) \
- /**/
- //////////////////////////////////////////////////////////////////////////////
- // BOOST_HANA_CONSTEXPR_ASSERT and BOOST_HANA_CONSTEXPR_ASSERT_MSG
- //////////////////////////////////////////////////////////////////////////////
- # define BOOST_HANA_CONSTEXPR_ASSERT_MSG(condition, message) \
- BOOST_HANA_CONSTEXPR_CHECK_MSG(condition, message) \
- /**/
- # define BOOST_HANA_CONSTEXPR_ASSERT(...) \
- BOOST_HANA_CONSTEXPR_CHECK(__VA_ARGS__) \
- /**/
- #endif
- //////////////////////////////////////////////////////////////////////////////
- // BOOST_HANA_RUNTIME_CHECK and BOOST_HANA_RUNTIME_CHECK_MSG
- //////////////////////////////////////////////////////////////////////////////
- //! @ingroup group-assertions
- //! Equivalent to `BOOST_HANA_RUNTIME_ASSERT_MSG`, but not influenced by the
- //! `BOOST_HANA_CONFIG_DISABLE_ASSERTIONS` config macro. For internal use only.
- # define BOOST_HANA_RUNTIME_CHECK_MSG(condition, message) \
- do { \
- auto __hana_tmp = condition; \
- static_assert(!::boost::hana::Constant<decltype(__hana_tmp)>::value,\
- "the expression (" # condition ") yields a Constant; " \
- "use BOOST_HANA_CONSTANT_ASSERT instead"); \
- \
- if (!static_cast<bool>(__hana_tmp)) { \
- ::std::fprintf(stderr, "Assertion failed: " \
- "(%s), function %s, file %s, line %i.\n", \
- message, __func__, __FILE__, __LINE__); \
- ::std::abort(); \
- } \
- } while (false); \
- static_assert(true, "force trailing semicolon") \
- /**/
- //! @ingroup group-assertions
- //! Equivalent to `BOOST_HANA_RUNTIME_ASSERT`, but not influenced by the
- //! `BOOST_HANA_CONFIG_DISABLE_ASSERTIONS` config macro. For internal use only.
- # define BOOST_HANA_RUNTIME_CHECK(...) \
- BOOST_HANA_RUNTIME_CHECK_MSG( \
- (__VA_ARGS__), \
- BOOST_HANA_PP_STRINGIZE(__VA_ARGS__) \
- ) \
- /**/
- //////////////////////////////////////////////////////////////////////////////
- // BOOST_HANA_CONSTANT_CHECK and BOOST_HANA_CONSTANT_CHECK_MSG
- //////////////////////////////////////////////////////////////////////////////
- //! @ingroup group-assertions
- //! Equivalent to `BOOST_HANA_CONSTANT_ASSERT_MSG`, but not influenced by the
- //! `BOOST_HANA_CONFIG_DISABLE_ASSERTIONS` config macro. For internal use only.
- # define BOOST_HANA_CONSTANT_CHECK_MSG(condition, message) \
- auto BOOST_HANA_PP_CONCAT(__hana_tmp_, __LINE__) = condition; \
- static_assert(::boost::hana::Constant< \
- decltype(BOOST_HANA_PP_CONCAT(__hana_tmp_, __LINE__)) \
- >::value, \
- "the expression " # condition " does not yield a Constant; " \
- "use BOOST_HANA_RUNTIME_ASSERT instead"); \
- static_assert(::boost::hana::value< \
- decltype(BOOST_HANA_PP_CONCAT(__hana_tmp_, __LINE__)) \
- >(), message); \
- static_assert(true, "force trailing semicolon") \
- /**/
- //! @ingroup group-assertions
- //! Equivalent to `BOOST_HANA_CONSTANT_ASSERT`, but not influenced by the
- //! `BOOST_HANA_CONFIG_DISABLE_ASSERTIONS` config macro. For internal use only.
- # define BOOST_HANA_CONSTANT_CHECK(...) \
- BOOST_HANA_CONSTANT_CHECK_MSG( \
- (__VA_ARGS__), \
- BOOST_HANA_PP_STRINGIZE(__VA_ARGS__) \
- ) \
- /**/
- //////////////////////////////////////////////////////////////////////////////
- // BOOST_HANA_CHECK and BOOST_HANA_CHECK_MSG
- //////////////////////////////////////////////////////////////////////////////
- //! @ingroup group-assertions
- //! Equivalent to `BOOST_HANA_ASSERT_MSG`, but not influenced by the
- //! `BOOST_HANA_CONFIG_DISABLE_ASSERTIONS` config macro. For internal use only.
- # define BOOST_HANA_CHECK_MSG(condition, message) \
- do { \
- auto __hana_tmp = condition; \
- ::boost::hana::if_(::boost::hana::bool_c< \
- ::boost::hana::Constant<decltype(__hana_tmp)>::value>, \
- [](auto expr) { \
- static_assert(::boost::hana::value<decltype(expr)>(), \
- message); \
- }, \
- [](auto expr) { \
- if (!static_cast<bool>(expr)) { \
- ::std::fprintf(stderr, "Assertion failed: " \
- "(%s), function %s, file %s, line %i.\n", \
- message, __func__, __FILE__, __LINE__); \
- ::std::abort(); \
- } \
- } \
- )(__hana_tmp); \
- } while (false); \
- static_assert(true, "force trailing semicolon") \
- /**/
- //! @ingroup group-assertions
- //! Equivalent to `BOOST_HANA__ASSERT`, but not influenced by the
- //! `BOOST_HANA_CONFIG_DISABLE_ASSERTIONS` config macro. For internal use only.
- # define BOOST_HANA_CHECK(...) \
- BOOST_HANA_CHECK_MSG( \
- (__VA_ARGS__), \
- BOOST_HANA_PP_STRINGIZE(__VA_ARGS__) \
- ) \
- /**/
- //////////////////////////////////////////////////////////////////////////////
- // BOOST_HANA_CONSTEXPR_CHECK and BOOST_HANA_CONSTEXPR_CHECK_MSG
- //////////////////////////////////////////////////////////////////////////////
- #if defined(BOOST_HANA_DOXYGEN_INVOKED)
- //! @ingroup group-assertions
- //! Equivalent to `BOOST_HANA_CONSTEXPR_ASSERT_MSG`, but not influenced by
- //! the `BOOST_HANA_CONFIG_DISABLE_ASSERTIONS` config macro.
- //! For internal use only.
- # define BOOST_HANA_CONSTEXPR_CHECK_MSG(condition, message) implementation-defined
- //! @ingroup group-assertions
- //! Equivalent to `BOOST_HANA_CONSTEXPR_ASSERT`, but not influenced by the
- //! `BOOST_HANA_CONFIG_DISABLE_ASSERTIONS` config macro.
- //! For internal use only.
- # define BOOST_HANA_CONSTEXPR_CHECK(...) implementation-defined
- #elif defined(BOOST_HANA_CONFIG_HAS_CONSTEXPR_LAMBDA)
- # define BOOST_HANA_CONSTEXPR_CHECK_MSG(condition, message) \
- static_assert(condition, message) \
- /**/
- # define BOOST_HANA_CONSTEXPR_CHECK(...) \
- static_assert((__VA_ARGS__), BOOST_HANA_PP_STRINGIZE(__VA_ARGS__)) \
- /**/
- #else
- # define BOOST_HANA_CONSTEXPR_CHECK_MSG(condition, message) \
- BOOST_HANA_RUNTIME_CHECK_MSG(condition, message) \
- /**/
- # define BOOST_HANA_CONSTEXPR_CHECK(...) \
- BOOST_HANA_CONSTEXPR_CHECK_MSG( \
- (__VA_ARGS__), \
- BOOST_HANA_PP_STRINGIZE(__VA_ARGS__) \
- ) \
- /**/
- #endif
- #endif // !BOOST_HANA_ASSERT_HPP
|