summaryrefslogtreecommitdiff
path: root/tomlplusplus/tests/for_each.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tomlplusplus/tests/for_each.cpp')
-rw-r--r--tomlplusplus/tests/for_each.cpp380
1 files changed, 380 insertions, 0 deletions
diff --git a/tomlplusplus/tests/for_each.cpp b/tomlplusplus/tests/for_each.cpp
new file mode 100644
index 0000000000..6d28581281
--- /dev/null
+++ b/tomlplusplus/tests/for_each.cpp
@@ -0,0 +1,380 @@
+// This file is a part of toml++ and is subject to the the terms of the MIT license.
+// Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
+// See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
+// SPDX-License-Identifier: MIT
+
+#include "tests.hpp"
+TOML_DISABLE_SPAM_WARNINGS;
+
+TEST_CASE("array::for_each")
+{
+ toml::array arr{ 0, 1, 2, 3.0, "four", "five", 6 };
+
+ // check lvalue propagates correctly
+ static_cast<array&>(arr).for_each(
+ [](auto&& elem, size_t) noexcept
+ {
+ using elem_ref_type = decltype(elem);
+ static_assert(std::is_lvalue_reference_v<elem_ref_type>);
+
+ using elem_type = std::remove_reference_t<elem_ref_type>;
+ static_assert(!std::is_const_v<elem_type>);
+ static_assert(!std::is_volatile_v<elem_type>);
+ });
+ static_cast<array&>(arr).for_each(
+ [](size_t, auto&& elem) noexcept
+ {
+ using elem_ref_type = decltype(elem);
+ static_assert(std::is_lvalue_reference_v<elem_ref_type>);
+
+ using elem_type = std::remove_reference_t<elem_ref_type>;
+ static_assert(!std::is_const_v<elem_type>);
+ static_assert(!std::is_volatile_v<elem_type>);
+ });
+ static_cast<array&>(arr).for_each(
+ [](auto&& elem) noexcept
+ {
+ using elem_ref_type = decltype(elem);
+ static_assert(std::is_lvalue_reference_v<elem_ref_type>);
+
+ using elem_type = std::remove_reference_t<elem_ref_type>;
+ static_assert(!std::is_const_v<elem_type>);
+ static_assert(!std::is_volatile_v<elem_type>);
+ });
+
+ // check rvalue propagates correctly
+ static_cast<array&&>(arr).for_each(
+ [](auto&& elem, size_t) noexcept
+ {
+ using elem_ref_type = decltype(elem);
+ static_assert(std::is_rvalue_reference_v<elem_ref_type>);
+
+ using elem_type = std::remove_reference_t<elem_ref_type>;
+ static_assert(!std::is_const_v<elem_type>);
+ static_assert(!std::is_volatile_v<elem_type>);
+ });
+ static_cast<array&&>(arr).for_each(
+ [](size_t, auto&& elem) noexcept
+ {
+ using elem_ref_type = decltype(elem);
+ static_assert(std::is_rvalue_reference_v<elem_ref_type>);
+
+ using elem_type = std::remove_reference_t<elem_ref_type>;
+ static_assert(!std::is_const_v<elem_type>);
+ static_assert(!std::is_volatile_v<elem_type>);
+ });
+ static_cast<array&&>(arr).for_each(
+ [](auto&& elem) noexcept
+ {
+ using elem_ref_type = decltype(elem);
+ static_assert(std::is_rvalue_reference_v<elem_ref_type>);
+
+ using elem_type = std::remove_reference_t<elem_ref_type>;
+ static_assert(!std::is_const_v<elem_type>);
+ static_assert(!std::is_volatile_v<elem_type>);
+ });
+
+ // check const lvalue propagates correctly
+ static_cast<const array&>(arr).for_each(
+ [](auto&& elem, size_t) noexcept
+ {
+ using elem_ref_type = decltype(elem);
+ static_assert(std::is_lvalue_reference_v<elem_ref_type>);
+
+ using elem_type = std::remove_reference_t<elem_ref_type>;
+ static_assert(std::is_const_v<elem_type>);
+ static_assert(!std::is_volatile_v<elem_type>);
+ });
+ static_cast<const array&>(arr).for_each(
+ [](size_t, auto&& elem) noexcept
+ {
+ using elem_ref_type = decltype(elem);
+ static_assert(std::is_lvalue_reference_v<elem_ref_type>);
+
+ using elem_type = std::remove_reference_t<elem_ref_type>;
+ static_assert(std::is_const_v<elem_type>);
+ static_assert(!std::is_volatile_v<elem_type>);
+ });
+ static_cast<const array&>(arr).for_each(
+ [](auto&& elem) noexcept
+ {
+ using elem_ref_type = decltype(elem);
+ static_assert(std::is_lvalue_reference_v<elem_ref_type>);
+
+ using elem_type = std::remove_reference_t<elem_ref_type>;
+ static_assert(std::is_const_v<elem_type>);
+ static_assert(!std::is_volatile_v<elem_type>);
+ });
+
+ // check const rvalue propagates correctly
+ static_cast<const array&&>(arr).for_each(
+ [](auto&& elem, size_t) noexcept
+ {
+ using elem_ref_type = decltype(elem);
+ static_assert(std::is_rvalue_reference_v<elem_ref_type>);
+
+ using elem_type = std::remove_reference_t<elem_ref_type>;
+ static_assert(std::is_const_v<elem_type>);
+ static_assert(!std::is_volatile_v<elem_type>);
+ });
+ static_cast<const array&&>(arr).for_each(
+ [](size_t, auto&& elem) noexcept
+ {
+ using elem_ref_type = decltype(elem);
+ static_assert(std::is_rvalue_reference_v<elem_ref_type>);
+
+ using elem_type = std::remove_reference_t<elem_ref_type>;
+ static_assert(std::is_const_v<elem_type>);
+ static_assert(!std::is_volatile_v<elem_type>);
+ });
+ static_cast<const array&&>(arr).for_each(
+ [](auto&& elem) noexcept
+ {
+ using elem_ref_type = decltype(elem);
+ static_assert(std::is_rvalue_reference_v<elem_ref_type>);
+
+ using elem_type = std::remove_reference_t<elem_ref_type>;
+ static_assert(std::is_const_v<elem_type>);
+ static_assert(!std::is_volatile_v<elem_type>);
+ });
+
+ // check noexcept - func(elem, i)
+ {
+ static constexpr auto throwing_visitor = [](auto&&, size_t) noexcept(false) {};
+ static constexpr auto non_throwing_visitor = [](auto&&, size_t) noexcept(true) {};
+ static_assert(!noexcept(static_cast<array&>(arr).for_each(throwing_visitor)));
+ static_assert(!noexcept(static_cast<array&&>(arr).for_each(throwing_visitor)));
+ static_assert(!noexcept(static_cast<const array&>(arr).for_each(throwing_visitor)));
+ static_assert(!noexcept(static_cast<const array&&>(arr).for_each(throwing_visitor)));
+ static_assert(noexcept(static_cast<array&>(arr).for_each(non_throwing_visitor)));
+ static_assert(noexcept(static_cast<array&&>(arr).for_each(non_throwing_visitor)));
+ static_assert(noexcept(static_cast<const array&>(arr).for_each(non_throwing_visitor)));
+ static_assert(noexcept(static_cast<const array&&>(arr).for_each(non_throwing_visitor)));
+ }
+
+ // check noexcept - func(i, elem)
+ {
+ static constexpr auto throwing_visitor = [](size_t, auto&&) noexcept(false) {};
+ static constexpr auto non_throwing_visitor = [](size_t, auto&&) noexcept(true) {};
+ static_assert(!noexcept(static_cast<array&>(arr).for_each(throwing_visitor)));
+ static_assert(!noexcept(static_cast<array&&>(arr).for_each(throwing_visitor)));
+ static_assert(!noexcept(static_cast<const array&>(arr).for_each(throwing_visitor)));
+ static_assert(!noexcept(static_cast<const array&&>(arr).for_each(throwing_visitor)));
+ static_assert(noexcept(static_cast<array&>(arr).for_each(non_throwing_visitor)));
+ static_assert(noexcept(static_cast<array&&>(arr).for_each(non_throwing_visitor)));
+ static_assert(noexcept(static_cast<const array&>(arr).for_each(non_throwing_visitor)));
+ static_assert(noexcept(static_cast<const array&&>(arr).for_each(non_throwing_visitor)));
+ }
+
+ // check noexcept - func(elem)
+ {
+ static constexpr auto throwing_visitor = [](auto&&) noexcept(false) {};
+ static constexpr auto non_throwing_visitor = [](auto&&) noexcept(true) {};
+ static_assert(!noexcept(static_cast<array&>(arr).for_each(throwing_visitor)));
+ static_assert(!noexcept(static_cast<array&&>(arr).for_each(throwing_visitor)));
+ static_assert(!noexcept(static_cast<const array&>(arr).for_each(throwing_visitor)));
+ static_assert(!noexcept(static_cast<const array&&>(arr).for_each(throwing_visitor)));
+ static_assert(noexcept(static_cast<array&>(arr).for_each(non_throwing_visitor)));
+ static_assert(noexcept(static_cast<array&&>(arr).for_each(non_throwing_visitor)));
+ static_assert(noexcept(static_cast<const array&>(arr).for_each(non_throwing_visitor)));
+ static_assert(noexcept(static_cast<const array&&>(arr).for_each(non_throwing_visitor)));
+ }
+
+ // check that the iteration actually does what it says on the box
+ {
+ toml::array arr2;
+ arr.for_each([&](const auto& val) { arr2.push_back(val); });
+ CHECK(arr == arr2);
+ }
+
+ // check that visitation works for a specific type
+ {
+ toml::array arr2;
+ arr.for_each([&](const toml::value<int64_t>& val) { arr2.push_back(val); });
+ CHECK(arr2 == toml::array{ 0, 1, 2, 6 });
+ }
+
+#if !TOML_RETURN_BOOL_FROM_FOR_EACH_BROKEN
+
+ // check that early-stopping works
+ {
+ toml::array arr2;
+ arr.for_each(
+ [&](const auto& val)
+ {
+ if constexpr (!toml::is_number<decltype(val)>)
+ return false;
+ else
+ {
+ arr2.push_back(val);
+ return true;
+ }
+ });
+ CHECK(arr2 == toml::array{ 0, 1, 2, 3.0 });
+ }
+
+#endif
+}
+
+TEST_CASE("table::for_each")
+{
+ table tbl{ { "zero", 0 }, //
+ { "one", 1 }, //
+ { "two", 2 }, //
+ { "three", 3.0 }, //
+ { "four", "four" }, //
+ { "five", "five" }, //
+ { "six", 6 } };
+
+ // check lvalue propagates correctly
+ static_cast<table&>(tbl).for_each(
+ [](const toml::key&, auto&& elem) noexcept
+ {
+ using elem_ref_type = decltype(elem);
+ static_assert(std::is_lvalue_reference_v<elem_ref_type>);
+
+ using elem_type = std::remove_reference_t<elem_ref_type>;
+ static_assert(!std::is_const_v<elem_type>);
+ static_assert(!std::is_volatile_v<elem_type>);
+ });
+ static_cast<table&>(tbl).for_each(
+ [](auto&& elem) noexcept
+ {
+ using elem_ref_type = decltype(elem);
+ static_assert(std::is_lvalue_reference_v<elem_ref_type>);
+
+ using elem_type = std::remove_reference_t<elem_ref_type>;
+ static_assert(!std::is_const_v<elem_type>);
+ static_assert(!std::is_volatile_v<elem_type>);
+ });
+
+ // check rvalue propagates correctly
+ static_cast<table&&>(tbl).for_each(
+ [](const toml::key&, auto&& elem) noexcept
+ {
+ using elem_ref_type = decltype(elem);
+ static_assert(std::is_rvalue_reference_v<elem_ref_type>);
+
+ using elem_type = std::remove_reference_t<elem_ref_type>;
+ static_assert(!std::is_const_v<elem_type>);
+ static_assert(!std::is_volatile_v<elem_type>);
+ });
+ static_cast<table&&>(tbl).for_each(
+ [](auto&& elem) noexcept
+ {
+ using elem_ref_type = decltype(elem);
+ static_assert(std::is_rvalue_reference_v<elem_ref_type>);
+
+ using elem_type = std::remove_reference_t<elem_ref_type>;
+ static_assert(!std::is_const_v<elem_type>);
+ static_assert(!std::is_volatile_v<elem_type>);
+ });
+
+ // check const lvalue propagates correctly
+ static_cast<const table&>(tbl).for_each(
+ [](const toml::key&, auto&& elem) noexcept
+ {
+ using elem_ref_type = decltype(elem);
+ static_assert(std::is_lvalue_reference_v<elem_ref_type>);
+
+ using elem_type = std::remove_reference_t<elem_ref_type>;
+ static_assert(std::is_const_v<elem_type>);
+ static_assert(!std::is_volatile_v<elem_type>);
+ });
+ static_cast<const table&>(tbl).for_each(
+ [](auto&& elem) noexcept
+ {
+ using elem_ref_type = decltype(elem);
+ static_assert(std::is_lvalue_reference_v<elem_ref_type>);
+
+ using elem_type = std::remove_reference_t<elem_ref_type>;
+ static_assert(std::is_const_v<elem_type>);
+ static_assert(!std::is_volatile_v<elem_type>);
+ });
+
+ // check const rvalue propagates correctly
+ static_cast<const table&&>(tbl).for_each(
+ [](const toml::key&, auto&& elem) noexcept
+ {
+ using elem_ref_type = decltype(elem);
+ static_assert(std::is_rvalue_reference_v<elem_ref_type>);
+
+ using elem_type = std::remove_reference_t<elem_ref_type>;
+ static_assert(std::is_const_v<elem_type>);
+ static_assert(!std::is_volatile_v<elem_type>);
+ });
+ static_cast<const table&&>(tbl).for_each(
+ [](auto&& elem) noexcept
+ {
+ using elem_ref_type = decltype(elem);
+ static_assert(std::is_rvalue_reference_v<elem_ref_type>);
+
+ using elem_type = std::remove_reference_t<elem_ref_type>;
+ static_assert(std::is_const_v<elem_type>);
+ static_assert(!std::is_volatile_v<elem_type>);
+ });
+
+ // check noexcept - func(key, value)
+ {
+ static constexpr auto throwing_visitor = [](const toml::key&, auto&&) noexcept(false) {};
+ static constexpr auto non_throwing_visitor = [](const toml::key&, auto&&) noexcept(true) {};
+ static_assert(!noexcept(static_cast<table&>(tbl).for_each(throwing_visitor)));
+ static_assert(!noexcept(static_cast<table&&>(tbl).for_each(throwing_visitor)));
+ static_assert(!noexcept(static_cast<const table&>(tbl).for_each(throwing_visitor)));
+ static_assert(!noexcept(static_cast<const table&&>(tbl).for_each(throwing_visitor)));
+ static_assert(noexcept(static_cast<table&>(tbl).for_each(non_throwing_visitor)));
+ static_assert(noexcept(static_cast<table&&>(tbl).for_each(non_throwing_visitor)));
+ static_assert(noexcept(static_cast<const table&>(tbl).for_each(non_throwing_visitor)));
+ static_assert(noexcept(static_cast<const table&&>(tbl).for_each(non_throwing_visitor)));
+ }
+
+ // check noexcept - func(value)
+ {
+ static constexpr auto throwing_visitor = [](auto&&) noexcept(false) {};
+ static constexpr auto non_throwing_visitor = [](auto&&) noexcept(true) {};
+ static_assert(!noexcept(static_cast<table&>(tbl).for_each(throwing_visitor)));
+ static_assert(!noexcept(static_cast<table&&>(tbl).for_each(throwing_visitor)));
+ static_assert(!noexcept(static_cast<const table&>(tbl).for_each(throwing_visitor)));
+ static_assert(!noexcept(static_cast<const table&&>(tbl).for_each(throwing_visitor)));
+ static_assert(noexcept(static_cast<table&>(tbl).for_each(non_throwing_visitor)));
+ static_assert(noexcept(static_cast<table&&>(tbl).for_each(non_throwing_visitor)));
+ static_assert(noexcept(static_cast<const table&>(tbl).for_each(non_throwing_visitor)));
+ static_assert(noexcept(static_cast<const table&&>(tbl).for_each(non_throwing_visitor)));
+ }
+
+ // check that the iteration actually does what it says on the box
+ {
+ toml::table tbl2;
+ tbl.for_each([&](auto&& key, auto&& val) { tbl2.insert_or_assign(key, val); });
+ CHECK(tbl == tbl2);
+ }
+
+ // check that visitation works for a specific type
+ {
+ toml::table tbl2;
+ tbl.for_each([&](auto&& key, const toml::value<int64_t>& val) { tbl2.insert_or_assign(key, val); });
+ CHECK(tbl2
+ == table{ { "zero", 0 }, //
+ { "one", 1 }, //
+ { "two", 2 }, //
+ { "six", 6 } });
+ }
+
+#if !TOML_RETURN_BOOL_FROM_FOR_EACH_BROKEN
+
+ // check that early-stopping works
+ {
+ toml::table tbl2;
+ size_t added{};
+ tbl.for_each(
+ [&](auto&& key, const auto& val)
+ {
+ tbl2.insert_or_assign(key, val);
+ added++;
+ return added < 3u;
+ });
+ CHECK(tbl2.size() == 3u);
+ }
+
+#endif
+}