Skip to content

Instantly share code, notes, and snippets.

@pparuzel
Last active January 13, 2022 09:10
Show Gist options
  • Save pparuzel/e2193d12177f8302dc716b4665726b84 to your computer and use it in GitHub Desktop.
Save pparuzel/e2193d12177f8302dc716b4665726b84 to your computer and use it in GitHub Desktop.
Force compile-time evaluation of expressions (no macros)
#ifdef cxx20
#include <concepts>
template <typename Functor>
requires requires (Functor f)
{
{ f() } -> std::same_as<void>;
}
constexpr void const_eval(Functor f)
{
static_assert((f(), true), "failed to evaluate at compile-time");
}
template <typename Functor>
[[nodiscard]] constexpr auto const_eval(Functor f)
{
constexpr auto result = f();
return result;
}
#endif // cxx20
#ifdef cxx20_noconcepts
#include <type_traits> // std::is_same
#include <utility> // std::declval
template <typename Functor>
requires std::is_same_v<decltype(std::declval<Functor>()()), void>
constexpr void const_eval(Functor f)
{
static_assert((f(), true), "failed to evaluate at compile-time");
}
template <typename Functor>
[[nodiscard]] constexpr auto const_eval(Functor f)
{
constexpr auto result = f();
return result;
}
#endif // cxx20_noconcepts
#ifdef cxx17
#include <type_traits> // std::is_same
#include <utility> // std::declval
namespace detail
{
template <typename Functor>
constexpr void const_eval(Functor f, std::true_type)
{
static_assert((f(), true), "failed to evaluate at compile-time");
}
template <typename Functor>
[[nodiscard]] constexpr auto const_eval(Functor f, std::false_type)
{
constexpr auto result = f();
return result;
}
} // namespace detail
template <typename Functor>
[[nodiscard]] constexpr auto const_eval(Functor f)
{
return detail::const_eval(f, typename std::is_same<decltype(std::declval<Functor>()()), void>::type{});
}
#endif // cxx17
// Usage
#include <limits>
int main()
{
using TestedType = unsigned; // compiles
// using TestedType = int; // does not compile - disallowed compile-time undefined behavior
const_eval([] {
auto i = std::numeric_limits<TestedType>::max();
while (i != std::numeric_limits<TestedType>::min())
{
++i;
}
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment