diff --git a/include/fast_float/float_common.h b/include/fast_float/float_common.h index 77e3e59..468458d 100644 --- a/include/fast_float/float_common.h +++ b/include/fast_float/float_common.h @@ -122,8 +122,10 @@ && FASTFLOAT_HAS_BIT_CAST \ && __cpp_lib_constexpr_algorithms >= 201806L /*For std::copy and std::fill*/ #define FASTFLOAT_CONSTEXPR20 constexpr +#define FASTFLOAT_IS_CONSTEXPR 1 #else #define FASTFLOAT_CONSTEXPR20 +#define FASTFLOAT_IS_CONSTEXPR 0 #endif namespace fast_float { diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 223c9e1..2dc784e 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -60,7 +60,13 @@ fast_float_add_cpp_test(rcppfastfloat_test) fast_float_add_cpp_test(example_test) fast_float_add_cpp_test(example_comma_test) fast_float_add_cpp_test(basictest) -target_compile_features(basictest PRIVATE cxx_std_17) +option(FASTFLOAT_CONSTEXPR_TESTS "Constexpr tests" OFF) +if (FASTFLOAT_CONSTEXPR_TESTS) + target_compile_features(basictest PRIVATE cxx_std_20) + target_compile_definitions(basictest PRIVATE FASTFLOAT_CONSTEXPR_TESTS) +else() + target_compile_features(basictest PRIVATE cxx_std_17) +endif() fast_float_add_cpp_test(long_test) fast_float_add_cpp_test(powersoffive_hardround) diff --git a/tests/basictest.cpp b/tests/basictest.cpp index 433a9b5..4fe391f 100644 --- a/tests/basictest.cpp +++ b/tests/basictest.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #ifndef SUPPLEMENTAL_TEST_DATA_DIR @@ -614,7 +615,44 @@ void basic_test(float val) { } } +namespace { +template +struct dummy {}; + +template +struct verify_error; +} //anonymous namespace + +#if defined(FASTFLOAT_CONSTEXPR_TESTS) +#if !FASTFLOAT_IS_CONSTEXPR +#error "from_chars must be constexpr for constexpr tests" +#endif + +// Add constexpr testing to verify when the arguments are constant expressions +#define verify(lhs, rhs) \ + { \ + INFO(lhs); \ + basic_test(lhs, rhs); \ + [&]() { \ + if constexpr (requires { \ + typename ::dummy<(T(lhs), 0)>; \ + typename ::dummy<((void)(rhs), 0)>; \ + }) { \ + constexpr auto sv = T(lhs); \ + constexpr auto val = [&] { \ + ::std::remove_cvref_t ret; \ + (void)::fast_float::from_chars(sv.data(), sv.data() + sv.size(), \ + ret); \ + return ret; \ + }(); \ + static_assert(val == (rhs)); \ + } \ + }.operator()<::std::string_view>(); \ + } +#else #define verify(lhs, rhs) { INFO(lhs); basic_test(lhs, rhs); } +#endif + #define verify32(val) { INFO(#val); basic_test(val); } #define verify_options(lhs, rhs) { INFO(lhs); basic_test(lhs, rhs, options); }