fix is_homogeneous with outparam (fixes #231)

This commit is contained in:
Mark Gillard
2024-07-12 11:43:25 +03:00
parent b43f8a032a
commit 7ddb98543c
7 changed files with 148 additions and 127 deletions

View File

@@ -23,6 +23,10 @@ template:
## Unreleased
#### Fixes
- fixed `is_homogeneous()` overloads with `first_nonmatch` outparam being broken in optimized builds (#231) (@Forbinn)
## v3.4.0
- fixed "unresolved symbol" error with nvc++ (#220) (@Tomcat-42)

View File

@@ -11,7 +11,10 @@
// workaround for this: https://github.com/marzer/tomlplusplus/issues/220
#if TOML_NVCC
#define TOML_NVCC_WORKAROUND { return {}; }
#define TOML_NVCC_WORKAROUND \
{ \
return {}; \
}
#else
#define TOML_NVCC_WORKAROUND = 0
#endif
@@ -177,11 +180,11 @@ TOML_NAMESPACE_START
/// \returns True if the node was homogeneous.
///
/// \remarks Always returns `false` for empty tables and arrays.
TOML_PURE_GETTER
TOML_NODISCARD
virtual bool is_homogeneous(node_type ntype, node*& first_nonmatch) noexcept = 0;
/// \brief Checks if a node contains values/elements of only one type (const overload).
TOML_PURE_GETTER
TOML_NODISCARD
virtual bool is_homogeneous(node_type ntype, const node*& first_nonmatch) const noexcept = 0;
/// \brief Checks if the node contains values/elements of only one type.

View File

@@ -290,7 +290,7 @@ TOML_NAMESPACE_START
///
/// \remarks Always returns `false` if the view does not reference a node, or if the viewed node is
/// an empty table or array.
TOML_NODISCARD
TOML_PURE_GETTER
bool is_homogeneous(node_type ntype) const noexcept
{
return node_ ? node_->is_homogeneous(ntype) : false;

View File

@@ -298,11 +298,11 @@ TOML_NAMESPACE_START
TOML_EXPORTED_MEMBER_FUNCTION
bool is_homogeneous(node_type ntype) const noexcept final;
TOML_PURE_GETTER
TOML_NODISCARD
TOML_EXPORTED_MEMBER_FUNCTION
bool is_homogeneous(node_type ntype, node*& first_nonmatch) noexcept final;
TOML_PURE_GETTER
TOML_NODISCARD
TOML_EXPORTED_MEMBER_FUNCTION
bool is_homogeneous(node_type ntype, const node*& first_nonmatch) const noexcept final;

View File

@@ -377,7 +377,7 @@ TOML_NAMESPACE_START
return ntype == node_type::none || ntype == impl::node_type_of<value_type>;
}
TOML_PURE_GETTER
TOML_NODISCARD
bool is_homogeneous(node_type ntype, node*& first_nonmatch) noexcept final
{
if (ntype != node_type::none && ntype != impl::node_type_of<value_type>)
@@ -388,7 +388,7 @@ TOML_NAMESPACE_START
return true;
}
TOML_PURE_GETTER
TOML_NODISCARD
bool is_homogeneous(node_type ntype, const node*& first_nonmatch) const noexcept final
{
if (ntype != node_type::none && ntype != impl::node_type_of<value_type>)
@@ -1041,11 +1041,11 @@ TOML_NAMESPACE_START
"Retrieving values as wide-character strings with node::value_exact() is only "
"supported on Windows with TOML_ENABLE_WINDOWS_COMPAT enabled.");
static_assert((is_native<T> || can_represent_native<T>)&&!is_cvref<T>,
static_assert((is_native<T> || can_represent_native<T>) && !is_cvref<T>,
TOML_SA_VALUE_EXACT_FUNC_MESSAGE("return type of node::value_exact()"));
// prevent additional compiler error spam when the static_assert fails by gating behind if constexpr
if constexpr ((is_native<T> || can_represent_native<T>)&&!is_cvref<T>)
if constexpr ((is_native<T> || can_represent_native<T>) && !is_cvref<T>)
{
if (type() == node_type_of<T>)
return { this->get_value_exact<T>() };
@@ -1063,7 +1063,7 @@ TOML_NAMESPACE_START
static_assert(!is_wide_string<T> || TOML_ENABLE_WINDOWS_COMPAT,
"Retrieving values as wide-character strings with node::value() is only "
"supported on Windows with TOML_ENABLE_WINDOWS_COMPAT enabled.");
static_assert((is_native<T> || can_represent_native<T> || can_partially_represent_native<T>)&&!is_cvref<T>,
static_assert((is_native<T> || can_represent_native<T> || can_partially_represent_native<T>) && !is_cvref<T>,
TOML_SA_VALUE_FUNC_MESSAGE("return type of node::value()"));
// when asking for strings, dates, times and date_times there's no 'fuzzy' conversion

View File

@@ -7,8 +7,9 @@
TEST_CASE("parsing - arrays")
{
parsing_should_succeed(FILE_LINE_ARGS,
R"(
parsing_should_succeed(
FILE_LINE_ARGS,
R"(
integers = [ 1, 2, 3 ]
integers2 = [
1, 2, 3
@@ -22,115 +23,125 @@ TEST_CASE("parsing - arrays")
nested_mixed_array = [ [ 1, 2 ], ["a", "b", "c"] ]
string_array = [ "all", 'strings', """are the same""", '''type''' ]
)"sv,
[](table&& tbl)
{
REQUIRE(tbl["integers"].as<array>());
CHECK(tbl["integers"].is_homogeneous());
CHECK(tbl["integers"].is_homogeneous(node_type::integer));
CHECK(!tbl["integers"].is_homogeneous(node_type::floating_point));
CHECK(tbl["integers"].is_homogeneous<int64_t>());
CHECK(!tbl["integers"].is_homogeneous<double>());
CHECK(tbl["integers"].as<array>()->is_homogeneous());
CHECK(tbl["integers"].as<array>()->is_homogeneous(node_type::integer));
CHECK(!tbl["integers"].as<array>()->is_homogeneous(node_type::floating_point));
CHECK(tbl["integers"].as<array>()->is_homogeneous<int64_t>());
CHECK(!tbl["integers"].as<array>()->is_homogeneous<double>());
CHECK(tbl["integers"].as<array>()->size() == 3);
CHECK(tbl["integers"][0] == 1);
CHECK(tbl["integers"][1] == 2);
CHECK(tbl["integers"][2] == 3);
[](table&& tbl)
{
node* first_nonmatch = {};
REQUIRE(tbl["integers"].as<array>());
CHECK(tbl["integers"].is_homogeneous());
CHECK(tbl["integers"].is_homogeneous(node_type::integer));
CHECK(!tbl["integers"].is_homogeneous(node_type::floating_point));
CHECK(!tbl["integers"].is_homogeneous(node_type::floating_point, first_nonmatch));
CHECK(first_nonmatch != nullptr);
first_nonmatch = {};
REQUIRE(tbl["integers2"].as<array>());
CHECK(tbl["integers2"].is_homogeneous());
CHECK(tbl["integers2"].is_homogeneous(node_type::integer));
CHECK(!tbl["integers2"].is_homogeneous(node_type::floating_point));
CHECK(tbl["integers2"].is_homogeneous<int64_t>());
CHECK(!tbl["integers2"].is_homogeneous<double>());
CHECK(tbl["integers2"].as<array>()->is_homogeneous());
CHECK(tbl["integers2"].as<array>()->is_homogeneous(node_type::integer));
CHECK(!tbl["integers2"].as<array>()->is_homogeneous(node_type::floating_point));
CHECK(tbl["integers2"].as<array>()->is_homogeneous<int64_t>());
CHECK(!tbl["integers2"].as<array>()->is_homogeneous<double>());
CHECK(tbl["integers2"].as<array>()->size() == 3);
CHECK(tbl["integers2"][0] == 1);
CHECK(tbl["integers2"][1] == 2);
CHECK(tbl["integers2"][2] == 3);
CHECK(tbl["integers"].is_homogeneous<int64_t>());
CHECK(!tbl["integers"].is_homogeneous<double>());
CHECK(tbl["integers"].as<array>()->is_homogeneous());
CHECK(tbl["integers"].as<array>()->is_homogeneous(node_type::integer));
CHECK(!tbl["integers"].as<array>()->is_homogeneous(node_type::floating_point));
CHECK(!tbl["integers"].as<array>()->is_homogeneous(node_type::floating_point, first_nonmatch));
CHECK(first_nonmatch != nullptr);
first_nonmatch = {};
REQUIRE(tbl["integers3"].as<array>());
CHECK(tbl["integers3"].is_homogeneous());
CHECK(tbl["integers3"].is_homogeneous(node_type::integer));
CHECK(!tbl["integers3"].is_homogeneous(node_type::floating_point));
CHECK(tbl["integers3"].is_homogeneous<int64_t>());
CHECK(!tbl["integers3"].is_homogeneous<double>());
CHECK(tbl["integers3"].as<array>()->is_homogeneous());
CHECK(tbl["integers3"].as<array>()->is_homogeneous(node_type::integer));
CHECK(!tbl["integers3"].as<array>()->is_homogeneous(node_type::floating_point));
CHECK(tbl["integers3"].as<array>()->is_homogeneous<int64_t>());
CHECK(!tbl["integers3"].as<array>()->is_homogeneous<double>());
CHECK(tbl["integers3"].as<array>()->size() == 2);
CHECK(tbl["integers3"][0] == 1);
CHECK(tbl["integers3"][1] == 2);
CHECK(tbl["integers"].as<array>()->is_homogeneous<int64_t>());
CHECK(!tbl["integers"].as<array>()->is_homogeneous<double>());
REQUIRE(tbl["colors"].as<array>());
CHECK(tbl["colors"].is_homogeneous());
CHECK(tbl["colors"].is_homogeneous(node_type::string));
CHECK(!tbl["colors"].is_homogeneous(node_type::floating_point));
CHECK(tbl["colors"].is_homogeneous<std::string>());
CHECK(!tbl["colors"].is_homogeneous<double>());
CHECK(tbl["colors"].as<array>()->is_homogeneous());
CHECK(tbl["colors"].as<array>()->is_homogeneous(node_type::string));
CHECK(!tbl["colors"].as<array>()->is_homogeneous(node_type::floating_point));
CHECK(tbl["colors"].as<array>()->is_homogeneous<std::string>());
CHECK(!tbl["colors"].as<array>()->is_homogeneous<double>());
CHECK(tbl["colors"].as<array>()->size() == 3);
CHECK(tbl["colors"][0] == "red"sv);
CHECK(tbl["colors"][1] == "yellow"sv);
CHECK(tbl["colors"][2] == "green"sv);
CHECK(tbl["integers"].as<array>()->size() == 3);
CHECK(tbl["integers"][0] == 1);
CHECK(tbl["integers"][1] == 2);
CHECK(tbl["integers"][2] == 3);
REQUIRE(tbl["nested_array_of_int"].as<array>());
CHECK(tbl["nested_array_of_int"].as<array>()->is_homogeneous());
CHECK(tbl["nested_array_of_int"].as<array>()->size() == 2);
REQUIRE(tbl["nested_array_of_int"][0].as<array>());
CHECK(tbl["nested_array_of_int"][0].as<array>()->is_homogeneous());
CHECK(tbl["nested_array_of_int"][0].as<array>()->size() == 2);
CHECK(tbl["nested_array_of_int"][0][0] == 1);
CHECK(tbl["nested_array_of_int"][0][1] == 2);
REQUIRE(tbl["nested_array_of_int"][1].as<array>());
CHECK(tbl["nested_array_of_int"][1].as<array>()->is_homogeneous());
CHECK(tbl["nested_array_of_int"][1].as<array>()->size() == 3);
CHECK(tbl["nested_array_of_int"][1][0] == 3);
CHECK(tbl["nested_array_of_int"][1][1] == 4);
CHECK(tbl["nested_array_of_int"][1][2] == 5);
REQUIRE(tbl["integers2"].as<array>());
CHECK(tbl["integers2"].is_homogeneous());
CHECK(tbl["integers2"].is_homogeneous(node_type::integer));
CHECK(!tbl["integers2"].is_homogeneous(node_type::floating_point));
CHECK(tbl["integers2"].is_homogeneous<int64_t>());
CHECK(!tbl["integers2"].is_homogeneous<double>());
CHECK(tbl["integers2"].as<array>()->is_homogeneous());
CHECK(tbl["integers2"].as<array>()->is_homogeneous(node_type::integer));
CHECK(!tbl["integers2"].as<array>()->is_homogeneous(node_type::floating_point));
CHECK(tbl["integers2"].as<array>()->is_homogeneous<int64_t>());
CHECK(!tbl["integers2"].as<array>()->is_homogeneous<double>());
CHECK(tbl["integers2"].as<array>()->size() == 3);
CHECK(tbl["integers2"][0] == 1);
CHECK(tbl["integers2"][1] == 2);
CHECK(tbl["integers2"][2] == 3);
REQUIRE(tbl["nested_mixed_array"].as<array>());
CHECK(tbl["nested_mixed_array"].as<array>()->is_homogeneous());
CHECK(tbl["nested_mixed_array"].as<array>()->size() == 2);
REQUIRE(tbl["nested_mixed_array"][0].as<array>());
CHECK(tbl["nested_mixed_array"][0].as<array>()->is_homogeneous());
CHECK(tbl["nested_mixed_array"][0].as<array>()->size() == 2);
CHECK(tbl["nested_mixed_array"][0][0] == 1);
CHECK(tbl["nested_mixed_array"][0][1] == 2);
REQUIRE(tbl["nested_mixed_array"][1].as<array>());
CHECK(tbl["nested_mixed_array"][1].as<array>()->is_homogeneous());
CHECK(tbl["nested_mixed_array"][1].as<array>()->size() == 3);
CHECK(tbl["nested_mixed_array"][1][0] == "a"sv);
CHECK(tbl["nested_mixed_array"][1][1] == "b"sv);
CHECK(tbl["nested_mixed_array"][1][2] == "c"sv);
REQUIRE(tbl["integers3"].as<array>());
CHECK(tbl["integers3"].is_homogeneous());
CHECK(tbl["integers3"].is_homogeneous(node_type::integer));
CHECK(!tbl["integers3"].is_homogeneous(node_type::floating_point));
CHECK(tbl["integers3"].is_homogeneous<int64_t>());
CHECK(!tbl["integers3"].is_homogeneous<double>());
CHECK(tbl["integers3"].as<array>()->is_homogeneous());
CHECK(tbl["integers3"].as<array>()->is_homogeneous(node_type::integer));
CHECK(!tbl["integers3"].as<array>()->is_homogeneous(node_type::floating_point));
CHECK(tbl["integers3"].as<array>()->is_homogeneous<int64_t>());
CHECK(!tbl["integers3"].as<array>()->is_homogeneous<double>());
CHECK(tbl["integers3"].as<array>()->size() == 2);
CHECK(tbl["integers3"][0] == 1);
CHECK(tbl["integers3"][1] == 2);
REQUIRE(tbl["string_array"].as<array>());
CHECK(tbl["string_array"].as<array>()->is_homogeneous());
CHECK(tbl["string_array"].as<array>()->size() == 4);
CHECK(tbl["string_array"][0] == "all"sv);
CHECK(tbl["string_array"][1] == "strings"sv);
CHECK(tbl["string_array"][2] == "are the same"sv);
CHECK(tbl["string_array"][3] == "type"sv);
REQUIRE(tbl["integers"].as<array>());
CHECK(tbl["integers"].as<array>()->is_homogeneous());
CHECK(tbl["integers"].as<array>()->size() == 3);
CHECK(tbl["integers"][0] == 1);
CHECK(tbl["integers"][1] == 2);
CHECK(tbl["integers"][2] == 3);
});
REQUIRE(tbl["colors"].as<array>());
CHECK(tbl["colors"].is_homogeneous());
CHECK(tbl["colors"].is_homogeneous(node_type::string));
CHECK(!tbl["colors"].is_homogeneous(node_type::floating_point));
CHECK(tbl["colors"].is_homogeneous<std::string>());
CHECK(!tbl["colors"].is_homogeneous<double>());
CHECK(tbl["colors"].as<array>()->is_homogeneous());
CHECK(tbl["colors"].as<array>()->is_homogeneous(node_type::string));
CHECK(!tbl["colors"].as<array>()->is_homogeneous(node_type::floating_point));
CHECK(tbl["colors"].as<array>()->is_homogeneous<std::string>());
CHECK(!tbl["colors"].as<array>()->is_homogeneous<double>());
CHECK(tbl["colors"].as<array>()->size() == 3);
CHECK(tbl["colors"][0] == "red"sv);
CHECK(tbl["colors"][1] == "yellow"sv);
CHECK(tbl["colors"][2] == "green"sv);
REQUIRE(tbl["nested_array_of_int"].as<array>());
CHECK(tbl["nested_array_of_int"].as<array>()->is_homogeneous());
CHECK(tbl["nested_array_of_int"].as<array>()->size() == 2);
REQUIRE(tbl["nested_array_of_int"][0].as<array>());
CHECK(tbl["nested_array_of_int"][0].as<array>()->is_homogeneous());
CHECK(tbl["nested_array_of_int"][0].as<array>()->size() == 2);
CHECK(tbl["nested_array_of_int"][0][0] == 1);
CHECK(tbl["nested_array_of_int"][0][1] == 2);
REQUIRE(tbl["nested_array_of_int"][1].as<array>());
CHECK(tbl["nested_array_of_int"][1].as<array>()->is_homogeneous());
CHECK(tbl["nested_array_of_int"][1].as<array>()->size() == 3);
CHECK(tbl["nested_array_of_int"][1][0] == 3);
CHECK(tbl["nested_array_of_int"][1][1] == 4);
CHECK(tbl["nested_array_of_int"][1][2] == 5);
REQUIRE(tbl["nested_mixed_array"].as<array>());
CHECK(tbl["nested_mixed_array"].as<array>()->is_homogeneous());
CHECK(tbl["nested_mixed_array"].as<array>()->size() == 2);
REQUIRE(tbl["nested_mixed_array"][0].as<array>());
CHECK(tbl["nested_mixed_array"][0].as<array>()->is_homogeneous());
CHECK(tbl["nested_mixed_array"][0].as<array>()->size() == 2);
CHECK(tbl["nested_mixed_array"][0][0] == 1);
CHECK(tbl["nested_mixed_array"][0][1] == 2);
REQUIRE(tbl["nested_mixed_array"][1].as<array>());
CHECK(tbl["nested_mixed_array"][1].as<array>()->is_homogeneous());
CHECK(tbl["nested_mixed_array"][1].as<array>()->size() == 3);
CHECK(tbl["nested_mixed_array"][1][0] == "a"sv);
CHECK(tbl["nested_mixed_array"][1][1] == "b"sv);
CHECK(tbl["nested_mixed_array"][1][2] == "c"sv);
REQUIRE(tbl["string_array"].as<array>());
CHECK(tbl["string_array"].as<array>()->is_homogeneous());
CHECK(tbl["string_array"].as<array>()->size() == 4);
CHECK(tbl["string_array"][0] == "all"sv);
CHECK(tbl["string_array"][1] == "strings"sv);
CHECK(tbl["string_array"][2] == "are the same"sv);
CHECK(tbl["string_array"][3] == "type"sv);
REQUIRE(tbl["integers"].as<array>());
CHECK(tbl["integers"].as<array>()->is_homogeneous());
CHECK(tbl["integers"].as<array>()->size() == 3);
CHECK(tbl["integers"][0] == 1);
CHECK(tbl["integers"][1] == 2);
CHECK(tbl["integers"][2] == 3);
});
// toml/issues/665 (heterogeneous arrays)
#if TOML_LANG_AT_LEAST(1, 0, 0)

View File

@@ -3642,7 +3642,10 @@ TOML_PUSH_WARNINGS;
// workaround for this: https://github.com/marzer/tomlplusplus/issues/220
#if TOML_NVCC
#define TOML_NVCC_WORKAROUND { return {}; }
#define TOML_NVCC_WORKAROUND \
{ \
return {}; \
}
#else
#define TOML_NVCC_WORKAROUND = 0
#endif
@@ -3767,10 +3770,10 @@ TOML_NAMESPACE_START
TOML_EXPORTED_MEMBER_FUNCTION
virtual ~node() noexcept;
TOML_PURE_GETTER
TOML_NODISCARD
virtual bool is_homogeneous(node_type ntype, node*& first_nonmatch) noexcept = 0;
TOML_PURE_GETTER
TOML_NODISCARD
virtual bool is_homogeneous(node_type ntype, const node*& first_nonmatch) const noexcept = 0;
TOML_PURE_GETTER
@@ -4429,7 +4432,7 @@ TOML_NAMESPACE_START
return node_->is_homogeneous(ntype, first_nonmatch);
}
TOML_NODISCARD
TOML_PURE_GETTER
bool is_homogeneous(node_type ntype) const noexcept
{
return node_ ? node_->is_homogeneous(ntype) : false;
@@ -5115,7 +5118,7 @@ TOML_NAMESPACE_START
return ntype == node_type::none || ntype == impl::node_type_of<value_type>;
}
TOML_PURE_GETTER
TOML_NODISCARD
bool is_homogeneous(node_type ntype, node*& first_nonmatch) noexcept final
{
if (ntype != node_type::none && ntype != impl::node_type_of<value_type>)
@@ -5126,7 +5129,7 @@ TOML_NAMESPACE_START
return true;
}
TOML_PURE_GETTER
TOML_NODISCARD
bool is_homogeneous(node_type ntype, const node*& first_nonmatch) const noexcept final
{
if (ntype != node_type::none && ntype != impl::node_type_of<value_type>)
@@ -5640,11 +5643,11 @@ TOML_NAMESPACE_START
"Retrieving values as wide-character strings with node::value_exact() is only "
"supported on Windows with TOML_ENABLE_WINDOWS_COMPAT enabled.");
static_assert((is_native<T> || can_represent_native<T>)&&!is_cvref<T>,
static_assert((is_native<T> || can_represent_native<T>) && !is_cvref<T>,
TOML_SA_VALUE_EXACT_FUNC_MESSAGE("return type of node::value_exact()"));
// prevent additional compiler error spam when the static_assert fails by gating behind if constexpr
if constexpr ((is_native<T> || can_represent_native<T>)&&!is_cvref<T>)
if constexpr ((is_native<T> || can_represent_native<T>) && !is_cvref<T>)
{
if (type() == node_type_of<T>)
return { this->get_value_exact<T>() };
@@ -5662,7 +5665,7 @@ TOML_NAMESPACE_START
static_assert(!is_wide_string<T> || TOML_ENABLE_WINDOWS_COMPAT,
"Retrieving values as wide-character strings with node::value() is only "
"supported on Windows with TOML_ENABLE_WINDOWS_COMPAT enabled.");
static_assert((is_native<T> || can_represent_native<T> || can_partially_represent_native<T>)&&!is_cvref<T>,
static_assert((is_native<T> || can_represent_native<T> || can_partially_represent_native<T>) && !is_cvref<T>,
TOML_SA_VALUE_FUNC_MESSAGE("return type of node::value()"));
// when asking for strings, dates, times and date_times there's no 'fuzzy' conversion
@@ -7718,11 +7721,11 @@ TOML_NAMESPACE_START
TOML_EXPORTED_MEMBER_FUNCTION
bool is_homogeneous(node_type ntype) const noexcept final;
TOML_PURE_GETTER
TOML_NODISCARD
TOML_EXPORTED_MEMBER_FUNCTION
bool is_homogeneous(node_type ntype, node*& first_nonmatch) noexcept final;
TOML_PURE_GETTER
TOML_NODISCARD
TOML_EXPORTED_MEMBER_FUNCTION
bool is_homogeneous(node_type ntype, const node*& first_nonmatch) const noexcept final;