diff --git a/CHANGELOG.md b/CHANGELOG.md
index bcd3f4b8..5a930019 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -30,6 +30,7 @@ template:
- fixed some `_Float16` detection issues
- fixed `toml::parse_file()` on windows for non-ASCII paths
- added `toml::format_flags::terse_key_value_pairs`
+- added `TOML_ENABLE_FLOAT16` config to fix #178 (@Scrumplex)
diff --git a/README.md b/README.md
index 56f69e5c..8d7afacd 100644
--- a/README.md
+++ b/README.md
@@ -209,6 +209,7 @@ won't need to mess with these at all, but if you do, set them before including t
| `TOML_CALLCONV` | define | Calling convention to apply to exported free/static functions. | undefined |
| `TOML_CONFIG_HEADER` | string literal | Includes the given header file before the rest of the library. | undefined |
| `TOML_ENABLE_FORMATTERS` | boolean | Enables the formatters. Set to `0` if you don't need them to improve compile times and binary size. | `1` |
+| `TOML_ENABLE_FLOAT16` | boolean | Enables support for the built-in `_Float16` type. | per compiler settings |
| `TOML_ENABLE_PARSER` | boolean | Enables the parser. Set to `0` if you don't need it to improve compile times and binary size. | `1` |
| `TOML_ENABLE_UNRELEASED_FEATURES` | boolean | Enables support for [unreleased TOML language features]. | `0` |
| `TOML_ENABLE_WINDOWS_COMPAT` | boolean | Enables support for transparent conversion between wide and narrow strings. | `1` on Windows |
diff --git a/include/toml++/impl/forward_declarations.h b/include/toml++/impl/forward_declarations.h
index 6d110fdf..49f6ac51 100644
--- a/include/toml++/impl/forward_declarations.h
+++ b/include/toml++/impl/forward_declarations.h
@@ -628,9 +628,9 @@ TOML_IMPL_NAMESPACE_START
template
struct float_traits : float_traits_base::digits, std::numeric_limits::digits10>
{};
-#ifdef TOML_FLOAT16
+#if TOML_ENABLE_FLOAT16
template <>
- struct float_traits : float_traits_base
+ struct float_traits<_Float16> : float_traits_base<_Float16, __FLT16_MANT_DIG__, __FLT16_DIG__>
{};
#endif
#ifdef TOML_FLOAT128
@@ -649,9 +649,9 @@ TOML_IMPL_NAMESPACE_START
template <>
struct value_traits : float_traits
{};
-#ifdef TOML_FLOAT16
+#if TOML_ENABLE_FLOAT16
template <>
- struct value_traits : float_traits
+ struct value_traits<_Float16> : float_traits<_Float16>
{};
#endif
#ifdef TOML_FLOAT128
diff --git a/include/toml++/impl/preprocessor.h b/include/toml++/impl/preprocessor.h
index 9cf8e467..7305218c 100644
--- a/include/toml++/impl/preprocessor.h
+++ b/include/toml++/impl/preprocessor.h
@@ -1055,7 +1055,34 @@ TOML_ENABLE_WARNINGS;
//# FLOAT16
//#=====================================================================================================================
-#if TOML_CLANG
+#ifndef TOML_ENABLE_FLOAT16
+
+#ifdef __FLT16_MANT_DIG__
+#define TOML_FLOAT16_MANT_DIG __FLT16_MANT_DIG__
+#define TOML_FLOAT16_DIG __FLT16_DIG__
+#define TOML_FLOAT16_MIN_EXP __FLT16_MIN_EXP__
+#define TOML_FLOAT16_MIN_10_EXP __FLT16_MIN_10_EXP__
+#define TOML_FLOAT16_MAX_EXP __FLT16_MAX_EXP__
+#define TOML_FLOAT16_MAX_10_EXP __FLT16_MAX_10_EXP__
+#else
+#define TOML_FLOAT16_MANT_DIG 0
+#define TOML_FLOAT16_DIG 0
+#define TOML_FLOAT16_MIN_EXP 0
+#define TOML_FLOAT16_MIN_10_EXP 0
+#define TOML_FLOAT16_MAX_EXP 0
+#define TOML_FLOAT16_MAX_10_EXP 0
+#endif
+
+#if (TOML_FLOAT16_MANT_DIG && TOML_FLOAT16_DIG && TOML_FLOAT16_MIN_EXP && TOML_FLOAT16_MIN_10_EXP \
+ && TOML_FLOAT16_MAX_EXP && TOML_FLOAT16_MAX_10_EXP)
+#define TOML_FLOAT16_LIMITS_SET 1
+#else
+#define TOML_FLOAT16_LIMITS_SET 0
+#endif
+
+#if TOML_FLOAT16_LIMITS_SET
+
+#if TOML_CLANG // >= 15
//# {{
// Excerpt from https://clang.llvm.org/docs/LanguageExtensions.html:
//
@@ -1069,9 +1096,10 @@ TOML_ENABLE_WARNINGS;
// X86 as long as SSE2 is available
//
//# }}
-#if (TOML_ARCH_ARM || TOML_ARCH_X86 || TOML_ARCH_AMD64) && defined(__FLT16_MANT_DIG__)
-#define TOML_FLOAT16 _Float16
+#if (TOML_ARCH_ARM || TOML_ARCH_AMD64 || TOML_ARCH_X86)
+#define TOML_ENABLE_FLOAT16 1
#endif
+
#elif TOML_GCC
//# {{
// Excerpt from https://gcc.gnu.org/onlinedocs/gcc/Floating-Types.html:
@@ -1082,13 +1110,25 @@ TOML_ENABLE_WARNINGS;
//
// *** except: the bit about x86 seems incorrect?? ***
//# }}
-/*
-
- */
-#if (TOML_ARCH_ARM /*|| TOML_ARCH_X86 || TOML_ARCH_AMD64*/) && defined(__FLT16_MANT_DIG__)
-#define TOML_FLOAT16 _Float16
+#if (TOML_ARCH_ARM || TOML_ARCH_AMD64 /* || TOML_ARCH_X86*/)
+#define TOML_ENABLE_FLOAT16 1
#endif
+
+#endif // clang/gcc
+
+#endif // TOML_FLOAT16_LIMITS_SET
+
+#endif // !defined(TOML_ENABLE_FLOAT16)
+
+#ifndef TOML_ENABLE_FLOAT16
+#define TOML_ENABLE_FLOAT16 0
#endif
+//# {{
+/// \def TOML_ENABLE_FLOAT16
+/// \brief Enable support for the built-in `_Float16` type.
+/// \detail Default behaviour is to try to determine support based on compiler, architecture and built-in defines, but
+/// you can override it to force-enable/disable support.
+//# }}
//#=====================================================================================================================
//# FLOAT128
diff --git a/include/toml++/toml.h b/include/toml++/toml.h
index f7db954c..8ac1a37f 100644
--- a/include/toml++/toml.h
+++ b/include/toml++/toml.h
@@ -90,8 +90,8 @@ TOML_POP_WARNINGS;
#undef TOML_ANON_NAMESPACE
#undef TOML_ANON_NAMESPACE_END
#undef TOML_ANON_NAMESPACE_START
-#undef TOML_ARCH_ARM
#undef TOML_ARCH_AMD64
+#undef TOML_ARCH_ARM
#undef TOML_ARCH_ARM32
#undef TOML_ARCH_ARM64
#undef TOML_ARCH_ITANIUM
@@ -131,7 +131,13 @@ TOML_POP_WARNINGS;
#undef TOML_FLAGS_ENUM
#undef TOML_FLOAT_CHARCONV
#undef TOML_FLOAT128
-#undef TOML_FLOAT16
+#undef TOML_FLOAT16_DIG
+#undef TOML_FLOAT16_LIMITS_SET
+#undef TOML_FLOAT16_MANT_DIG
+#undef TOML_FLOAT16_MAX_10_EXP
+#undef TOML_FLOAT16_MAX_EXP
+#undef TOML_FLOAT16_MIN_10_EXP
+#undef TOML_FLOAT16_MIN_EXP
#undef TOML_GCC
#undef TOML_HAS_ATTR
#undef TOML_HAS_BUILTIN
diff --git a/meson.build b/meson.build
index c8152253..3dd9735a 100644
--- a/meson.build
+++ b/meson.build
@@ -319,27 +319,11 @@ compiler_supports_consteval_properly = compiler_supports_consteval and not compi
)
#######################################################################################################################
-# __fp16 and _Float16 checks
+# _Float16 checks
#######################################################################################################################
-compiler_supports_float16_args = []
-if is_gcc
- compiler_supports_float16_args += '-mfp16-format=ieee'
-endif
-compiler_supports_fp16 = compiler.links('''
- int main()
- {
- static_assert(sizeof(__fp16) == 2);
- __fp16 f = static_cast<__fp16>(1);
- const auto f2 = static_cast(f);
- const auto f3 = static_cast<__fp16>(0.2L);
- return 0;
- }
- ''',
- name: 'supports __fp16',
- args: compiler_supports_float16_args
-)
-compiler_supports_float16 = compiler.links('''
+compiler_supports_float16_args = compiler.get_supported_arguments('-mfp16-format=ieee')
+compiler_supports_float16 = get_option('float16') and compiler.links('''
int main()
{
static_assert(sizeof(_Float16) == 2);
@@ -352,7 +336,7 @@ compiler_supports_float16 = compiler.links('''
name: 'supports _Float16',
args: compiler_supports_float16_args
)
-if compiler_supports_fp16 or compiler_supports_float16
+if compiler_supports_float16
devel_args += compiler_supports_float16_args
endif
@@ -411,8 +395,8 @@ compiler_supports_float128 = compiler.links('''
name: 'supports __float128'
)
-if compiler_supports_float128 and is_gcc and not is_subproject
- add_global_arguments('-fext-numeric-literals', language: 'cpp')
+if compiler_supports_float16 or compiler_supports_float128 or compiler_supports_int128
+ devel_args += compiler.get_supported_arguments('-fext-numeric-literals')
endif
#######################################################################################################################
diff --git a/meson_options.txt b/meson_options.txt
index 885040ce..13c9a454 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -11,3 +11,4 @@ option('build_tt_encoder', type: 'boolean', value: false, description: 'Enable
option('build_tt_decoder', type: 'boolean', value: false, description: 'Enable to build the toml-test decoder.')
option('compile_library', type: 'boolean', value: false, description: 'Compile as a library')
option('use_vendored_libs', type: 'boolean', value: true, description: 'Use the libs from the vendor dir when building tests.')
+option('float16', type: 'boolean', value: true, description: 'Use _Float16 automatically where available.')
diff --git a/src/meson.build b/src/meson.build
index a49cb1f2..b64ba54b 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -6,6 +6,15 @@ lib_args = ['-DTOML_HEADER_ONLY=0']
if get_option('default_library') != 'static'
lib_args += '-DTOML_SHARED_LIB=1'
endif
+if compiler_supports_float16
+ lib_args += compiler_supports_float16_args
+ lib_args += '-DTOML_ENABLE_FLOAT16=1'
+else
+ lib_args += '-DTOML_ENABLE_FLOAT16=0'
+endif
+if compiler_supports_float16 or compiler_supports_float128 or compiler_supports_int128
+ lib_args += compiler.get_supported_arguments('-fext-numeric-literals')
+endif
lib = library(
meson.project_name(),
diff --git a/tests/impl_toml.cpp b/tests/impl_toml.cpp
index 37c02a66..95a8d92f 100644
--- a/tests/impl_toml.cpp
+++ b/tests/impl_toml.cpp
@@ -64,8 +64,8 @@ namespace toml
CHECK_CAN_REPRESENT_NATIVE(TOML_INT128, true);
CHECK_CAN_REPRESENT_NATIVE(TOML_UINT128, false);
#endif
-#ifdef TOML_FLOAT16
- CHECK_CAN_REPRESENT_NATIVE(TOML_FLOAT16, false);
+#if TOML_ENABLE_FLOAT16
+ CHECK_CAN_REPRESENT_NATIVE(_Float16, false);
#endif
#ifdef TOML_FLOAT128
CHECK_CAN_REPRESENT_NATIVE(TOML_FLOAT128, true);
@@ -289,8 +289,8 @@ namespace toml
CHECK_INSERTED_AS(uint32_t, value);
CHECK_INSERTED_AS(float, value);
CHECK_INSERTED_AS(double, value);
-#ifdef TOML_FLOAT16
- CHECK_INSERTED_AS(TOML_FLOAT16, value);
+#if TOML_ENABLE_FLOAT16
+ CHECK_INSERTED_AS(_Float16, value);
#endif
#define CHECK_NODE_REF_TYPE(T) \
diff --git a/tests/meson.build b/tests/meson.build
index 6c3b8112..97f3cd5b 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -39,13 +39,7 @@ endif
# fast math check
#######################################################################################################################
-compiler_supports_fast_math_args = []
-if is_gcc or is_clang
- compiler_supports_fast_math_args += '-ffast-math'
- compiler_supports_fast_math_args += '-ffp-contract=fast'
-elif is_msvc or is_icc_cl
- compiler_supports_fast_math_args += '/fp:fast'
-endif
+compiler_supports_fast_math_args = compiler.get_supported_arguments('-ffast-math', '-ffp-contract=fast', '/fp:fast')
compiler_supports_fast_math = compiler.links('''
#include
#include
@@ -58,7 +52,6 @@ compiler_supports_fast_math = compiler.links('''
name: 'supports fast-math',
args: compiler_supports_fast_math_args
)
-
#######################################################################################################################
# do the thing!
#######################################################################################################################
diff --git a/tests/tests.h b/tests/tests.h
index 5756a270..3d93069b 100644
--- a/tests/tests.h
+++ b/tests/tests.h
@@ -11,8 +11,8 @@
#else
#include "../include/toml++/toml.h"
#endif
-#if defined(TOML_FLOAT16) ^ SHOULD_HAVE_FLOAT16
-#error TOML_FLOAT16 was not deduced correctly
+#if TOML_ENABLE_FLOAT16 ^ SHOULD_HAVE_FLOAT16
+#error TOML_ENABLE_FLOAT16 was not deduced correctly
#endif
#if defined(TOML_FLOAT128) ^ SHOULD_HAVE_FLOAT128
#error TOML_FLOAT128 was not deduced correctly
diff --git a/toml.hpp b/toml.hpp
index 7171b54d..5e4c7f8c 100644
--- a/toml.hpp
+++ b/toml.hpp
@@ -930,17 +930,51 @@ TOML_ENABLE_WARNINGS;
TOML_REQUIRES(condition)
#define TOML_HIDDEN_CONSTRAINT(condition, ...) TOML_CONSTRAINED_TEMPLATE(condition, __VA_ARGS__)
-#if TOML_CLANG
-#if (TOML_ARCH_ARM || TOML_ARCH_X86 || TOML_ARCH_AMD64) && defined(__FLT16_MANT_DIG__)
-#define TOML_FLOAT16 _Float16
+#ifndef TOML_ENABLE_FLOAT16
+
+#ifdef __FLT16_MANT_DIG__
+#define TOML_FLOAT16_MANT_DIG __FLT16_MANT_DIG__
+#define TOML_FLOAT16_DIG __FLT16_DIG__
+#define TOML_FLOAT16_MIN_EXP __FLT16_MIN_EXP__
+#define TOML_FLOAT16_MIN_10_EXP __FLT16_MIN_10_EXP__
+#define TOML_FLOAT16_MAX_EXP __FLT16_MAX_EXP__
+#define TOML_FLOAT16_MAX_10_EXP __FLT16_MAX_10_EXP__
+#else
+#define TOML_FLOAT16_MANT_DIG 0
+#define TOML_FLOAT16_DIG 0
+#define TOML_FLOAT16_MIN_EXP 0
+#define TOML_FLOAT16_MIN_10_EXP 0
+#define TOML_FLOAT16_MAX_EXP 0
+#define TOML_FLOAT16_MAX_10_EXP 0
+#endif
+
+#if (TOML_FLOAT16_MANT_DIG && TOML_FLOAT16_DIG && TOML_FLOAT16_MIN_EXP && TOML_FLOAT16_MIN_10_EXP \
+ && TOML_FLOAT16_MAX_EXP && TOML_FLOAT16_MAX_10_EXP)
+#define TOML_FLOAT16_LIMITS_SET 1
+#else
+#define TOML_FLOAT16_LIMITS_SET 0
+#endif
+
+#if TOML_FLOAT16_LIMITS_SET
+
+#if TOML_CLANG // >= 15
+#if (TOML_ARCH_ARM || TOML_ARCH_AMD64 || TOML_ARCH_X86)
+#define TOML_ENABLE_FLOAT16 1
#endif
-#elif TOML_GCC
-/*
- */
-#if (TOML_ARCH_ARM /*|| TOML_ARCH_X86 || TOML_ARCH_AMD64*/) && defined(__FLT16_MANT_DIG__)
-#define TOML_FLOAT16 _Float16
+#elif TOML_GCC
+#if (TOML_ARCH_ARM || TOML_ARCH_AMD64 /* || TOML_ARCH_X86*/)
+#define TOML_ENABLE_FLOAT16 1
#endif
+
+#endif // clang/gcc
+
+#endif // TOML_FLOAT16_LIMITS_SET
+
+#endif // !defined(TOML_ENABLE_FLOAT16)
+
+#ifndef TOML_ENABLE_FLOAT16
+#define TOML_ENABLE_FLOAT16 0
#endif
#if defined(__SIZEOF_FLOAT128__) && defined(__FLT128_MANT_DIG__) && defined(__LDBL_MANT_DIG__) \
@@ -1701,9 +1735,9 @@ TOML_IMPL_NAMESPACE_START
template
struct float_traits : float_traits_base::digits, std::numeric_limits::digits10>
{};
-#ifdef TOML_FLOAT16
+#if TOML_ENABLE_FLOAT16
template <>
- struct float_traits : float_traits_base
+ struct float_traits<_Float16> : float_traits_base<_Float16, __FLT16_MANT_DIG__, __FLT16_DIG__>
{};
#endif
#ifdef TOML_FLOAT128
@@ -1722,9 +1756,9 @@ TOML_IMPL_NAMESPACE_START
template <>
struct value_traits : float_traits
{};
-#ifdef TOML_FLOAT16
+#if TOML_ENABLE_FLOAT16
template <>
- struct value_traits : float_traits
+ struct value_traits<_Float16> : float_traits<_Float16>
{};
#endif
#ifdef TOML_FLOAT128
@@ -17091,8 +17125,8 @@ TOML_POP_WARNINGS;
#undef TOML_ANON_NAMESPACE
#undef TOML_ANON_NAMESPACE_END
#undef TOML_ANON_NAMESPACE_START
-#undef TOML_ARCH_ARM
#undef TOML_ARCH_AMD64
+#undef TOML_ARCH_ARM
#undef TOML_ARCH_ARM32
#undef TOML_ARCH_ARM64
#undef TOML_ARCH_ITANIUM
@@ -17132,7 +17166,13 @@ TOML_POP_WARNINGS;
#undef TOML_FLAGS_ENUM
#undef TOML_FLOAT_CHARCONV
#undef TOML_FLOAT128
-#undef TOML_FLOAT16
+#undef TOML_FLOAT16_DIG
+#undef TOML_FLOAT16_LIMITS_SET
+#undef TOML_FLOAT16_MANT_DIG
+#undef TOML_FLOAT16_MAX_10_EXP
+#undef TOML_FLOAT16_MAX_EXP
+#undef TOML_FLOAT16_MIN_10_EXP
+#undef TOML_FLOAT16_MIN_EXP
#undef TOML_GCC
#undef TOML_HAS_ATTR
#undef TOML_HAS_BUILTIN
diff --git a/tools/generate_single_header.py b/tools/generate_single_header.py
index 6df41bfc..18f0a195 100755
--- a/tools/generate_single_header.py
+++ b/tools/generate_single_header.py
@@ -215,6 +215,7 @@ def main():
r'TOML_ENABLE_SIMD',
r'TOML_ENABLE_UNRELEASED_FEATURES',
r'TOML_ENABLE_WINDOWS_COMPAT',
+ r'TOML_ENABLE_FLOAT16',
r'TOML_EXCEPTIONS',
r'TOML_EXPORTED_CLASS',
r'TOML_EXPORTED_FREE_FUNCTION',