added copy construction/assignment for arrays. tables and values

In service of satisfying #49.
This commit is contained in:
Mark Gillard 2020-07-27 13:38:01 +03:00
parent 539aad89f4
commit 17d1876529
12 changed files with 470 additions and 150 deletions

View File

@ -316,3 +316,9 @@ pre > p.godbolt
{
float: right;
}
@media only screen and ((max-width: 575px) or ((hover: none) and (pointer: coarse)))
{
.godbolt {
display: none;
}
}

View File

@ -176,16 +176,13 @@ TOML_IMPL_NAMESPACE_START
template <typename T>
[[nodiscard]]
TOML_ATTR(returns_nonnull)
TOML_ALWAYS_INLINE
auto* make_node(T&& val) noexcept
auto* make_node_specialized(T&& val) noexcept
{
using type = unwrap_node<remove_cvref_t<T>>;
static_assert(!std::is_same_v<type, node>);
if constexpr (is_one_of<type, array, table>)
{
static_assert(
std::is_rvalue_reference_v<decltype(val)>,
"Tables and arrays may only be moved (not copied)."
);
return new type{ std::forward<T>(val) };
}
else
@ -215,7 +212,23 @@ TOML_IMPL_NAMESPACE_START
template <typename T>
[[nodiscard]]
TOML_ATTR(returns_nonnull)
TOML_ALWAYS_INLINE
auto* make_node(T&& val) noexcept
{
using type = unwrap_node<remove_cvref_t<T>>;
if constexpr (std::is_same_v<type, node>)
{
return std::forward<T>(val).visit([](auto&& concrete) noexcept
{
return static_cast<toml::node*>(make_node_specialized(std::forward<decltype(concrete)>(concrete)));
});
}
else
return make_node_specialized(std::forward<T>(val));
}
template <typename T>
[[nodiscard]]
TOML_ATTR(returns_nonnull)
auto* make_node(inserter<T>&& val) noexcept
{
return make_node(std::move(val.value));
@ -308,10 +321,20 @@ TOML_NAMESPACE_START
TOML_NODISCARD_CTOR
array() noexcept;
/// \brief Copy constructor.
TOML_NODISCARD_CTOR
array(const array&) noexcept;
/// \brief Move constructor.
TOML_NODISCARD_CTOR
array(array&& other) noexcept;
/// \brief Copy-assignment operator.
array& operator= (const array&) noexcept;
/// \brief Move-assignment operator.
array& operator= (array&& rhs) noexcept;
/// \brief Constructs an array with one or more initial elements.
///
/// \detail \cpp
@ -345,7 +368,10 @@ TOML_NAMESPACE_START
/// \tparam ElemTypes One of the TOML node or value types (or a type promotable to one).
/// \param val The node or value used to initialize element 0.
/// \param vals The nodes or values used to initialize elements 1...N.
template <typename ElemType, typename... ElemTypes>
template <typename ElemType, typename... ElemTypes, typename = std::enable_if_t<
(sizeof...(ElemTypes) > 0_sz)
|| !std::is_same_v<impl::remove_cvref_t<ElemType>, array>
>>
TOML_NODISCARD_CTOR
explicit array(ElemType&& val, ElemTypes&&... vals)
{
@ -360,11 +386,6 @@ TOML_NAMESPACE_START
}
}
/// \brief Move-assignment operator.
array& operator= (array&& rhs) noexcept;
array(const array&) = delete;
array& operator= (const array&) = delete;
/// \brief Always returns node_type::array for array nodes.
[[nodiscard]] node_type type() const noexcept override;

View File

@ -19,6 +19,49 @@ TOML_DISABLE_PADDING_WARNINGS
TOML_NAMESPACE_START
{
TOML_EXTERNAL_LINKAGE
array::array() noexcept = default;
TOML_EXTERNAL_LINKAGE
array::array(const array& other) noexcept
: node{ other }
{
elements.reserve(other.elements.size());
for (const auto& elem : other)
elements.emplace_back(impl::make_node(elem));
}
TOML_EXTERNAL_LINKAGE
array::array(array&& other) noexcept
: node{ std::move(other) },
elements{ std::move(other.elements) }
{}
TOML_EXTERNAL_LINKAGE
array& array::operator= (const array& rhs) noexcept
{
if (&rhs != this)
{
node::operator=(rhs);
elements.clear();
elements.reserve(rhs.elements.size());
for (const auto& elem : rhs)
elements.emplace_back(impl::make_node(elem));
}
return *this;
}
TOML_EXTERNAL_LINKAGE
array& array::operator= (array&& rhs) noexcept
{
if (&rhs != this)
{
node::operator=(std::move(rhs));
elements = std::move(rhs.elements);
}
return *this;
}
TOML_EXTERNAL_LINKAGE
void array::preinsertion_resize(size_t idx, size_t count) noexcept
{
@ -35,23 +78,6 @@ TOML_NAMESPACE_START
}
}
TOML_EXTERNAL_LINKAGE
array::array() noexcept = default;
TOML_EXTERNAL_LINKAGE
array::array(array&& other) noexcept
: node{ std::move(other) },
elements{ std::move(other.elements) }
{}
TOML_EXTERNAL_LINKAGE
array& array::operator= (array&& rhs) noexcept
{
node::operator=(std::move(rhs));
elements = std::move(rhs.elements);
return *this;
}
#define TOML_MEMBER_ATTR(attr) TOML_EXTERNAL_LINKAGE TOML_ATTR(attr)
TOML_MEMBER_ATTR(const) node_type array::type() const noexcept { return node_type::array; }

View File

@ -75,7 +75,10 @@ TOML_NAMESPACE_START
protected:
node() noexcept = default;
node(const node&) noexcept = default;
node(node&& other) noexcept;
node& operator= (const node&) noexcept = default;
node& operator= (node&& rhs) noexcept;
template <typename T>
@ -105,10 +108,6 @@ TOML_NAMESPACE_START
template <typename N, typename T>
using ref_cast_type = decltype(std::declval<N>().template ref_cast<T>());
node() noexcept = default;
node(const node&) = delete;
node& operator= (const node&) = delete;
public:
virtual ~node() noexcept = default;

View File

@ -229,6 +229,20 @@ TOML_NAMESPACE_START
TOML_NODISCARD_CTOR
table() noexcept;
/// \brief Copy constructor.
TOML_NODISCARD_CTOR
table(const table&) noexcept;
/// \brief Move constructor.
TOML_NODISCARD_CTOR
table(table&& other) noexcept;
/// \brief Copy-assignment operator.
table& operator= (const table&) noexcept;
/// \brief Move-assignment operator.
table& operator= (table&& rhs) noexcept;
/// \brief Constructs a table with one or more initial key-value pairs.
///
/// \detail \cpp
@ -264,15 +278,6 @@ TOML_NAMESPACE_START
: table{ arr, N }
{}
/// \brief Move constructor.
TOML_NODISCARD_CTOR
table(table&& other) noexcept;
/// \brief Move-assignment operator.
table& operator= (table&& rhs) noexcept;
table(const table&) = delete;
table& operator= (const table&) = delete;
/// \brief Always returns `node_type::table` for table nodes.
[[nodiscard]] node_type type() const noexcept override;

View File

@ -21,19 +21,16 @@ TOML_DISABLE_PADDING_WARNINGS
TOML_NAMESPACE_START
{
TOML_EXTERNAL_LINKAGE
table::table(impl::table_init_pair* pairs, size_t count) noexcept
{
for (size_t i = 0; i < count; i++)
{
map.insert_or_assign(
std::move(pairs[i].key),
std::move(pairs[i].value)
);
}
}
table::table() noexcept {}
TOML_EXTERNAL_LINKAGE
table::table() noexcept {}
table::table(const table& other) noexcept
: node{ std::move(other) },
inline_{ other.inline_ }
{
for (auto&& [k, v] : other)
map.emplace_hint(map.end(), k, impl::make_node(v));
}
TOML_EXTERNAL_LINKAGE
table::table(table&& other) noexcept
@ -43,14 +40,43 @@ TOML_NAMESPACE_START
{}
TOML_EXTERNAL_LINKAGE
table& table::operator = (table&& rhs) noexcept
table& table::operator= (const table& rhs) noexcept
{
node::operator=(std::move(rhs));
map = std::move(rhs.map);
inline_ = rhs.inline_;
if (&rhs != this)
{
node::operator=(rhs);
map.clear();
for (auto&& [k, v] : rhs)
map.emplace_hint(map.end(), k, impl::make_node(v));
inline_ = rhs.inline_;
}
return *this;
}
TOML_EXTERNAL_LINKAGE
table& table::operator= (table&& rhs) noexcept
{
if (&rhs != this)
{
node::operator=(std::move(rhs));
map = std::move(rhs.map);
inline_ = rhs.inline_;
}
return *this;
}
TOML_EXTERNAL_LINKAGE
table::table(impl::table_init_pair* pairs, size_t count) noexcept
{
for (size_t i = 0; i < count; i++)
{
map.insert_or_assign(
std::move(pairs[i].key),
std::move(pairs[i].value)
);
}
}
#define TOML_MEMBER_ATTR(attr) TOML_EXTERNAL_LINKAGE TOML_ATTR(attr)
TOML_MEMBER_ATTR(const) node_type table::type() const noexcept { return node_type::table; }

View File

@ -173,6 +173,13 @@ TOML_NAMESPACE_START
: val_(impl::native_value_maker<value_type, std::decay_t<Args>...>::make(std::forward<Args>(args)...))
{}
/// \brief Copy constructor.
TOML_NODISCARD_CTOR
value(const value& other) noexcept
: node{ other },
val_{ other.val_ }
{}
/// \brief Move constructor.
TOML_NODISCARD_CTOR
value(value&& other) noexcept
@ -180,16 +187,24 @@ TOML_NAMESPACE_START
val_{ std::move(other.val_) }
{}
/// \brief Move-assignment operator.
value& operator= (value&& rhs) noexcept
/// \brief Copy-assignment operator.
value& operator= (const value& rhs) noexcept
{
node::operator=(std::move(rhs));
val_ = std::move(rhs.val_);
node::operator=(rhs);
val_ = rhs.val_;
return *this;
}
value(const value&) = delete;
value& operator= (const value&) = delete;
/// \brief Move-assignment operator.
value& operator= (value&& rhs) noexcept
{
if (&rhs != this)
{
node::operator=(std::move(rhs));
val_ = std::move(rhs.val_);
}
return *this;
}
/// \brief Returns the value's node type identifier.
///

View File

@ -14,12 +14,7 @@ TEST_CASE("arrays - moving")
R"(test = [ "foo" ])"sv,
[&](table&& tbl)
{
CHECK(tbl.source().begin == source_position{ 1, 1 });
CHECK(tbl.source().end == source_position{ 1, 17 });
CHECK(tbl.source().path);
CHECK(*tbl.source().path == filename);
CHECK(tbl.size() == 1_sz);
// sanity-check initial state of a freshly-parsed array
auto arr1 = tbl["test"].as<array>();
REQUIRE(arr1);
CHECK(arr1->size() == 1_sz);
@ -30,12 +25,14 @@ TEST_CASE("arrays - moving")
REQUIRE(arr1->get_as<std::string>(0_sz));
CHECK(*arr1->get_as<std::string>(0_sz) == "foo"sv);
// sanity-check initial state of default-constructed array
array arr2;
CHECK(arr2.source().begin == source_position{});
CHECK(arr2.source().end == source_position{});
CHECK(!arr2.source().path);
CHECK(arr2.size() == 0_sz);
// check the results of move-assignment
arr2 = std::move(*arr1);
CHECK(arr2.source().begin == source_position{ 1, 8 });
CHECK(arr2.source().end == source_position{ 1, 17 });
@ -45,14 +42,84 @@ TEST_CASE("arrays - moving")
REQUIRE(arr2.get_as<std::string>(0_sz));
CHECK(*arr2.get_as<std::string>(0_sz) == "foo"sv);
// check that moved-from array is now the same as default-constructed
CHECK(arr1->source().begin == source_position{});
CHECK(arr1->source().end == source_position{});
CHECK(!arr1->source().path);
CHECK(arr1->size() == 0_sz);
// check the results of move-construction
array arr3{ std::move(arr2) };
CHECK(arr3.source().begin == source_position{ 1, 8 });
CHECK(arr3.source().end == source_position{ 1, 17 });
CHECK(arr3.source().path);
CHECK(*arr3.source().path == filename);
CHECK(arr3.size() == 1_sz);
REQUIRE(arr3.get_as<std::string>(0_sz));
CHECK(*arr3.get_as<std::string>(0_sz) == "foo"sv);
// check that moved-from array is now the same as default-constructed
CHECK(arr2.source().begin == source_position{});
CHECK(arr2.source().end == source_position{});
CHECK(!arr2.source().path);
CHECK(arr2.size() == 0_sz);
},
filename
);
}
TEST_CASE("arrays - copying")
{
static constexpr auto filename = "foo.toml"sv;
parsing_should_succeed(
FILE_LINE_ARGS,
R"(test = [ "foo" ])"sv,
[&](table&& tbl)
{
// sanity-check initial state of a freshly-parsed array
auto arr1 = tbl["test"].as<array>();
REQUIRE(arr1);
CHECK(arr1->size() == 1_sz);
CHECK(arr1->source().begin == source_position{ 1, 8 });
CHECK(arr1->source().end == source_position{ 1, 17 });
CHECK(arr1->source().path);
CHECK(*arr1->source().path == filename);
REQUIRE(arr1->get_as<std::string>(0_sz));
CHECK(*arr1->get_as<std::string>(0_sz) == "foo"sv);
// sanity-check initial state of default-constructed array
array arr2;
CHECK(arr2.source().begin == source_position{});
CHECK(arr2.source().end == source_position{});
CHECK(!arr2.source().path);
CHECK(arr2.size() == 0_sz);
// check the results of copy-assignment
arr2 = *arr1;
CHECK(arr2.source().begin == source_position{ 1, 8 });
CHECK(arr2.source().end == source_position{ 1, 17 });
CHECK(arr2.source().path);
CHECK(*arr2.source().path == filename);
CHECK(arr2.size() == 1_sz);
REQUIRE(arr2.get_as<std::string>(0_sz));
CHECK(*arr2.get_as<std::string>(0_sz) == "foo"sv);
CHECK(arr2 == *arr1);
// check the results of copy-construction
array arr3{ arr2 };
CHECK(arr3.source().begin == source_position{ 1, 8 });
CHECK(arr3.source().end == source_position{ 1, 17 });
CHECK(arr3.source().path);
CHECK(*arr3.source().path == filename);
CHECK(arr3.size() == 1_sz);
REQUIRE(arr3.get_as<std::string>(0_sz));
CHECK(*arr3.get_as<std::string>(0_sz) == "foo"sv);
CHECK(arr3 == *arr1);
CHECK(arr3 == arr2);
},
filename
);
}
TEST_CASE("arrays - construction")

View File

@ -14,19 +14,22 @@ TEST_CASE("tables - moving")
R"(test = { val1 = "foo" })"sv,
[&](table&& tbl)
{
CHECK(tbl.source().begin == source_position{ 1, 1 });
CHECK(tbl.source().end == source_position{ 1, 24 });
CHECK(tbl.source().path);
CHECK(*tbl.source().path == filename);
CHECK(tbl.size() == 1_sz);
// sanity-check initial state of a freshly-parsed table
REQUIRE(tbl["test"].as<table>());
CHECK(tbl["test"].as<table>()->size() == 1_sz);
CHECK(tbl["test"].as<table>()->source().begin == source_position{ 1, 8 });
CHECK(tbl["test"].as<table>()->source().end == source_position{ 1, 24 });
CHECK(tbl["test"]["val1"] == "foo");
table tbl2 = std::move(tbl);
// sanity-check initial state of default-constructed table
table tbl2;
CHECK(tbl2.source().begin == source_position{});
CHECK(tbl2.source().end == source_position{});
CHECK(!tbl2.source().path);
CHECK(tbl2.size() == 0_sz);
// check the results of move-assignment
tbl2 = std::move(tbl);
CHECK(tbl2.source().begin == source_position{ 1, 1 });
CHECK(tbl2.source().end == source_position{ 1, 24 });
CHECK(tbl2.source().path);
@ -36,11 +39,82 @@ TEST_CASE("tables - moving")
CHECK(tbl2["test"].as<table>()->size() == 1_sz);
CHECK(tbl2["test"]["val1"] == "foo"sv);
// check that moved-from table is now the same as default-constructed
CHECK(tbl.source().begin == source_position{});
CHECK(tbl.source().end == source_position{});
CHECK(!tbl.source().path);
CHECK(tbl.size() == 0_sz);
CHECK(!tbl["test"].as<table>());
// check the results of move-construction
table tbl3{ std::move(tbl2) };
CHECK(tbl3.source().begin == source_position{ 1, 1 });
CHECK(tbl3.source().end == source_position{ 1, 24 });
CHECK(tbl3.source().path);
CHECK(*tbl3.source().path == filename);
CHECK(tbl3.size() == 1_sz);
REQUIRE(tbl3["test"].as<table>());
CHECK(tbl3["test"].as<table>()->size() == 1_sz);
CHECK(tbl3["test"]["val1"] == "foo"sv);
// check that moved-from table is now the same as default-constructed
CHECK(tbl2.source().begin == source_position{});
CHECK(tbl2.source().end == source_position{});
CHECK(!tbl2.source().path);
CHECK(tbl2.size() == 0_sz);
CHECK(!tbl2["test"].as<table>());
},
filename
);
}
TEST_CASE("tables - copying")
{
static constexpr auto filename = "foo.toml"sv;
parsing_should_succeed(
FILE_LINE_ARGS,
R"(test = { val1 = "foo" })"sv,
[&](table&& tbl)
{
// sanity-check initial state of a freshly-parsed table
REQUIRE(tbl["test"].as<table>());
CHECK(tbl["test"].as<table>()->size() == 1_sz);
CHECK(tbl["test"].as<table>()->source().begin == source_position{ 1, 8 });
CHECK(tbl["test"].as<table>()->source().end == source_position{ 1, 24 });
CHECK(tbl["test"]["val1"] == "foo");
// sanity-check initial state of default-constructed table
table tbl2;
CHECK(tbl2.source().begin == source_position{});
CHECK(tbl2.source().end == source_position{});
CHECK(!tbl2.source().path);
CHECK(tbl2.size() == 0_sz);
// check the results of copy-assignment
tbl2 = tbl;
CHECK(tbl2.source().begin == source_position{ 1, 1 });
CHECK(tbl2.source().end == source_position{ 1, 24 });
CHECK(tbl2.source().path);
CHECK(*tbl2.source().path == filename);
CHECK(tbl2.size() == 1_sz);
REQUIRE(tbl2["test"].as<table>());
CHECK(tbl2["test"].as<table>()->size() == 1_sz);
CHECK(tbl2["test"]["val1"] == "foo"sv);
CHECK(tbl2 == tbl);
// check the results of copy-construction
table tbl3{ tbl2 };
CHECK(tbl3.source().begin == source_position{ 1, 1 });
CHECK(tbl3.source().end == source_position{ 1, 24 });
CHECK(tbl3.source().path);
CHECK(*tbl3.source().path == filename);
CHECK(tbl3.size() == 1_sz);
REQUIRE(tbl3["test"].as<table>());
CHECK(tbl3["test"].as<table>()->size() == 1_sz);
CHECK(tbl3["test"]["val1"] == "foo"sv);
CHECK(tbl3 == tbl2);
CHECK(tbl3 == tbl);
},
filename
);

View File

@ -75,11 +75,11 @@ TEST_CASE("values - construction")
CHECK_VALUE_INIT2(one<DWORDLONG>, int64_t, 1u);
#if TOML_WINDOWS_COMPAT
CHECK_VALUE_INIT2(L"kek", std::string, "kek"sv);
CHECK_VALUE_INIT2(L"kek"s, std::string, "kek"sv);
CHECK_VALUE_INIT2(L"kek"sv, std::string, "kek"sv);
CHECK_VALUE_INIT2(L"kek"sv.data(), std::string, "kek"sv);
CHECK_VALUE_INIT2(L"kek", std::string, "kek"sv);
CHECK_VALUE_INIT2(L"kek"s, std::string, "kek"sv);
CHECK_VALUE_INIT2(L"kek"sv, std::string, "kek"sv);
CHECK_VALUE_INIT2(L"kek"sv.data(), std::string, "kek"sv);
#endif // TOML_WINDOWS_COMPAT

205
toml.hpp
View File

@ -2087,7 +2087,10 @@ TOML_NAMESPACE_START
protected:
node() noexcept = default;
node(const node&) noexcept = default;
node(node&& other) noexcept;
node& operator= (const node&) noexcept = default;
node& operator= (node&& rhs) noexcept;
template <typename T>
@ -2117,10 +2120,6 @@ TOML_NAMESPACE_START
template <typename N, typename T>
using ref_cast_type = decltype(std::declval<N>().template ref_cast<T>());
node() noexcept = default;
node(const node&) = delete;
node& operator= (const node&) = delete;
public:
virtual ~node() noexcept = default;
@ -2618,21 +2617,34 @@ TOML_NAMESPACE_START
: val_(impl::native_value_maker<value_type, std::decay_t<Args>...>::make(std::forward<Args>(args)...))
{}
TOML_NODISCARD_CTOR
value(const value& other) noexcept
: node{ other },
val_{ other.val_ }
{}
TOML_NODISCARD_CTOR
value(value&& other) noexcept
: node{ std::move(other) },
val_{ std::move(other.val_) }
{}
value& operator= (value&& rhs) noexcept
value& operator= (const value& rhs) noexcept
{
node::operator=(std::move(rhs));
val_ = std::move(rhs.val_);
node::operator=(rhs);
val_ = rhs.val_;
return *this;
}
value(const value&) = delete;
value& operator= (const value&) = delete;
value& operator= (value&& rhs) noexcept
{
if (&rhs != this)
{
node::operator=(std::move(rhs));
val_ = std::move(rhs.val_);
}
return *this;
}
[[nodiscard]] node_type type() const noexcept override { return impl::node_type_of<value_type>; }
[[nodiscard]] bool is_table() const noexcept override { return false; }
@ -3384,16 +3396,13 @@ TOML_IMPL_NAMESPACE_START
template <typename T>
[[nodiscard]]
TOML_ATTR(returns_nonnull)
TOML_ALWAYS_INLINE
auto* make_node(T&& val) noexcept
auto* make_node_specialized(T&& val) noexcept
{
using type = unwrap_node<remove_cvref_t<T>>;
static_assert(!std::is_same_v<type, node>);
if constexpr (is_one_of<type, array, table>)
{
static_assert(
std::is_rvalue_reference_v<decltype(val)>,
"Tables and arrays may only be moved (not copied)."
);
return new type{ std::forward<T>(val) };
}
else
@ -3423,7 +3432,23 @@ TOML_IMPL_NAMESPACE_START
template <typename T>
[[nodiscard]]
TOML_ATTR(returns_nonnull)
TOML_ALWAYS_INLINE
auto* make_node(T&& val) noexcept
{
using type = unwrap_node<remove_cvref_t<T>>;
if constexpr (std::is_same_v<type, node>)
{
return std::forward<T>(val).visit([](auto&& concrete) noexcept
{
return static_cast<toml::node*>(make_node_specialized(std::forward<decltype(concrete)>(concrete)));
});
}
else
return make_node_specialized(std::forward<T>(val));
}
template <typename T>
[[nodiscard]]
TOML_ATTR(returns_nonnull)
auto* make_node(inserter<T>&& val) noexcept
{
return make_node(std::move(val.value));
@ -3459,9 +3484,17 @@ TOML_NAMESPACE_START
array() noexcept;
TOML_NODISCARD_CTOR
array(array&& other) noexcept;
array(const array&) noexcept;
template <typename ElemType, typename... ElemTypes>
TOML_NODISCARD_CTOR
array(array&& other) noexcept;
array& operator= (const array&) noexcept;
array& operator= (array&& rhs) noexcept;
template <typename ElemType, typename... ElemTypes, typename = std::enable_if_t<
(sizeof...(ElemTypes) > 0_sz)
|| !std::is_same_v<impl::remove_cvref_t<ElemType>, array>
>>
TOML_NODISCARD_CTOR
explicit array(ElemType&& val, ElemTypes&&... vals)
{
@ -3476,11 +3509,6 @@ TOML_NAMESPACE_START
}
}
array& operator= (array&& rhs) noexcept;
array(const array&) = delete;
array& operator= (const array&) = delete;
[[nodiscard]] node_type type() const noexcept override;
[[nodiscard]] bool is_table() const noexcept override;
[[nodiscard]] bool is_array() const noexcept override;
@ -3950,19 +3978,20 @@ TOML_NAMESPACE_START
TOML_NODISCARD_CTOR
table() noexcept;
TOML_NODISCARD_CTOR
table(const table&) noexcept;
TOML_NODISCARD_CTOR
table(table&& other) noexcept;
table& operator= (const table&) noexcept;
table& operator= (table&& rhs) noexcept;
template <size_t N>
TOML_NODISCARD_CTOR
explicit table(impl::table_init_pair(&& arr)[N]) noexcept
: table{ arr, N }
{}
TOML_NODISCARD_CTOR
table(table&& other) noexcept;
table& operator= (table&& rhs) noexcept;
table(const table&) = delete;
table& operator= (const table&) = delete;
[[nodiscard]] node_type type() const noexcept override;
[[nodiscard]] bool is_table() const noexcept override;
[[nodiscard]] bool is_array() const noexcept override;
@ -7294,6 +7323,49 @@ TOML_DISABLE_PADDING_WARNINGS
TOML_NAMESPACE_START
{
TOML_EXTERNAL_LINKAGE
array::array() noexcept = default;
TOML_EXTERNAL_LINKAGE
array::array(const array& other) noexcept
: node{ other }
{
elements.reserve(other.elements.size());
for (const auto& elem : other)
elements.emplace_back(impl::make_node(elem));
}
TOML_EXTERNAL_LINKAGE
array::array(array&& other) noexcept
: node{ std::move(other) },
elements{ std::move(other.elements) }
{}
TOML_EXTERNAL_LINKAGE
array& array::operator= (const array& rhs) noexcept
{
if (&rhs != this)
{
node::operator=(rhs);
elements.clear();
elements.reserve(rhs.elements.size());
for (const auto& elem : rhs)
elements.emplace_back(impl::make_node(elem));
}
return *this;
}
TOML_EXTERNAL_LINKAGE
array& array::operator= (array&& rhs) noexcept
{
if (&rhs != this)
{
node::operator=(std::move(rhs));
elements = std::move(rhs.elements);
}
return *this;
}
TOML_EXTERNAL_LINKAGE
void array::preinsertion_resize(size_t idx, size_t count) noexcept
{
@ -7310,23 +7382,6 @@ TOML_NAMESPACE_START
}
}
TOML_EXTERNAL_LINKAGE
array::array() noexcept = default;
TOML_EXTERNAL_LINKAGE
array::array(array&& other) noexcept
: node{ std::move(other) },
elements{ std::move(other.elements) }
{}
TOML_EXTERNAL_LINKAGE
array& array::operator= (array&& rhs) noexcept
{
node::operator=(std::move(rhs));
elements = std::move(rhs.elements);
return *this;
}
#define TOML_MEMBER_ATTR(attr) TOML_EXTERNAL_LINKAGE TOML_ATTR(attr)
TOML_MEMBER_ATTR(const) node_type array::type() const noexcept { return node_type::array; }
@ -7550,19 +7605,16 @@ TOML_DISABLE_PADDING_WARNINGS
TOML_NAMESPACE_START
{
TOML_EXTERNAL_LINKAGE
table::table(impl::table_init_pair* pairs, size_t count) noexcept
{
for (size_t i = 0; i < count; i++)
{
map.insert_or_assign(
std::move(pairs[i].key),
std::move(pairs[i].value)
);
}
}
table::table() noexcept {}
TOML_EXTERNAL_LINKAGE
table::table() noexcept {}
table::table(const table& other) noexcept
: node{ std::move(other) },
inline_{ other.inline_ }
{
for (auto&& [k, v] : other)
map.emplace_hint(map.end(), k, impl::make_node(v));
}
TOML_EXTERNAL_LINKAGE
table::table(table&& other) noexcept
@ -7572,14 +7624,43 @@ TOML_NAMESPACE_START
{}
TOML_EXTERNAL_LINKAGE
table& table::operator = (table&& rhs) noexcept
table& table::operator= (const table& rhs) noexcept
{
node::operator=(std::move(rhs));
map = std::move(rhs.map);
inline_ = rhs.inline_;
if (&rhs != this)
{
node::operator=(rhs);
map.clear();
for (auto&& [k, v] : rhs)
map.emplace_hint(map.end(), k, impl::make_node(v));
inline_ = rhs.inline_;
}
return *this;
}
TOML_EXTERNAL_LINKAGE
table& table::operator= (table&& rhs) noexcept
{
if (&rhs != this)
{
node::operator=(std::move(rhs));
map = std::move(rhs.map);
inline_ = rhs.inline_;
}
return *this;
}
TOML_EXTERNAL_LINKAGE
table::table(impl::table_init_pair* pairs, size_t count) noexcept
{
for (size_t i = 0; i < count; i++)
{
map.insert_or_assign(
std::move(pairs[i].key),
std::move(pairs[i].value)
);
}
}
#define TOML_MEMBER_ATTR(attr) TOML_EXTERNAL_LINKAGE TOML_ATTR(attr)
TOML_MEMBER_ATTR(const) node_type table::type() const noexcept { return node_type::table; }

View File

@ -95,12 +95,12 @@
</Type>
<Type Name="toml::v2::table">
<DisplayString>{values}</DisplayString>
<DisplayString>{map}</DisplayString>
<Expand>
<!-- Modified from std::map visualizer in VS 2019 stl.natvis -->
<TreeItems>
<Size>values._Mypair._Myval2._Myval2._Mysize</Size>
<HeadPointer>values._Mypair._Myval2._Myval2._Myhead-&gt;_Parent</HeadPointer>
<Size>map._Mypair._Myval2._Myval2._Mysize</Size>
<HeadPointer>map._Mypair._Myval2._Myval2._Myhead-&gt;_Parent</HeadPointer>
<LeftPointer>_Left</LeftPointer>
<RightPointer>_Right</RightPointer>
<ValueNode Condition="_Isnil == 0" Name="[{_Myval.first,s8}]">*_Myval.second</ValueNode>
@ -109,12 +109,12 @@
</Type>
<Type Name="toml::v2::array">
<DisplayString>{values}</DisplayString>
<DisplayString>{elements}</DisplayString>
<Expand>
<!-- Modified from std::vector visualizer in VS 2019 stl.natvis -->
<IndexListItems>
<Size>values._Mypair._Myval2._Mylast - values._Mypair._Myval2._Myfirst</Size>
<ValueNode>*values._Mypair._Myval2._Myfirst[$i]</ValueNode>
<Size>elements._Mypair._Myval2._Mylast - elements._Mypair._Myval2._Myfirst</Size>
<ValueNode>*elements._Mypair._Myval2._Myfirst[$i]</ValueNode>
</IndexListItems>
</Expand>
</Type>