Skip to content

Commit d46cac7

Browse files
committed
fixed #197
also: - fixed `noexcept(...)` sometimes being incorrectly derived on `for_each() - refactors
1 parent 882d9d1 commit d46cac7

File tree

60 files changed

+1064
-445
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

60 files changed

+1064
-445
lines changed

.editorconfig

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,15 @@ tab_width = 4
88
end_of_line = lf
99
trim_trailing_whitespace = true
1010
charset = utf-8
11+
max_line_length = 120
1112

1213
[*.{md,markdown}]
1314
trim_trailing_whitespace = false
1415

15-
[*.{gitattributes,yaml,yml,vcxproj,vcxproj.filters,sln,rc,clang-format,toml}]
16+
[*.{gitattributes,yaml,yml,vcxproj,vcxproj.filters,sln,rc,clang-format,toml,py,cmake}]
1617
indent_style = space
1718

18-
[{Doxyfile,Doxyfile-mcss}]
19+
[{Doxyfile,Doxyfile-mcss,CMakeLists.txt}]
1920
indent_style = space
2021

2122
[*.{hlsl,rc,sln,vcxproj,vcxproj.filters}]

.gitattributes

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,17 @@
77

88
*.cs eol=lf diff=csharp
99

10-
*.doc diff=astextplain
11-
*.DOC diff=astextplain
12-
*.docx diff=astextplain
13-
*.DOCX diff=astextplain
1410
*.dot diff=astextplain
1511
*.DOT diff=astextplain
16-
*.pdf diff=astextplain
17-
*.PDF diff=astextplain
1812
*.rtf diff=astextplain
1913
*.RTF diff=astextplain
2014

15+
*.doc binary
16+
*.DOC binary
17+
*.docx binary
18+
*.DOCX binary
19+
*.pdf binary
20+
*.PDF binary
2121
*.ai binary
2222
*.bin binary
2323
*.bmp binary

.github/pull_request_template.md

Lines changed: 14 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,40 +3,36 @@
33
Thanks for contributing!
44
-->
55

6-
7-
86
**What does this change do?**
7+
98
<!--
109
Changes all Foos to Bars.
1110
--->
1211

13-
14-
1512
**Is it related to an exisiting bug report or feature request?**
13+
1614
<!--
1715
Fixes #69.
1816
--->
1917

20-
21-
2218
**Pre-merge checklist**
19+
2320
<!--
2421
Not all of these will necessarily apply, particularly if you're not making a code change (e.g. fixing documentation).
2522
That's OK. Tick the ones that do by placing an x in them, e.g. [x]
2623
--->
27-
- [ ] I've read [CONTRIBUTING.md]
28-
- [ ] I've rebased my changes against the current HEAD of `origin/master` (if necessary)
29-
- [ ] I've added new test cases to verify my change
30-
- [ ] I've regenerated toml.hpp ([how-to])
31-
- [ ] I've updated any affected documentation
32-
- [ ] I've rebuilt and run the tests with at least one of:
33-
- [ ] Clang 6 or higher
34-
- [ ] GCC 7 or higher
35-
- [ ] MSVC 19.20 (Visual Studio 2019) or higher
36-
- [ ] I've added my name to the list of contributors in [README.md](https://github.com/marzer/tomlplusplus/blob/master/README.md)
37-
3824

25+
- [ ] I've read [CONTRIBUTING.md]
26+
- [ ] I've rebased my changes against the current HEAD of `origin/master` (if necessary)
27+
- [ ] I've added new test cases to verify my change
28+
- [ ] I've regenerated toml.hpp ([how-to])
29+
- [ ] I've updated any affected documentation
30+
- [ ] I've rebuilt and run the tests with at least one of:
31+
- [ ] Clang 8 or higher
32+
- [ ] GCC 8 or higher
33+
- [ ] MSVC 19.20 (Visual Studio 2019) or higher
34+
- [ ] I've added my name to the list of contributors in [README.md](https://github.com/marzer/tomlplusplus/blob/master/README.md)
3935

4036
[CONTRIBUTING.md]: https://github.com/marzer/tomlplusplus/blob/master/CONTRIBUTING.md
4137
[how-to]: https://github.com/marzer/tomlplusplus/blob/master/CONTRIBUTING.md#regenerating-tomlhpp
42-
[README.md]: https://github.com/marzer/tomlplusplus/blob/master/README.md
38+
[README.md]: https://github.com/marzer/tomlplusplus/blob/master/README.md

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ template:
2929
- fixed `toml::value::flags()` not being cleared when `std::move`-ing a value
3030
- fixed error in README (#195) (@andrewkcorcoran)
3131
- fixed compiler error when using NVCC (#198) (@thompsonnoahe)
32+
- fixed `noexcept(...)` sometimes being incorrectly derived on `for_each()`
33+
- fixed `for_each()` compilation error on GCC &lt;= 7 (#197) (@sagi-ottopia)
3234

3335
#### Changes:
3436

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
- C++17 (plus some C++20 features where available, e.g. experimental support for [char8_t] strings)
2828
- Doesn't require RTTI
2929
- Works with or without exceptions
30-
- Tested on Clang (6+), GCC (7+) and MSVC (VS2019)
30+
- Tested on Clang (8+), GCC (8+) and MSVC (VS2019)
3131
- Tested on x64, x86 and ARM
3232

3333
<br>

docs/pages/main_page.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
- C++17 (plus some C++20 features where available, e.g. experimental support for char8_t strings)
1616
- Doesn't require RTTI
1717
- Works with or without exceptions
18-
- Tested on Clang (6+), GCC (7+) and MSVC (VS2019)
18+
- Tested on Clang (8+), GCC (8+) and MSVC (VS2019)
1919
- Tested on x64, x86 and ARM
2020

2121
<!-- --------------------------------------------------------------------------------------------------------------- -->

include/toml++/impl/array.hpp

Lines changed: 105 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,26 @@
1111
#include "make_node.hpp"
1212
#include "header_start.hpp"
1313

14+
#ifndef TOML_RETURN_BOOL_FROM_FOR_EACH_BROKEN
15+
#if TOML_GCC && TOML_GCC <= 7
16+
#define TOML_RETURN_BOOL_FROM_FOR_EACH_BROKEN 1
17+
#else
18+
#define TOML_RETURN_BOOL_FROM_FOR_EACH_BROKEN 0
19+
#endif
20+
#endif
21+
22+
#if TOML_RETURN_BOOL_FROM_FOR_EACH_BROKEN && !defined(TOML_RETURN_BOOL_FROM_FOR_EACH_BROKEN_ACKNOWLEDGED)
23+
#define TOML_RETURN_BOOL_FROM_FOR_EACH_BROKEN_MESSAGE \
24+
"If you're seeing this error it's because you're using one of toml++'s for_each() functions on a compiler with " \
25+
"known bugs in that area (e.g. GCC 7). On these compilers returning a bool (or bool-convertible) value from the " \
26+
"for_each() callable causes spurious compilation failures, while returning nothing (void) works fine. " \
27+
"If you believe this message is incorrect for your compiler, you can try your luck by #defining " \
28+
"TOML_RETURN_BOOL_FROM_FOR_EACH_BROKEN as 0 and recompiling - if it works, great! Let me know at " \
29+
"https://github.com/marzer/tomlplusplus/issues. Alternatively, if you don't have any need for early-exiting from " \
30+
"for_each(), you can suppress this error by #defining TOML_RETURN_BOOL_FROM_FOR_EACH_BROKEN_ACKNOWLEDGED " \
31+
"and moving on with your life."
32+
#endif
33+
1434
/// \cond
1535
TOML_IMPL_NAMESPACE_START
1636
{
@@ -834,51 +854,56 @@ TOML_NAMESPACE_START
834854
using for_each_elem_ref = impl::copy_cvref<impl::wrap_node<impl::remove_cvref<impl::unwrap_node<T>>>, Array>;
835855

836856
template <typename Func, typename Array, typename T>
837-
static constexpr bool can_for_each = std::is_invocable_v<Func, for_each_elem_ref<T, Array>, size_t> //
838-
|| std::is_invocable_v<Func, size_t, for_each_elem_ref<T, Array>> //
839-
|| std::is_invocable_v<Func, for_each_elem_ref<T, Array>>;
857+
using can_for_each = std::disjunction<std::is_invocable<Func, for_each_elem_ref<T, Array>, size_t>,
858+
std::is_invocable<Func, size_t, for_each_elem_ref<T, Array>>,
859+
std::is_invocable<Func, for_each_elem_ref<T, Array>>>;
840860

841861
template <typename Func, typename Array, typename T>
842-
static constexpr bool can_for_each_nothrow =
843-
std::is_nothrow_invocable_v<Func, for_each_elem_ref<T, Array>, size_t> //
844-
|| std::is_nothrow_invocable_v<Func, size_t, for_each_elem_ref<T, Array>> //
845-
|| std::is_nothrow_invocable_v<Func, for_each_elem_ref<T, Array>>;
862+
using can_for_each_nothrow = std::conditional_t<
863+
// first form
864+
std::is_invocable_v<Func, for_each_elem_ref<T, Array>, size_t>,
865+
std::is_nothrow_invocable<Func, for_each_elem_ref<T, Array>, size_t>,
866+
std::conditional_t<
867+
// second form
868+
std::is_invocable_v<Func, size_t, for_each_elem_ref<T, Array>>,
869+
std::is_nothrow_invocable<Func, size_t, for_each_elem_ref<T, Array>>,
870+
std::conditional_t<
871+
// third form
872+
std::is_invocable_v<Func, for_each_elem_ref<T, Array>>,
873+
std::is_nothrow_invocable<Func, for_each_elem_ref<T, Array>>,
874+
std::false_type>>>;
846875

847876
template <typename Func, typename Array>
848-
static constexpr bool can_for_each_any = can_for_each<Func, Array, table> //
849-
|| can_for_each<Func, Array, array> //
850-
|| can_for_each<Func, Array, std::string> //
851-
|| can_for_each<Func, Array, int64_t> //
852-
|| can_for_each<Func, Array, double> //
853-
|| can_for_each<Func, Array, bool> //
854-
|| can_for_each<Func, Array, date> //
855-
|| can_for_each<Func, Array, time> //
856-
|| can_for_each<Func, Array, date_time>;
877+
using can_for_each_any = std::disjunction<can_for_each<Func, Array, table>,
878+
can_for_each<Func, Array, array>,
879+
can_for_each<Func, Array, std::string>,
880+
can_for_each<Func, Array, int64_t>,
881+
can_for_each<Func, Array, double>,
882+
can_for_each<Func, Array, bool>,
883+
can_for_each<Func, Array, date>,
884+
can_for_each<Func, Array, time>,
885+
can_for_each<Func, Array, date_time>>;
857886

858887
template <typename Func, typename Array, typename T>
859-
static constexpr bool for_each_is_nothrow_one = !can_for_each<Func, Array, T> //
860-
|| can_for_each_nothrow<Func, Array, T>;
861-
862-
// clang-format off
863-
888+
using for_each_is_nothrow_one = std::disjunction<std::negation<can_for_each<Func, Array, T>>, //
889+
can_for_each_nothrow<Func, Array, T>>;
864890

865891
template <typename Func, typename Array>
866-
static constexpr bool for_each_is_nothrow = for_each_is_nothrow_one<Func, Array, table> //
867-
&& for_each_is_nothrow_one<Func, Array, array> //
868-
&& for_each_is_nothrow_one<Func, Array, std::string> //
869-
&& for_each_is_nothrow_one<Func, Array, int64_t> //
870-
&& for_each_is_nothrow_one<Func, Array, double> //
871-
&& for_each_is_nothrow_one<Func, Array, bool> //
872-
&& for_each_is_nothrow_one<Func, Array, date> //
873-
&& for_each_is_nothrow_one<Func, Array, time> //
874-
&& for_each_is_nothrow_one<Func, Array, date_time>;
875-
876-
// clang-format on
892+
using for_each_is_nothrow = std::conjunction<for_each_is_nothrow_one<Func, Array, table>,
893+
for_each_is_nothrow_one<Func, Array, array>,
894+
for_each_is_nothrow_one<Func, Array, std::string>,
895+
for_each_is_nothrow_one<Func, Array, int64_t>,
896+
for_each_is_nothrow_one<Func, Array, double>,
897+
for_each_is_nothrow_one<Func, Array, bool>,
898+
for_each_is_nothrow_one<Func, Array, date>,
899+
for_each_is_nothrow_one<Func, Array, time>,
900+
for_each_is_nothrow_one<Func, Array, date_time>>;
877901

878902
template <typename Func, typename Array>
879-
static void do_for_each(Func&& visitor, Array&& arr) noexcept(for_each_is_nothrow<Func&&, Array&&>)
903+
static void do_for_each(Func&& visitor, Array&& arr) //
904+
noexcept(for_each_is_nothrow<Func&&, Array&&>::value)
880905
{
881-
static_assert(can_for_each_any<Func&&, Array&&>,
906+
static_assert(can_for_each_any<Func&&, Array&&>::value,
882907
"TOML array for_each visitors must be invocable for at least one of the toml::node "
883908
"specializations:" TOML_SA_NODE_TYPE_LIST);
884909

@@ -887,13 +912,46 @@ TOML_NAMESPACE_START
887912
using node_ref = impl::copy_cvref<toml::node, Array&&>;
888913
static_assert(std::is_reference_v<node_ref>);
889914

915+
#if TOML_RETURN_BOOL_FROM_FOR_EACH_BROKEN
916+
917+
#ifndef TOML_RETURN_BOOL_FROM_FOR_EACH_BROKEN_ACKNOWLEDGED
918+
static_assert(impl::always_false<Func, Array, node_ref>, //
919+
TOML_RETURN_BOOL_FROM_FOR_EACH_BROKEN_MESSAGE);
920+
#endif
921+
922+
static_cast<node_ref>(static_cast<Array&&>(arr)[i])
923+
.visit(
924+
[&]([[maybe_unused]] auto&& elem) //
925+
noexcept(for_each_is_nothrow_one<Func&&, Array&&, decltype(elem)>::value)
926+
{
927+
using elem_ref = for_each_elem_ref<decltype(elem), Array&&>;
928+
static_assert(std::is_reference_v<elem_ref>);
929+
930+
// func(elem, i)
931+
if constexpr (std::is_invocable_v<Func&&, elem_ref, size_t>)
932+
{
933+
static_cast<Func&&>(visitor)(static_cast<elem_ref>(elem), i);
934+
}
935+
936+
// func(i, elem)
937+
else if constexpr (std::is_invocable_v<Func&&, size_t, elem_ref>)
938+
{
939+
static_cast<Func&&>(visitor)(i, static_cast<elem_ref>(elem));
940+
}
941+
942+
// func(elem)
943+
else if constexpr (std::is_invocable_v<Func&&, elem_ref>)
944+
{
945+
static_cast<Func&&>(visitor)(static_cast<elem_ref>(elem));
946+
}
947+
});
948+
949+
#else
890950
const auto keep_going =
891951
static_cast<node_ref>(static_cast<Array&&>(arr)[i])
892952
.visit(
893-
[&](auto&& elem)
894-
#if !TOML_MSVC // MSVC thinks this is invalid syntax O_o
895-
noexcept(for_each_is_nothrow_one<Func&&, Array&&, decltype(elem)>)
896-
#endif
953+
[&]([[maybe_unused]] auto&& elem) //
954+
noexcept(for_each_is_nothrow_one<Func&&, Array&&, decltype(elem)>::value)
897955
{
898956
using elem_ref = for_each_elem_ref<decltype(elem), Array&&>;
899957
static_assert(std::is_reference_v<elem_ref>);
@@ -959,6 +1017,7 @@ TOML_NAMESPACE_START
9591017

9601018
if (!keep_going)
9611019
return;
1020+
#endif
9621021
}
9631022
}
9641023

@@ -1026,31 +1085,35 @@ TOML_NAMESPACE_START
10261085
///
10271086
/// \see node::visit()
10281087
template <typename Func>
1029-
array& for_each(Func&& visitor) & noexcept(for_each_is_nothrow<Func&&, array&>)
1088+
array& for_each(Func&& visitor) & //
1089+
noexcept(for_each_is_nothrow<Func&&, array&>::value)
10301090
{
10311091
do_for_each(static_cast<Func&&>(visitor), *this);
10321092
return *this;
10331093
}
10341094

10351095
/// \brief Invokes a visitor on each element in the array (rvalue overload).
10361096
template <typename Func>
1037-
array&& for_each(Func&& visitor) && noexcept(for_each_is_nothrow<Func&&, array&&>)
1097+
array&& for_each(Func&& visitor) && //
1098+
noexcept(for_each_is_nothrow<Func&&, array&&>::value)
10381099
{
10391100
do_for_each(static_cast<Func&&>(visitor), static_cast<array&&>(*this));
10401101
return static_cast<array&&>(*this);
10411102
}
10421103

10431104
/// \brief Invokes a visitor on each element in the array (const lvalue overload).
10441105
template <typename Func>
1045-
const array& for_each(Func&& visitor) const& noexcept(for_each_is_nothrow<Func&&, const array&>)
1106+
const array& for_each(Func&& visitor) const& //
1107+
noexcept(for_each_is_nothrow<Func&&, const array&>::value)
10461108
{
10471109
do_for_each(static_cast<Func&&>(visitor), *this);
10481110
return *this;
10491111
}
10501112

10511113
/// \brief Invokes a visitor on each element in the array (const rvalue overload).
10521114
template <typename Func>
1053-
const array&& for_each(Func&& visitor) const&& noexcept(for_each_is_nothrow<Func&&, const array&&>)
1115+
const array&& for_each(Func&& visitor) const&& //
1116+
noexcept(for_each_is_nothrow<Func&&, const array&&>::value)
10541117
{
10551118
do_for_each(static_cast<Func&&>(visitor), static_cast<const array&&>(*this));
10561119
return static_cast<const array&&>(*this);

include/toml++/impl/forward_declarations.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -465,8 +465,8 @@ TOML_IMPL_NAMESPACE_START
465465
using copy_cvref =
466466
copy_ref<copy_ref<copy_cv<std::remove_reference_t<Dest>, std::remove_reference_t<Src>>, Dest>, Src>;
467467

468-
template <typename T>
469-
inline constexpr bool dependent_false = false;
468+
template <typename...>
469+
inline constexpr bool always_false = false;
470470

471471
template <typename T, typename... U>
472472
inline constexpr bool first_is_same = false;

include/toml++/impl/make_node.hpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,14 +49,14 @@ TOML_IMPL_NAMESPACE_START
4949
if constexpr (!is_losslessly_convertible_to_native<unwrapped_type>)
5050
{
5151
if constexpr (std::is_same_v<native_type, int64_t>)
52-
static_assert(dependent_false<T>,
52+
static_assert(always_false<T>,
5353
"Integral value initializers must be losslessly convertible to int64_t");
5454
else if constexpr (std::is_same_v<native_type, double>)
55-
static_assert(dependent_false<T>,
55+
static_assert(always_false<T>,
5656
"Floating-point value initializers must be losslessly convertible to double");
5757
else
5858
static_assert(
59-
dependent_false<T>,
59+
always_false<T>,
6060
"Value initializers must be losslessly convertible to one of the TOML value types");
6161
}
6262

@@ -65,7 +65,7 @@ TOML_IMPL_NAMESPACE_START
6565
#if TOML_ENABLE_WINDOWS_COMPAT
6666
out = new value_type{ narrow(static_cast<T&&>(val)) };
6767
#else
68-
static_assert(dependent_false<T>, "Evaluated unreachable branch!");
68+
static_assert(always_false<T>, "Evaluated unreachable branch!");
6969
#endif
7070
}
7171
else

include/toml++/impl/node_view.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -501,7 +501,7 @@ TOML_NAMESPACE_START
501501

502502
#else
503503

504-
static_assert(impl::dependent_false<T>, "Evaluated unreachable branch!");
504+
static_assert(impl::always_false<T>, "Evaluated unreachable branch!");
505505

506506
#endif
507507
}
@@ -656,7 +656,7 @@ TOML_NAMESPACE_START
656656
#if TOML_ENABLE_WINDOWS_COMPAT
657657
return lhs == impl::narrow(rhs);
658658
#else
659-
static_assert(impl::dependent_false<T>, "Evaluated unreachable branch!");
659+
static_assert(impl::always_false<T>, "Evaluated unreachable branch!");
660660
#endif
661661
}
662662
else

0 commit comments

Comments
 (0)