11
11
#include " make_node.hpp"
12
12
#include " header_start.hpp"
13
13
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
+
14
34
// / \cond
15
35
TOML_IMPL_NAMESPACE_START
16
36
{
@@ -834,51 +854,56 @@ TOML_NAMESPACE_START
834
854
using for_each_elem_ref = impl::copy_cvref<impl::wrap_node<impl::remove_cvref<impl::unwrap_node<T>>>, Array>;
835
855
836
856
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> >>;
840
860
841
861
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>>>;
846
875
847
876
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> >;
857
886
858
887
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>>;
864
890
865
891
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>>;
877
901
878
902
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)
880
905
{
881
- static_assert (can_for_each_any<Func&&, Array&&>,
906
+ static_assert (can_for_each_any<Func&&, Array&&>::value ,
882
907
" TOML array for_each visitors must be invocable for at least one of the toml::node "
883
908
" specializations:" TOML_SA_NODE_TYPE_LIST);
884
909
@@ -887,13 +912,46 @@ TOML_NAMESPACE_START
887
912
using node_ref = impl::copy_cvref<toml::node, Array&&>;
888
913
static_assert (std::is_reference_v<node_ref>);
889
914
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
890
950
const auto keep_going =
891
951
static_cast <node_ref>(static_cast <Array&&>(arr)[i])
892
952
.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)
897
955
{
898
956
using elem_ref = for_each_elem_ref<decltype (elem), Array&&>;
899
957
static_assert (std::is_reference_v<elem_ref>);
@@ -959,6 +1017,7 @@ TOML_NAMESPACE_START
959
1017
960
1018
if (!keep_going)
961
1019
return ;
1020
+ #endif
962
1021
}
963
1022
}
964
1023
@@ -1026,31 +1085,35 @@ TOML_NAMESPACE_START
1026
1085
// /
1027
1086
// / \see node::visit()
1028
1087
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)
1030
1090
{
1031
1091
do_for_each (static_cast <Func&&>(visitor), *this );
1032
1092
return *this ;
1033
1093
}
1034
1094
1035
1095
// / \brief Invokes a visitor on each element in the array (rvalue overload).
1036
1096
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)
1038
1099
{
1039
1100
do_for_each (static_cast <Func&&>(visitor), static_cast <array&&>(*this ));
1040
1101
return static_cast <array&&>(*this );
1041
1102
}
1042
1103
1043
1104
// / \brief Invokes a visitor on each element in the array (const lvalue overload).
1044
1105
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)
1046
1108
{
1047
1109
do_for_each (static_cast <Func&&>(visitor), *this );
1048
1110
return *this ;
1049
1111
}
1050
1112
1051
1113
// / \brief Invokes a visitor on each element in the array (const rvalue overload).
1052
1114
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)
1054
1117
{
1055
1118
do_for_each (static_cast <Func&&>(visitor), static_cast <const array&&>(*this ));
1056
1119
return static_cast <const array&&>(*this );
0 commit comments