diff --git a/.editorconfig b/.editorconfig
index 43b1c14..e36bb3d 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -8,14 +8,15 @@ tab_width = 4
end_of_line = lf
trim_trailing_whitespace = true
charset = utf-8
+max_line_length = 120
[*.{md,markdown}]
trim_trailing_whitespace = false
-[*.{gitattributes,yaml,yml,vcxproj,vcxproj.filters,sln,rc,clang-format,toml}]
+[*.{gitattributes,yaml,yml,vcxproj,vcxproj.filters,sln,rc,clang-format,toml,py,cmake}]
indent_style = space
-[{Doxyfile,Doxyfile-mcss}]
+[{Doxyfile,Doxyfile-mcss,CMakeLists.txt}]
indent_style = space
[*.{hlsl,rc,sln,vcxproj,vcxproj.filters}]
diff --git a/.gitattributes b/.gitattributes
index bb99cda..864cdfd 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -7,17 +7,17 @@
*.cs eol=lf diff=csharp
-*.doc diff=astextplain
-*.DOC diff=astextplain
-*.docx diff=astextplain
-*.DOCX diff=astextplain
*.dot diff=astextplain
*.DOT diff=astextplain
-*.pdf diff=astextplain
-*.PDF diff=astextplain
*.rtf diff=astextplain
*.RTF diff=astextplain
+*.doc binary
+*.DOC binary
+*.docx binary
+*.DOCX binary
+*.pdf binary
+*.PDF binary
*.ai binary
*.bin binary
*.bmp binary
diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md
index 1d269ac..4632299 100644
--- a/.github/pull_request_template.md
+++ b/.github/pull_request_template.md
@@ -3,40 +3,36 @@
Thanks for contributing!
-->
-
-
**What does this change do?**
+
-
-
**Is it related to an exisiting bug report or feature request?**
+
-
-
**Pre-merge checklist**
+
-- [ ] I've read [CONTRIBUTING.md]
-- [ ] I've rebased my changes against the current HEAD of `origin/master` (if necessary)
-- [ ] I've added new test cases to verify my change
-- [ ] I've regenerated toml.hpp ([how-to])
-- [ ] I've updated any affected documentation
-- [ ] I've rebuilt and run the tests with at least one of:
- - [ ] Clang 6 or higher
- - [ ] GCC 7 or higher
- - [ ] MSVC 19.20 (Visual Studio 2019) or higher
-- [ ] I've added my name to the list of contributors in [README.md](https://github.com/marzer/tomlplusplus/blob/master/README.md)
-
+- [ ] I've read [CONTRIBUTING.md]
+- [ ] I've rebased my changes against the current HEAD of `origin/master` (if necessary)
+- [ ] I've added new test cases to verify my change
+- [ ] I've regenerated toml.hpp ([how-to])
+- [ ] I've updated any affected documentation
+- [ ] I've rebuilt and run the tests with at least one of:
+ - [ ] Clang 8 or higher
+ - [ ] GCC 8 or higher
+ - [ ] MSVC 19.20 (Visual Studio 2019) or higher
+- [ ] I've added my name to the list of contributors in [README.md](https://github.com/marzer/tomlplusplus/blob/master/README.md)
[CONTRIBUTING.md]: https://github.com/marzer/tomlplusplus/blob/master/CONTRIBUTING.md
[how-to]: https://github.com/marzer/tomlplusplus/blob/master/CONTRIBUTING.md#regenerating-tomlhpp
-[README.md]: https://github.com/marzer/tomlplusplus/blob/master/README.md
\ No newline at end of file
+[README.md]: https://github.com/marzer/tomlplusplus/blob/master/README.md
diff --git a/CHANGELOG.md b/CHANGELOG.md
index e36ce9f..92a881b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -29,6 +29,8 @@ template:
- fixed `toml::value::flags()` not being cleared when `std::move`-ing a value
- fixed error in README (#195) (@andrewkcorcoran)
- fixed compiler error when using NVCC (#198) (@thompsonnoahe)
+- fixed `noexcept(...)` sometimes being incorrectly derived on `for_each()`
+- fixed `for_each()` compilation error on GCC <= 7 (#197) (@sagi-ottopia)
#### Changes:
diff --git a/README.md b/README.md
index b66d140..53a6c66 100644
--- a/README.md
+++ b/README.md
@@ -27,7 +27,7 @@
- C++17 (plus some C++20 features where available, e.g. experimental support for [char8_t] strings)
- Doesn't require RTTI
- Works with or without exceptions
-- Tested on Clang (6+), GCC (7+) and MSVC (VS2019)
+- Tested on Clang (8+), GCC (8+) and MSVC (VS2019)
- Tested on x64, x86 and ARM
diff --git a/docs/pages/main_page.md b/docs/pages/main_page.md
index 061fe8c..bb1a100 100644
--- a/docs/pages/main_page.md
+++ b/docs/pages/main_page.md
@@ -15,7 +15,7 @@
- C++17 (plus some C++20 features where available, e.g. experimental support for char8_t strings)
- Doesn't require RTTI
- Works with or without exceptions
-- Tested on Clang (6+), GCC (7+) and MSVC (VS2019)
+- Tested on Clang (8+), GCC (8+) and MSVC (VS2019)
- Tested on x64, x86 and ARM
diff --git a/include/toml++/impl/array.hpp b/include/toml++/impl/array.hpp
index b7fd96a..ad79379 100644
--- a/include/toml++/impl/array.hpp
+++ b/include/toml++/impl/array.hpp
@@ -11,6 +11,26 @@
#include "make_node.hpp"
#include "header_start.hpp"
+#ifndef TOML_RETURN_BOOL_FROM_FOR_EACH_BROKEN
+#if TOML_GCC && TOML_GCC <= 7
+#define TOML_RETURN_BOOL_FROM_FOR_EACH_BROKEN 1
+#else
+#define TOML_RETURN_BOOL_FROM_FOR_EACH_BROKEN 0
+#endif
+#endif
+
+#if TOML_RETURN_BOOL_FROM_FOR_EACH_BROKEN && !defined(TOML_RETURN_BOOL_FROM_FOR_EACH_BROKEN_ACKNOWLEDGED)
+#define TOML_RETURN_BOOL_FROM_FOR_EACH_BROKEN_MESSAGE \
+ "If you're seeing this error it's because you're using one of toml++'s for_each() functions on a compiler with " \
+ "known bugs in that area (e.g. GCC 7). On these compilers returning a bool (or bool-convertible) value from the " \
+ "for_each() callable causes spurious compilation failures, while returning nothing (void) works fine. " \
+ "If you believe this message is incorrect for your compiler, you can try your luck by #defining " \
+ "TOML_RETURN_BOOL_FROM_FOR_EACH_BROKEN as 0 and recompiling - if it works, great! Let me know at " \
+ "https://github.com/marzer/tomlplusplus/issues. Alternatively, if you don't have any need for early-exiting from " \
+ "for_each(), you can suppress this error by #defining TOML_RETURN_BOOL_FROM_FOR_EACH_BROKEN_ACKNOWLEDGED " \
+ "and moving on with your life."
+#endif
+
/// \cond
TOML_IMPL_NAMESPACE_START
{
@@ -834,51 +854,56 @@ TOML_NAMESPACE_START
using for_each_elem_ref = impl::copy_cvref>>, Array>;
template
- static constexpr bool can_for_each = std::is_invocable_v, size_t> //
- || std::is_invocable_v> //
- || std::is_invocable_v>;
+ using can_for_each = std::disjunction, size_t>,
+ std::is_invocable>,
+ std::is_invocable>>;
template
- static constexpr bool can_for_each_nothrow =
- std::is_nothrow_invocable_v, size_t> //
- || std::is_nothrow_invocable_v> //
- || std::is_nothrow_invocable_v>;
+ using can_for_each_nothrow = std::conditional_t<
+ // first form
+ std::is_invocable_v, size_t>,
+ std::is_nothrow_invocable, size_t>,
+ std::conditional_t<
+ // second form
+ std::is_invocable_v>,
+ std::is_nothrow_invocable>,
+ std::conditional_t<
+ // third form
+ std::is_invocable_v>,
+ std::is_nothrow_invocable>,
+ std::false_type>>>;
template
- static constexpr bool can_for_each_any = can_for_each //
- || can_for_each //
- || can_for_each //
- || can_for_each //
- || can_for_each //
- || can_for_each //
- || can_for_each //
- || can_for_each //
- || can_for_each;
+ using can_for_each_any = std::disjunction,
+ can_for_each,
+ can_for_each,
+ can_for_each,
+ can_for_each,
+ can_for_each,
+ can_for_each,
+ can_for_each,
+ can_for_each>;
template
- static constexpr bool for_each_is_nothrow_one = !can_for_each //
- || can_for_each_nothrow;
-
- // clang-format off
-
+ using for_each_is_nothrow_one = std::disjunction>, //
+ can_for_each_nothrow>;
template
- static constexpr bool for_each_is_nothrow = for_each_is_nothrow_one //
- && for_each_is_nothrow_one //
- && for_each_is_nothrow_one //
- && for_each_is_nothrow_one //
- && for_each_is_nothrow_one //
- && for_each_is_nothrow_one //
- && for_each_is_nothrow_one //
- && for_each_is_nothrow_one //
- && for_each_is_nothrow_one;
-
- // clang-format on
+ using for_each_is_nothrow = std::conjunction,
+ for_each_is_nothrow_one,
+ for_each_is_nothrow_one,
+ for_each_is_nothrow_one,
+ for_each_is_nothrow_one,
+ for_each_is_nothrow_one,
+ for_each_is_nothrow_one,
+ for_each_is_nothrow_one,
+ for_each_is_nothrow_one>;
template
- static void do_for_each(Func&& visitor, Array&& arr) noexcept(for_each_is_nothrow)
+ static void do_for_each(Func&& visitor, Array&& arr) //
+ noexcept(for_each_is_nothrow::value)
{
- static_assert(can_for_each_any,
+ static_assert(can_for_each_any::value,
"TOML array for_each visitors must be invocable for at least one of the toml::node "
"specializations:" TOML_SA_NODE_TYPE_LIST);
@@ -887,13 +912,46 @@ TOML_NAMESPACE_START
using node_ref = impl::copy_cvref;
static_assert(std::is_reference_v);
+#if TOML_RETURN_BOOL_FROM_FOR_EACH_BROKEN
+
+#ifndef TOML_RETURN_BOOL_FROM_FOR_EACH_BROKEN_ACKNOWLEDGED
+ static_assert(impl::always_false, //
+ TOML_RETURN_BOOL_FROM_FOR_EACH_BROKEN_MESSAGE);
+#endif
+
+ static_cast(static_cast(arr)[i])
+ .visit(
+ [&]([[maybe_unused]] auto&& elem) //
+ noexcept(for_each_is_nothrow_one::value)
+ {
+ using elem_ref = for_each_elem_ref;
+ static_assert(std::is_reference_v);
+
+ // func(elem, i)
+ if constexpr (std::is_invocable_v)
+ {
+ static_cast(visitor)(static_cast(elem), i);
+ }
+
+ // func(i, elem)
+ else if constexpr (std::is_invocable_v)
+ {
+ static_cast(visitor)(i, static_cast(elem));
+ }
+
+ // func(elem)
+ else if constexpr (std::is_invocable_v)
+ {
+ static_cast(visitor)(static_cast(elem));
+ }
+ });
+
+#else
const auto keep_going =
static_cast(static_cast(arr)[i])
.visit(
- [&](auto&& elem)
-#if !TOML_MSVC // MSVC thinks this is invalid syntax O_o
- noexcept(for_each_is_nothrow_one)
-#endif
+ [&]([[maybe_unused]] auto&& elem) //
+ noexcept(for_each_is_nothrow_one::value)
{
using elem_ref = for_each_elem_ref;
static_assert(std::is_reference_v);
@@ -959,6 +1017,7 @@ TOML_NAMESPACE_START
if (!keep_going)
return;
+#endif
}
}
@@ -1026,7 +1085,8 @@ TOML_NAMESPACE_START
///
/// \see node::visit()
template
- array& for_each(Func&& visitor) & noexcept(for_each_is_nothrow)
+ array& for_each(Func&& visitor) & //
+ noexcept(for_each_is_nothrow::value)
{
do_for_each(static_cast(visitor), *this);
return *this;
@@ -1034,7 +1094,8 @@ TOML_NAMESPACE_START
/// \brief Invokes a visitor on each element in the array (rvalue overload).
template
- array&& for_each(Func&& visitor) && noexcept(for_each_is_nothrow)
+ array&& for_each(Func&& visitor) && //
+ noexcept(for_each_is_nothrow::value)
{
do_for_each(static_cast(visitor), static_cast(*this));
return static_cast(*this);
@@ -1042,7 +1103,8 @@ TOML_NAMESPACE_START
/// \brief Invokes a visitor on each element in the array (const lvalue overload).
template
- const array& for_each(Func&& visitor) const& noexcept(for_each_is_nothrow)
+ const array& for_each(Func&& visitor) const& //
+ noexcept(for_each_is_nothrow::value)
{
do_for_each(static_cast(visitor), *this);
return *this;
@@ -1050,7 +1112,8 @@ TOML_NAMESPACE_START
/// \brief Invokes a visitor on each element in the array (const rvalue overload).
template
- const array&& for_each(Func&& visitor) const&& noexcept(for_each_is_nothrow)
+ const array&& for_each(Func&& visitor) const&& //
+ noexcept(for_each_is_nothrow::value)
{
do_for_each(static_cast(visitor), static_cast(*this));
return static_cast(*this);
diff --git a/include/toml++/impl/forward_declarations.hpp b/include/toml++/impl/forward_declarations.hpp
index d9162ad..5c248de 100644
--- a/include/toml++/impl/forward_declarations.hpp
+++ b/include/toml++/impl/forward_declarations.hpp
@@ -465,8 +465,8 @@ TOML_IMPL_NAMESPACE_START
using copy_cvref =
copy_ref, std::remove_reference_t>, Dest>, Src>;
- template
- inline constexpr bool dependent_false = false;
+ template
+ inline constexpr bool always_false = false;
template
inline constexpr bool first_is_same = false;
diff --git a/include/toml++/impl/make_node.hpp b/include/toml++/impl/make_node.hpp
index c4a1210..69a566a 100644
--- a/include/toml++/impl/make_node.hpp
+++ b/include/toml++/impl/make_node.hpp
@@ -49,14 +49,14 @@ TOML_IMPL_NAMESPACE_START
if constexpr (!is_losslessly_convertible_to_native)
{
if constexpr (std::is_same_v)
- static_assert(dependent_false,
+ static_assert(always_false,
"Integral value initializers must be losslessly convertible to int64_t");
else if constexpr (std::is_same_v)
- static_assert(dependent_false,
+ static_assert(always_false,
"Floating-point value initializers must be losslessly convertible to double");
else
static_assert(
- dependent_false,
+ always_false,
"Value initializers must be losslessly convertible to one of the TOML value types");
}
@@ -65,7 +65,7 @@ TOML_IMPL_NAMESPACE_START
#if TOML_ENABLE_WINDOWS_COMPAT
out = new value_type{ narrow(static_cast(val)) };
#else
- static_assert(dependent_false, "Evaluated unreachable branch!");
+ static_assert(always_false, "Evaluated unreachable branch!");
#endif
}
else
diff --git a/include/toml++/impl/node_view.hpp b/include/toml++/impl/node_view.hpp
index 296ae53..fb63025 100644
--- a/include/toml++/impl/node_view.hpp
+++ b/include/toml++/impl/node_view.hpp
@@ -501,7 +501,7 @@ TOML_NAMESPACE_START
#else
- static_assert(impl::dependent_false, "Evaluated unreachable branch!");
+ static_assert(impl::always_false, "Evaluated unreachable branch!");
#endif
}
@@ -656,7 +656,7 @@ TOML_NAMESPACE_START
#if TOML_ENABLE_WINDOWS_COMPAT
return lhs == impl::narrow(rhs);
#else
- static_assert(impl::dependent_false, "Evaluated unreachable branch!");
+ static_assert(impl::always_false, "Evaluated unreachable branch!");
#endif
}
else
diff --git a/include/toml++/impl/parse_result.hpp b/include/toml++/impl/parse_result.hpp
index 25743f4..5837a0b 100644
--- a/include/toml++/impl/parse_result.hpp
+++ b/include/toml++/impl/parse_result.hpp
@@ -474,7 +474,7 @@ TOML_NAMESPACE_START
return err_ ? node_view{} : table()[key];
}
-#endif // TOML_ENABLE_WINDOWS_COMPAT
+#endif // TOML_ENABLE_WINDOWS_COMPAT
/// @}
diff --git a/include/toml++/impl/parser.hpp b/include/toml++/impl/parser.hpp
index fbdd65e..c794c5e 100644
--- a/include/toml++/impl/parser.hpp
+++ b/include/toml++/impl/parser.hpp
@@ -379,7 +379,7 @@ TOML_NAMESPACE_START
return parse(std::u8string_view{ str, len });
}
-#endif // TOML_HAS_CHAR8
+#endif // TOML_HAS_CHAR8
TOML_ABI_NAMESPACE_END; // TOML_EXCEPTIONS
}
diff --git a/include/toml++/impl/parser.inl b/include/toml++/impl/parser.inl
index a5135d0..6f0136f 100644
--- a/include/toml++/impl/parser.inl
+++ b/include/toml++/impl/parser.inl
@@ -792,7 +792,7 @@ TOML_ANON_NAMESPACE_START
else
{
static_assert(
- impl::dependent_false,
+ impl::always_false,
"concatenate() inputs are limited to std::string_views, integers, floats, and escaped_codepoint");
}
}
@@ -2122,7 +2122,7 @@ TOML_IMPL_NAMESPACE_START
return (fragments[0].value + fragments[1].value) * pow(2.0, fragments[2].value * exponent_sign) * sign;
-#else // !TOML_LANG_UNRELEASED
+#else // !TOML_LANG_UNRELEASED
set_error_and_return_default("hexadecimal floating-point values are not supported "
"in TOML 1.0.0 and earlier"sv);
@@ -3906,7 +3906,7 @@ TOML_NAMESPACE_START
return TOML_ANON_NAMESPACE::do_parse(TOML_ANON_NAMESPACE::utf8_reader{ doc, impl::narrow(source_path) });
}
-#endif // TOML_HAS_CHAR8 && TOML_ENABLE_WINDOWS_COMPAT
+#endif // TOML_HAS_CHAR8 && TOML_ENABLE_WINDOWS_COMPAT
TOML_ABI_NAMESPACE_END; // TOML_EXCEPTIONS
}
diff --git a/include/toml++/impl/preprocessor.hpp b/include/toml++/impl/preprocessor.hpp
index bd27f41..feeb802 100644
--- a/include/toml++/impl/preprocessor.hpp
+++ b/include/toml++/impl/preprocessor.hpp
@@ -11,82 +11,86 @@
#ifndef __cplusplus
#error toml++ is a C++ library.
#endif
+
+#ifndef TOML_CPP
#ifdef _MSVC_LANG
+#if _MSVC_LANG > __cplusplus
#define TOML_CPP _MSVC_LANG
-#else
+#endif
+#endif
+#ifndef TOML_CPP
#define TOML_CPP __cplusplus
#endif
-#if TOML_CPP >= 202002L
+#if TOML_CPP >= 202900L
+#undef TOML_CPP
+#define TOML_CPP 29
+#elif TOML_CPP >= 202600L
+#undef TOML_CPP
+#define TOML_CPP 26
+#elif TOML_CPP >= 202302L
+#undef TOML_CPP
+#define TOML_CPP 23
+#elif TOML_CPP >= 202002L
#undef TOML_CPP
#define TOML_CPP 20
#elif TOML_CPP >= 201703L
#undef TOML_CPP
#define TOML_CPP 17
+#elif TOML_CPP >= 201402L
+#undef TOML_CPP
+#define TOML_CPP 14
+#elif TOML_CPP >= 201103L
+#undef TOML_CPP
+#define TOML_CPP 11
#else
-#if TOML_CPP < 201103L
+#undef TOML_CPP
+#define TOML_CPP 0
+#endif
+#endif
+
+#if !TOML_CPP
#error toml++ requires C++17 or higher. For a pre-C++11 TOML library see https://github.com/ToruNiina/Boost.toml
-#elif TOML_CPP < 201703L
+#elif TOML_CPP < 17
#error toml++ requires C++17 or higher. For a C++11 TOML library see https://github.com/ToruNiina/toml11
#endif
-#endif
//#=====================================================================================================================
-//# COMPILER / OS
+//# COMPILER
//#=====================================================================================================================
+#ifndef TOML_MAKE_VERSION
#define TOML_MAKE_VERSION(major, minor, patch) (((major)*10000) + ((minor)*100) + ((patch)))
+#endif
-#ifdef __clang__
-#define TOML_CLANG __clang_major__
-#else
-#define TOML_CLANG 0
-#endif
-#ifdef __INTEL_COMPILER
-#define TOML_ICC __INTEL_COMPILER
-#ifdef __ICL
-#define TOML_ICC_CL TOML_ICC
-#else
-#define TOML_ICC_CL 0
-#endif
-#else
-#define TOML_ICC 0
-#define TOML_ICC_CL 0
-#endif
-#if defined(_MSC_VER) && !TOML_CLANG && !TOML_ICC
-#define TOML_MSVC _MSC_VER
-#else
-#define TOML_MSVC 0
-#endif
-#if defined(__GNUC__) && !TOML_CLANG && !TOML_ICC
-#define TOML_GCC __GNUC__
-#else
-#define TOML_GCC 0
-#endif
-#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__) || defined(__CYGWIN__)
-#define TOML_WINDOWS 1
-#else
-#define TOML_WINDOWS 0
-#endif
-#if defined(DOXYGEN) || defined(__DOXYGEN__) || defined(__POXY__) || defined(__poxy__)
-#define TOML_DOXYGEN 1
-#else
-#define TOML_DOXYGEN 0
-#endif
+#ifndef TOML_INTELLISENSE
#ifdef __INTELLISENSE__
#define TOML_INTELLISENSE 1
#else
#define TOML_INTELLISENSE 0
#endif
-#if defined(__CUDACC__) || defined(__CUDA_ARCH__) || defined(__CUDA_LIBDEVICE__)
-#define TOML_CUDA 1
+#endif
+
+#ifndef TOML_DOXYGEN
+#if defined(DOXYGEN) || defined(__DOXYGEN) || defined(__DOXYGEN__) || defined(__doxygen__) || defined(__POXY__) \
+ || defined(__poxy__)
+#define TOML_DOXYGEN 1
#else
-#define TOML_CUDA 0
+#define TOML_DOXYGEN 0
+#endif
+#endif
+
+#ifndef TOML_CLANG
+#ifdef __clang__
+#define TOML_CLANG __clang_major__
+#else
+#define TOML_CLANG 0
#endif
// special handling for apple clang; see:
// - https://github.com/marzer/tomlplusplus/issues/189
// - https://en.wikipedia.org/wiki/Xcode
-// - https://stackoverflow.com/questions/19387043/how-can-i-reliably-detect-the-version-of-clang-at-preprocessing-time
+// -
+// https://stackoverflow.com/questions/19387043/how-can-i-reliably-detect-the-version-of-clang-at-preprocessing-time
#if TOML_CLANG && defined(__apple_build_version__)
#undef TOML_CLANG
#define TOML_CLANG_VERSION TOML_MAKE_VERSION(__clang_major__, __clang_minor__, __clang_patchlevel__)
@@ -115,112 +119,229 @@
#endif
#undef TOML_CLANG_VERSION
#endif
+#endif
+
+#ifndef TOML_ICC
+#ifdef __INTEL_COMPILER
+#define TOML_ICC __INTEL_COMPILER
+#ifdef __ICL
+#define TOML_ICC_CL TOML_ICC
+#else
+#define TOML_ICC_CL 0
+#endif
+#else
+#define TOML_ICC 0
+#define TOML_ICC_CL 0
+#endif
+#endif
+
+#ifndef TOML_MSVC_LIKE
+#ifdef _MSC_VER
+#define TOML_MSVC_LIKE _MSC_VER
+#else
+#define TOML_MSVC_LIKE 0
+#endif
+#endif
+
+#ifndef TOML_MSVC
+#if TOML_MSVC_LIKE && !TOML_CLANG && !TOML_ICC
+#define TOML_MSVC TOML_MSVC_LIKE
+#else
+#define TOML_MSVC 0
+#endif
+#endif
+
+#ifndef TOML_GCC_LIKE
+#ifdef __GNUC__
+#define TOML_GCC_LIKE __GNUC__
+#else
+#define TOML_GCC_LIKE 0
+#endif
+#endif
+
+#ifndef TOML_GCC
+#if TOML_GCC_LIKE && !TOML_CLANG && !TOML_ICC
+#define TOML_GCC TOML_GCC_LIKE
+#else
+#define TOML_GCC 0
+#endif
+#endif
+
+#ifndef TOML_CUDA
+#if defined(__CUDACC__) || defined(__CUDA_ARCH__) || defined(__CUDA_LIBDEVICE__)
+#define TOML_CUDA 1
+#else
+#define TOML_CUDA 0
+#endif
+#endif
//#=====================================================================================================================
//# ARCHITECTURE
//#=====================================================================================================================
-// IA64
+#ifndef TOML_ARCH_ITANIUM
#if defined(__ia64__) || defined(__ia64) || defined(_IA64) || defined(__IA64__) || defined(_M_IA64)
#define TOML_ARCH_ITANIUM 1
+#define TOML_ARCH_BITNESS 64
#else
#define TOML_ARCH_ITANIUM 0
#endif
+#endif
-// AMD64
+#ifndef TOML_ARCH_AMD64
#if defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64) || defined(_M_AMD64)
-#define TOML_ARCH_AMD64 1
+#define TOML_ARCH_AMD64 1
+#define TOML_ARCH_BITNESS 64
#else
#define TOML_ARCH_AMD64 0
#endif
+#endif
-// 32-bit x86
+#ifndef TOML_ARCH_X86
#if defined(__i386__) || defined(_M_IX86)
-#define TOML_ARCH_X86 1
+#define TOML_ARCH_X86 1
+#define TOML_ARCH_BITNESS 32
#else
#define TOML_ARCH_X86 0
#endif
+#endif
-// ARM
+#ifndef TOML_ARCH_ARM
#if defined(__aarch64__) || defined(__ARM_ARCH_ISA_A64) || defined(_M_ARM64) || defined(__ARM_64BIT_STATE) \
|| defined(_M_ARM64EC)
-#define TOML_ARCH_ARM32 0
-#define TOML_ARCH_ARM64 1
-#define TOML_ARCH_ARM 1
+#define TOML_ARCH_ARM32 0
+#define TOML_ARCH_ARM64 1
+#define TOML_ARCH_ARM 1
+#define TOML_ARCH_BITNESS 64
#elif defined(__arm__) || defined(_M_ARM) || defined(__ARM_32BIT_STATE)
-#define TOML_ARCH_ARM32 1
-#define TOML_ARCH_ARM64 0
-#define TOML_ARCH_ARM 1
+#define TOML_ARCH_ARM32 1
+#define TOML_ARCH_ARM64 0
+#define TOML_ARCH_ARM 1
+#define TOML_ARCH_BITNESS 32
#else
#define TOML_ARCH_ARM32 0
#define TOML_ARCH_ARM64 0
#define TOML_ARCH_ARM 0
#endif
+#endif
+
+#ifndef TOML_ARCH_BITNESS
+#define TOML_ARCH_BITNESS 0
+#endif
+
+#ifndef TOML_ARCH_X64
+#if TOML_ARCH_BITNESS == 64
+#define TOML_ARCH_X64 1
+#else
+#define TOML_ARCH_X64 0
+#endif
+#endif
+
+//#=====================================================================================================================
+//# OS
+//#=====================================================================================================================
+
+#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__) || defined(__CYGWIN__)
+#define TOML_WINDOWS 1
+#else
+#define TOML_WINDOWS 0
+#endif
+
+#ifdef __unix__
+#define TOML_UNIX 1
+#else
+#define TOML_UNIX 0
+#endif
+
+#ifdef __linux__
+#define TOML_LINUX 1
+#else
+#define TOML_LINUX 0
+#endif
//#=====================================================================================================================
//# ATTRIBUTES / FEATURE DETECTION / UTILITY MACROS
//#=====================================================================================================================
// TOML_HAS_INCLUDE
+#ifndef TOML_HAS_INCLUDE
#ifdef __has_include
-#define TOML_HAS_INCLUDE(header) __has_include(header)
+#define TOML_HAS_INCLUDE(header) __has_include(header)
#else
#define TOML_HAS_INCLUDE(header) 0
#endif
+#endif
+// TOML_HAS_BUILTIN
+#ifndef TOML_HAS_BUILTIN
#ifdef __has_builtin
#define TOML_HAS_BUILTIN(name) __has_builtin(name)
#else
#define TOML_HAS_BUILTIN(name) 0
#endif
+#endif
// TOML_HAS_FEATURE
+#ifndef TOML_HAS_FEATURE
#ifdef __has_feature
#define TOML_HAS_FEATURE(name) __has_feature(name)
#else
#define TOML_HAS_FEATURE(name) 0
#endif
+#endif
// TOML_HAS_ATTR
+#ifndef TOML_HAS_ATTR
#ifdef __has_attribute
#define TOML_HAS_ATTR(attr) __has_attribute(attr)
#else
#define TOML_HAS_ATTR(attr) 0
#endif
+#endif
// TOML_HAS_CPP_ATTR
+#ifndef TOML_HAS_CPP_ATTR
#ifdef __has_cpp_attribute
#define TOML_HAS_CPP_ATTR(attr) __has_cpp_attribute(attr)
#else
#define TOML_HAS_CPP_ATTR(attr) 0
#endif
+#endif
+
+// TOML_ATTR (gnu attributes)
+#ifndef TOML_ATTR
+#if TOML_CLANG || TOML_GCC_LIKE
+#define TOML_ATTR(...) __attribute__((__VA_ARGS__))
+#else
+#define TOML_ATTR(...)
+#endif
+#endif
+
+// TOML_DECLSPEC (msvc attributes)
+#ifndef TOML_DECLSPEC
+#if TOML_MSVC_LIKE
+#define TOML_DECLSPEC(...) __declspec(__VA_ARGS__)
+#else
+#define TOML_DECLSPEC(...)
+#endif
+#endif
// TOML_COMPILER_HAS_EXCEPTIONS
+#ifndef TOML_COMPILER_HAS_EXCEPTIONS
#if defined(__EXCEPTIONS) || defined(_CPPUNWIND) || defined(__cpp_exceptions)
#define TOML_COMPILER_HAS_EXCEPTIONS 1
#else
#define TOML_COMPILER_HAS_EXCEPTIONS 0
#endif
+#endif
// TOML_COMPILER_HAS_RTTI
+#ifndef TOML_COMPILER_HAS_RTTI
#if defined(_CPPRTTI) || defined(__GXX_RTTI) || TOML_HAS_FEATURE(cxx_rtti)
#define TOML_COMPILER_HAS_RTTI 1
#else
#define TOML_COMPILER_HAS_RTTI 0
#endif
-
-// TOML_ATTR (gnu attributes)
-#if TOML_CLANG || TOML_GCC || defined(__GNUC__)
-#define TOML_ATTR(...) __attribute__((__VA_ARGS__))
-#else
-#define TOML_ATTR(...)
-#endif
-
-// TOML_DECLSPEC (msvc attributes)
-#ifdef _MSC_VER
-#define TOML_DECLSPEC(...) __declspec(__VA_ARGS__)
-#else
-#define TOML_DECLSPEC(...)
#endif
// TOML_CONCAT
@@ -237,6 +358,11 @@
#else
#define TOML_PRAGMA_CLANG(decl)
#endif
+#if TOML_CLANG >= 8
+#define TOML_PRAGMA_CLANG_GE_8(decl) TOML_PRAGMA_CLANG(decl)
+#else
+#define TOML_PRAGMA_CLANG_GE_8(decl)
+#endif
#if TOML_CLANG >= 9
#define TOML_PRAGMA_CLANG_GE_9(decl) TOML_PRAGMA_CLANG(decl)
#else
@@ -321,23 +447,51 @@
#endif
// pure + const
-// clang-format off
+#ifndef TOML_PURE
#ifdef NDEBUG
- #define TOML_PURE TOML_DECLSPEC(noalias) TOML_ATTR(__pure__)
- #define TOML_CONST TOML_DECLSPEC(noalias) TOML_ATTR(__const__)
- #define TOML_PURE_GETTER TOML_NODISCARD TOML_PURE
- #define TOML_CONST_GETTER TOML_NODISCARD TOML_CONST
- #define TOML_PURE_INLINE_GETTER TOML_NODISCARD TOML_ALWAYS_INLINE TOML_PURE
- #define TOML_CONST_INLINE_GETTER TOML_NODISCARD TOML_ALWAYS_INLINE TOML_CONST
+#define TOML_PURE \
+ TOML_DECLSPEC(noalias) \
+ TOML_ATTR(pure)
#else
- #define TOML_PURE
- #define TOML_CONST
- #define TOML_PURE_GETTER TOML_NODISCARD
- #define TOML_CONST_GETTER TOML_NODISCARD
- #define TOML_PURE_INLINE_GETTER TOML_NODISCARD TOML_ALWAYS_INLINE
- #define TOML_CONST_INLINE_GETTER TOML_NODISCARD TOML_ALWAYS_INLINE
+#define TOML_PURE
+#endif
+#endif
+#ifndef TOML_CONST
+#ifdef NDEBUG
+#define TOML_CONST \
+ TOML_DECLSPEC(noalias) \
+ TOML_ATTR(const)
+#else
+#define TOML_CONST
+#endif
+#endif
+#ifndef TOML_INLINE_GETTER
+#define TOML_INLINE_GETTER \
+ TOML_NODISCARD \
+ TOML_ALWAYS_INLINE
+#endif
+#ifndef TOML_PURE_GETTER
+#define TOML_PURE_GETTER \
+ TOML_NODISCARD \
+ TOML_PURE
+#endif
+#ifndef TOML_PURE_INLINE_GETTER
+#define TOML_PURE_INLINE_GETTER \
+ TOML_NODISCARD \
+ TOML_ALWAYS_INLINE \
+ TOML_PURE
+#endif
+#ifndef TOML_CONST_GETTER
+#define TOML_CONST_GETTER \
+ TOML_NODISCARD \
+ TOML_CONST
+#endif
+#ifndef TOML_CONST_INLINE_GETTER
+#define TOML_CONST_INLINE_GETTER \
+ TOML_NODISCARD \
+ TOML_ALWAYS_INLINE \
+ TOML_CONST
#endif
-// clang-format on
// TOML_ASSUME
#ifdef _MSC_VER
@@ -495,6 +649,7 @@
static_assert(true)
#define TOML_DISABLE_ARITHMETIC_WARNINGS \
+ TOML_PRAGMA_CLANG_GE_10(diagnostic ignored "-Wimplicit-int-float-conversion") \
TOML_PRAGMA_CLANG(diagnostic ignored "-Wfloat-equal") \
TOML_PRAGMA_CLANG(diagnostic ignored "-Wdouble-promotion") \
TOML_PRAGMA_CLANG(diagnostic ignored "-Wchar-subscripts") \
@@ -502,6 +657,7 @@
static_assert(true)
#define TOML_DISABLE_SPAM_WARNINGS \
+ TOML_PRAGMA_CLANG_GE_8(diagnostic ignored "-Wdefaulted-function-deleted") \
TOML_PRAGMA_CLANG_GE_9(diagnostic ignored "-Wctad-maybe-unsupported") \
TOML_PRAGMA_CLANG_GE_10(diagnostic ignored "-Wzero-as-null-pointer-constant") \
TOML_PRAGMA_CLANG_GE_11(diagnostic ignored "-Wsuggest-destructor-override") \
diff --git a/include/toml++/impl/table.hpp b/include/toml++/impl/table.hpp
index ca839b8..edb7316 100644
--- a/include/toml++/impl/table.hpp
+++ b/include/toml++/impl/table.hpp
@@ -841,49 +841,51 @@ TOML_NAMESPACE_START
using for_each_value_ref = impl::copy_cvref>>, Table>;
template
- static constexpr bool can_for_each = std::is_invocable_v> //
- || std::is_invocable_v>;
+ using can_for_each = std::disjunction>, //
+ std::is_invocable>>;
template
- static constexpr bool can_for_each_nothrow =
- std::is_nothrow_invocable_v> //
- || std::is_nothrow_invocable_v>;
+ using can_for_each_nothrow = std::conditional_t<
+ // first form
+ std::is_invocable_v>,
+ std::is_nothrow_invocable>,
+ std::conditional_t<
+ // second form
+ std::is_invocable_v>,
+ std::is_nothrow_invocable>,
+ std::false_type>>;
template
- static constexpr bool can_for_each_any = can_for_each //
- || can_for_each //
- || can_for_each //
- || can_for_each //
- || can_for_each //
- || can_for_each //
- || can_for_each //
- || can_for_each //
- || can_for_each;
+ using can_for_each_any = std::disjunction,
+ can_for_each,
+ can_for_each,
+ can_for_each,
+ can_for_each,
+ can_for_each,
+ can_for_each,
+ can_for_each,
+ can_for_each>;
template
- static constexpr bool for_each_is_nothrow_one = !can_for_each //
- || can_for_each_nothrow;
-
- // clang-format off
-
-
- template
- static constexpr bool for_each_is_nothrow = for_each_is_nothrow_one //
- && for_each_is_nothrow_one //
- && for_each_is_nothrow_one //
- && for_each_is_nothrow_one //
- && for_each_is_nothrow_one //
- && for_each_is_nothrow_one //
- && for_each_is_nothrow_one //
- && for_each_is_nothrow_one //
- && for_each_is_nothrow_one;
-
- // clang-format on
+ using for_each_is_nothrow_one = std::disjunction>, //
+ can_for_each_nothrow>;
template
- static void do_for_each(Func&& visitor, Table&& tbl) noexcept(for_each_is_nothrow)
+ using for_each_is_nothrow = std::conjunction,
+ for_each_is_nothrow_one,
+ for_each_is_nothrow_one,
+ for_each_is_nothrow_one,
+ for_each_is_nothrow_one,
+ for_each_is_nothrow_one,
+ for_each_is_nothrow_one,
+ for_each_is_nothrow_one,
+ for_each_is_nothrow_one>;
+
+ template
+ static void do_for_each(Func&& visitor, Table&& tbl) //
+ noexcept(for_each_is_nothrow::value)
{
- static_assert(can_for_each_any,
+ static_assert(can_for_each_any::value,
"TOML table for_each visitors must be invocable for at least one of the toml::node "
"specializations:" TOML_SA_NODE_TYPE_LIST);
@@ -894,13 +896,41 @@ TOML_NAMESPACE_START
using node_ref = impl::copy_cvref;
static_assert(std::is_reference_v);
+#if TOML_RETURN_BOOL_FROM_FOR_EACH_BROKEN
+
+#ifndef TOML_RETURN_BOOL_FROM_FOR_EACH_BROKEN_ACKNOWLEDGED
+ static_assert(impl::always_false, //
+ TOML_RETURN_BOOL_FROM_FOR_EACH_BROKEN_MESSAGE);
+#endif
+
+ static_cast(*kvp.second)
+ .visit(
+ [&]([[maybe_unused]] auto&& v) //
+ noexcept(for_each_is_nothrow_one::value)
+ {
+ using value_ref = for_each_value_ref;
+ static_assert(std::is_reference_v);
+
+ // func(key, val)
+ if constexpr (std::is_invocable_v)
+ {
+ static_cast(visitor)(static_cast(kvp.first),
+ static_cast(v));
+ }
+
+ // func(val)
+ else if constexpr (std::is_invocable_v)
+ {
+ static_cast(visitor)(static_cast(v));
+ }
+ });
+
+#else
const auto keep_going =
static_cast(*kvp.second)
.visit(
- [&](auto&& v)
-#if !TOML_MSVC // MSVC thinks this is invalid syntax O_o
- noexcept(for_each_is_nothrow_one)
-#endif
+ [&]([[maybe_unused]] auto&& v) //
+ noexcept(for_each_is_nothrow_one::value)
{
using value_ref = for_each_value_ref;
static_assert(std::is_reference_v);
@@ -949,6 +979,7 @@ TOML_NAMESPACE_START
if (!keep_going)
return;
+#endif
}
}
@@ -1037,7 +1068,8 @@ TOML_NAMESPACE_START
///
/// \see node::visit()
template
- table& for_each(Func&& visitor) & noexcept(for_each_is_nothrow)
+ table& for_each(Func&& visitor) & //
+ noexcept(for_each_is_nothrow::value)
{
do_for_each(static_cast(visitor), *this);
return *this;
@@ -1045,7 +1077,8 @@ TOML_NAMESPACE_START
/// \brief Invokes a visitor on each key-value pair in the table (rvalue overload).
template
- table&& for_each(Func&& visitor) && noexcept(for_each_is_nothrow)
+ table&& for_each(Func&& visitor) && //
+ noexcept(for_each_is_nothrow::value)
{
do_for_each(static_cast(visitor), static_cast(*this));
return static_cast(*this);
@@ -1053,7 +1086,8 @@ TOML_NAMESPACE_START
/// \brief Invokes a visitor on each key-value pair in the table (const lvalue overload).
template
- const table& for_each(Func&& visitor) const& noexcept(for_each_is_nothrow)
+ const table& for_each(Func&& visitor) const& //
+ noexcept(for_each_is_nothrow::value)
{
do_for_each(static_cast(visitor), *this);
return *this;
@@ -1061,7 +1095,8 @@ TOML_NAMESPACE_START
/// \brief Invokes a visitor on each key-value pair in the table (const rvalue overload).
template
- const table&& for_each(Func&& visitor) const&& noexcept(for_each_is_nothrow)
+ const table&& for_each(Func&& visitor) const&& //
+ noexcept(for_each_is_nothrow::value)
{
do_for_each(static_cast(visitor), static_cast(*this));
return static_cast(*this);
@@ -1216,7 +1251,7 @@ TOML_NAMESPACE_START
return contains(impl::narrow(key));
}
-#endif // TOML_ENABLE_WINDOWS_COMPAT
+#endif // TOML_ENABLE_WINDOWS_COMPAT
/// @}
@@ -1448,7 +1483,7 @@ TOML_NAMESPACE_START
impl::narrow(static_cast(key)),
static_cast(args)...);
#else
- static_assert(impl::dependent_false, "Evaluated unreachable branch!");
+ static_assert(impl::always_false, "Evaluated unreachable branch!");
#endif
}
else
@@ -1567,7 +1602,7 @@ TOML_NAMESPACE_START
#if TOML_ENABLE_WINDOWS_COMPAT
return insert(impl::narrow(static_cast(key)), static_cast(val), flags);
#else
- static_assert(impl::dependent_false, "Evaluated unreachable branch!");
+ static_assert(impl::always_false, "Evaluated unreachable branch!");
#endif
}
else
@@ -1714,7 +1749,7 @@ TOML_NAMESPACE_START
static_cast(val),
flags);
#else
- static_assert(impl::dependent_false, "Evaluated unreachable branch!");
+ static_assert(impl::always_false, "Evaluated unreachable branch!");
#endif
}
else
@@ -1793,7 +1828,7 @@ TOML_NAMESPACE_START
return emplace(impl::narrow(static_cast(key)),
static_cast(args)...);
#else
- static_assert(impl::dependent_false, "Evaluated unreachable branch!");
+ static_assert(impl::always_false, "Evaluated unreachable branch!");
#endif
}
else
@@ -1900,7 +1935,7 @@ TOML_NAMESPACE_START
return node_view{ get(key) };
}
-#endif // TOML_ENABLE_WINDOWS_COMPAT
+#endif // TOML_ENABLE_WINDOWS_COMPAT
/// @}
diff --git a/include/toml++/impl/unicode.hpp b/include/toml++/impl/unicode.hpp
index c5890a8..9bad395 100644
--- a/include/toml++/impl/unicode.hpp
+++ b/include/toml++/impl/unicode.hpp
@@ -168,7 +168,7 @@ TOML_IMPL_NAMESPACE_START
const auto type = state_table[byte];
codepoint = static_cast(has_code_point() ? (uint_least32_t{ 255u } >> type) & byte
- : (byte& uint_least32_t{ 63u })
+ : (byte & uint_least32_t{ 63u })
| (static_cast(codepoint) << 6));
state = state_table[state + uint_least32_t{ 256u } + type];
diff --git a/include/toml++/impl/value.hpp b/include/toml++/impl/value.hpp
index 758c580..a784713 100644
--- a/include/toml++/impl/value.hpp
+++ b/include/toml++/impl/value.hpp
@@ -1011,7 +1011,7 @@ TOML_NAMESPACE_START
#if TOML_ENABLE_WINDOWS_COMPAT
return widen(str);
#else
- static_assert(dependent_false, "Evaluated unreachable branch!");
+ static_assert(always_false