From 6c2bc090bff91da5fc26d1485cdd3527927f2e10 Mon Sep 17 00:00:00 2001 From: dekken Date: Wed, 14 Oct 2020 13:45:58 +0200 Subject: [PATCH] pure const dict access method --- include/dict.hpp | 34 +++++++++++++++++++------ test/basic_dict_ops.cpp | 56 +++++++++++++++++++++++++---------------- 2 files changed, 61 insertions(+), 29 deletions(-) diff --git a/include/dict.hpp b/include/dict.hpp index 809f953..a15c2a1 100644 --- a/include/dict.hpp +++ b/include/dict.hpp @@ -17,13 +17,14 @@ namespace cppdict { -namespace { +namespace +{ template constexpr bool is_any_of() { return std::disjunction_v...>; } -} +} // namespace namespace // Visitor details { @@ -103,8 +104,9 @@ struct Dict using data_t = std::variant; template - struct is_value : std::conditional and !std::is_same_v, - std::true_type, std::false_type>::type + struct is_value + : std::conditional and !std::is_same_v, + std::true_type, std::false_type>::type { }; template @@ -131,6 +133,7 @@ struct Dict return *this; } Dict& operator=(Dict&& other) = default; + Dict& operator[](const std::string& key) { #ifndef NDEBUG @@ -161,6 +164,24 @@ struct Dict } + Dict& operator[](const std::string& key) const + { + if (isNode()) + { + auto& map = std::get(data); + + if (std::end(map) == map.find(key)) + { + throw std::runtime_error("cppdict: invalid key: " + key); + } + + return *std::get(data).at(key); + } + + throw std::runtime_error("cppdict: invalid key: " + key); + } + + bool isLeaf() const noexcept { return !isNode() && !isEmpty(); } bool isNode() const noexcept { return std::holds_alternative(data); } @@ -206,10 +227,7 @@ struct Dict throw std::runtime_error("cppdict: not a map or not default"); } - bool contains(std::string key) - { - return isNode() and std::get(data).count(key); - } + bool contains(std::string key) { return isNode() and std::get(data).count(key); } std::size_t size() const noexcept { diff --git a/test/basic_dict_ops.cpp b/test/basic_dict_ops.cpp index 71d43b4..f26f133 100644 --- a/test/basic_dict_ops.cpp +++ b/test/basic_dict_ops.cpp @@ -12,16 +12,16 @@ TEST_CASE("Can (depp)copy nodes with operator=", "[simple cppdict::Dict()==3.14); + dict["destination"] = dict["this"]; + REQUIRE(dict["destination"]["is"]["the"]["source"].to() == 3.14); } TEST_CASE("Can add values and retrieve them", "[simple cppdict::Dict]") { Dict dict; - dict["first"] = 3.14; + dict["first"] = 3.14; dict["second"] = 1; - dict["third"] = std::string{"hello"}; + dict["third"] = std::string{"hello"}; SECTION("Added values should be retrievable") { REQUIRE(dict["first"].to() == 3.14); @@ -40,43 +40,43 @@ TEST_CASE("Can add values and retrieve them", "[simple cppdict::Dict]") +TEST_CASE("Deals with both references and values", + "[simple cppdict::Dict]") { Dict dict; - dict["0"]["1"] = 3.5; - dict["0"]["2"]["1"] = 55.; - dict["0"]["2"]["2"] = 56.; + dict["0"]["1"] = 3.5; + dict["0"]["2"]["1"] = 55.; + dict["0"]["2"]["2"] = 56.; dict["0"]["2"]["3"]["1"]["1"] = 666.; SECTION("Values acces by value does a copy") { auto v = dict["0"]["1"].to(); - v = 10.; - REQUIRE(v!=dict["0"]["1"].to()); + v = 10.; + REQUIRE(v != dict["0"]["1"].to()); } SECTION("Values access by ref doesn't copy") { - auto &v = dict["0"]["1"].to(); - v = 10.; - REQUIRE(v==dict["0"]["1"].to()); + auto& v = dict["0"]["1"].to(); + v = 10.; + REQUIRE(v == dict["0"]["1"].to()); } SECTION("Nodes access by value does copy") { auto node = dict["0"]; node["1"] = 100; - REQUIRE(dict["0"]["1"].to()==3.5); - node = dict["2"]; + REQUIRE(dict["0"]["1"].to() == 3.5); + node = dict["2"]; node["3"]["1"]["1"] = 42; - REQUIRE(dict["0"]["2"]["3"]["1"]["1"].to()==666.); + REQUIRE(dict["0"]["2"]["3"]["1"]["1"].to() == 666.); } SECTION("Nodes access by ref doesn't copy") { - auto &node = dict["0"]; - node["1"] = 100; + auto& node = dict["0"]; + node["1"] = 100; node["2"]["3"]["1"]["1"] = 42; - REQUIRE(dict["0"]["1"].to()==100); - REQUIRE(dict["0"]["2"]["3"]["1"]["1"].to()==42); + REQUIRE(dict["0"]["1"].to() == 100); + REQUIRE(dict["0"]["2"]["3"]["1"]["1"].to() == 42); } - } @@ -90,3 +90,17 @@ TEST_CASE("Contains expects true or false", "[simple cppdict::Dict]") +{ + Dict dict; + dict["first"] = 3.14; + dict["second"]["third"] = 3; + + auto const& dictRef = dict; + + REQUIRE(dictRef["first"].to() == 3.14); + REQUIRE_THROWS_WITH(dictRef["second"].to(), "cppdict: to invalid type"); + REQUIRE_THROWS_WITH(dictRef["one"]["two"].to(), "cppdict: invalid key: one"); +}