Add mstd::is_constant_evaluated

GCC 9 and sufficiently-new Clang (including ARM Compiler 6.13) give us
access to the C++20 (draft) `is_constant_evaluated` test. Allows us to
restrict code to compile-time only.

This is particularly useful when using assembler intrinsics, which the
compiler cannot optimise or compile-time evaluate. It allows us to write
something like

    constexpr uint32_t reverse_bits(uint32_t x)
    {
        if (is_constant_evaluated(x)) {
            // C code to do calculation here
            return x;
        } else {
            // an assembler intrinsic that cannot be optimised
            return __RBIT(x);
        }
    }

This can then be totally compile-time given a constant input.

(In this example, ultimately it would be a good idea to include this
functionality in CMSIS's GCC `__RBIT`, which needs it because GCC
requires use of assembler. Clang implements `__RBIT` as a built-in,
meaning it can already compute it at compile-time, so does not benefit.).
pull/11897/head
Kevin Bracey 2019-11-19 14:19:26 +02:00
parent 04f929e85f
commit 07d43b72d2
1 changed files with 24 additions and 0 deletions

View File

@ -47,6 +47,7 @@
* - mstd::is_invocable, mbed::is_invocable_r, etc
* - mstd::invoke_result
* - logical operator traits (mstd::conjunction, mstd::disjunction, mstd::negation)
* - mstd::is_constant_evaluated
*/
#include <mstd_cstddef>
@ -1361,6 +1362,29 @@ struct is_nothrow_invocable_r : impl::is_invocable_r<R, invoke_result<F, Args...
#endif // __cpp_lib_is_invocable
/* C++20 is_constant_evaluated */
constexpr bool is_constant_evaluated() noexcept
{
#ifdef __clang__
#if __has_builtin(__builtin_is_constant_evaluated)
#define MSTD_HAS_IS_CONSTANT_EVALUATED 1
return __builtin_is_constant_evaluated();
#else
return false;
#endif
#elif __GNUC__ >= 9
#define MSTD_HAS_IS_CONSTANT_EVALUATED 1
return __builtin_is_constant_evaluated();
#else
return false;
#endif
}
#if MSTD_HAS_IS_CONSTANT_EVALUATED
#define MSTD_CONSTEXPR_IF_HAS_IS_CONSTANT_EVALUATED constexpr
#else
#define MSTD_CONSTEXPR_IF_HAS_IS_CONSTANT_EVALUATED
#endif
} // namespace mstd