Skip to content

Commit

Permalink
better compile time error messages for unsupported types
Browse files Browse the repository at this point in the history
  • Loading branch information
dalle committed Nov 22, 2024
1 parent cb1d42a commit 74829bb
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 24 deletions.
4 changes: 2 additions & 2 deletions include/fast_float/fast_float.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ namespace fast_float {
* `scientific`.
*/
template <typename T, typename UC = char,
typename = FASTFLOAT_ENABLE_IF(is_supported_float_type<T>())>
typename = FASTFLOAT_ENABLE_IF(is_supported_float_type<T>::value)>
FASTFLOAT_CONSTEXPR20 from_chars_result_t<UC>
from_chars(UC const *first, UC const *last, T &value,
chars_format fmt = chars_format::general) noexcept;
Expand All @@ -49,7 +49,7 @@ from_chars_advanced(UC const *first, UC const *last, T &value,
* from_chars for integer types.
*/
template <typename T, typename UC = char,
typename = FASTFLOAT_ENABLE_IF(!is_supported_float_type<T>())>
typename = FASTFLOAT_ENABLE_IF(is_supported_integer_type<T>::value)>
FASTFLOAT_CONSTEXPR20 from_chars_result_t<UC>
from_chars(UC const *first, UC const *last, T &value, int base = 10) noexcept;

Expand Down
24 changes: 14 additions & 10 deletions include/fast_float/float_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -202,22 +202,26 @@ fastfloat_really_inline constexpr bool cpp20_and_in_constexpr() {
}

template <typename T>
fastfloat_really_inline constexpr bool is_supported_float_type() {
return std::is_same<T, float>::value || std::is_same<T, double>::value
struct is_supported_float_type
: std::integral_constant<bool, std::is_same<T, float>::value ||
std::is_same<T, double>::value
#if __STDCPP_FLOAT32_T__
|| std::is_same<T, std::float32_t>::value
|| std::is_same<T, std::float32_t>::value
#endif
#if __STDCPP_FLOAT64_T__
|| std::is_same<T, std::float64_t>::value
|| std::is_same<T, std::float64_t>::value
#endif
;
}
> {
};

template <typename T> struct is_supported_integer_type : std::is_integral<T> {};

template <typename UC>
fastfloat_really_inline constexpr bool is_supported_char_type() {
return std::is_same<UC, char>::value || std::is_same<UC, wchar_t>::value ||
std::is_same<UC, char16_t>::value || std::is_same<UC, char32_t>::value;
}
struct is_supported_char_type
: std::integral_constant<bool, std::is_same<UC, char>::value ||
std::is_same<UC, wchar_t>::value ||
std::is_same<UC, char16_t>::value ||
std::is_same<UC, char32_t>::value> {};

// Compares two ASCII strings in a case insensitive manner.
template <typename UC>
Expand Down
32 changes: 20 additions & 12 deletions include/fast_float/parse_number.h
Original file line number Diff line number Diff line change
Expand Up @@ -196,9 +196,9 @@ template <typename T, typename UC>
FASTFLOAT_CONSTEXPR20 from_chars_result_t<UC>
from_chars_advanced(parsed_number_string_t<UC> &pns, T &value) noexcept {

static_assert(is_supported_float_type<T>(),
static_assert(is_supported_float_type<T>::value,
"only some floating-point types are supported");
static_assert(is_supported_char_type<UC>(),
static_assert(is_supported_char_type<UC>::value,
"only char, wchar_t, char16_t and char32_t are supported");

from_chars_result_t<UC> answer;
Expand Down Expand Up @@ -285,9 +285,9 @@ FASTFLOAT_CONSTEXPR20 from_chars_result_t<UC>
from_chars_float_advanced(UC const *first, UC const *last, T &value,
parse_options_t<UC> options) noexcept {

static_assert(is_supported_float_type<T>(),
static_assert(is_supported_float_type<T>::value,
"only some floating-point types are supported");
static_assert(is_supported_char_type<UC>(),
static_assert(is_supported_char_type<UC>::value,
"only char, wchar_t, char16_t and char32_t are supported");

chars_format const fmt = detail::adjust_for_feature_macros(options.format);
Expand Down Expand Up @@ -323,8 +323,9 @@ template <typename T, typename UC, typename>
FASTFLOAT_CONSTEXPR20 from_chars_result_t<UC>
from_chars(UC const *first, UC const *last, T &value, int base) noexcept {

static_assert(std::is_integral<T>::value, "only integer types are supported");
static_assert(is_supported_char_type<UC>(),
static_assert(is_supported_integer_type<T>::value,
"only integer types are supported");
static_assert(is_supported_char_type<UC>::value,
"only char, wchar_t, char16_t and char32_t are supported");

parse_options_t<UC> options;
Expand All @@ -337,8 +338,9 @@ FASTFLOAT_CONSTEXPR20 from_chars_result_t<UC>
from_chars_int_advanced(UC const *first, UC const *last, T &value,
parse_options_t<UC> options) noexcept {

static_assert(std::is_integral<T>::value, "only integer types are supported");
static_assert(is_supported_char_type<UC>(),
static_assert(is_supported_integer_type<T>::value,
"only integer types are supported");
static_assert(is_supported_char_type<UC>::value,
"only char, wchar_t, char16_t and char32_t are supported");

chars_format const fmt = detail::adjust_for_feature_macros(options.format);
Expand All @@ -359,7 +361,11 @@ from_chars_int_advanced(UC const *first, UC const *last, T &value,
return parse_int_string(first, last, value, options);
}

template <bool> struct from_chars_advanced_caller {
template <size_t TypeIx> struct from_chars_advanced_caller {
static_assert(TypeIx > 0, "unsupported type");
};

template <> struct from_chars_advanced_caller<1> {
template <typename T, typename UC>
FASTFLOAT_CONSTEXPR20 static from_chars_result_t<UC>
call(UC const *first, UC const *last, T &value,
Expand All @@ -368,7 +374,7 @@ template <bool> struct from_chars_advanced_caller {
}
};

template <> struct from_chars_advanced_caller<false> {
template <> struct from_chars_advanced_caller<2> {
template <typename T, typename UC>
FASTFLOAT_CONSTEXPR20 static from_chars_result_t<UC>
call(UC const *first, UC const *last, T &value,
Expand All @@ -381,8 +387,10 @@ template <typename T, typename UC>
FASTFLOAT_CONSTEXPR20 from_chars_result_t<UC>
from_chars_advanced(UC const *first, UC const *last, T &value,
parse_options_t<UC> options) noexcept {
return from_chars_advanced_caller<is_supported_float_type<T>()>::call(
first, last, value, options);
return from_chars_advanced_caller<
size_t(is_supported_float_type<T>::value) +
2 * size_t(is_supported_integer_type<T>::value)>::call(first, last, value,
options);
}

} // namespace fast_float
Expand Down

0 comments on commit 74829bb

Please sign in to comment.