Merge #16889: Add some general std::vector utility functions

7d8d3e6a2a Add tests for util/vector.h's Cat and Vector (Pieter Wuille)
e65e61c812 Add some general std::vector utility functions (Pieter Wuille)

Pull request description:

  This is another general improvement extracted from #16800 .

  Two functions are added are:

  * Vector(arg1,arg2,arg3,...) constructs a vector with the specified arguments as elements. The vector's type is derived from the arguments. If some of the arguments are rvalue references, they will be moved into place rather than copied (which can't be achieved using list initialization).
  * Cat(vector1,vector2) returns a concatenation of the two vectors, efficiently moving elements when relevant.

  Vector generalizes (and replaces) the `Singleton` function in src/descriptor.cpp, and `Cat` replaces the function in bech32.cpp

ACKs for top commit:
  laanwj:
    ACK 7d8d3e6a2a
  MarcoFalke:
    ACK 7d8d3e6a2a (enjoyed reading the tests, but did not compile)

Tree-SHA512: 92325f14e90d7e7d9d920421979aec22bb0d730e0291362b4326cccc76f9c2d865bec33a797c5c0201773468c3773cb50ce52c8eee4c1ec1a4d10db5cf2b9d2a
This commit is contained in:
MarcoFalke
2019-10-18 09:56:43 -04:00
7 changed files with 179 additions and 32 deletions

View File

@@ -13,6 +13,7 @@
#include <util/string.h>
#include <util/time.h>
#include <util/spanparsing.h>
#include <util/vector.h>
#include <stdint.h>
#include <thread>
@@ -1714,4 +1715,109 @@ BOOST_AUTO_TEST_CASE(test_LogEscapeMessage)
BOOST_CHECK_EQUAL(BCLog::LogEscapeMessage(NUL), R"(O\x00O)");
}
namespace {
struct Tracker
{
//! Points to the original object (possibly itself) we moved/copied from
const Tracker* origin;
//! How many copies where involved between the original object and this one (moves are not counted)
int copies;
Tracker() noexcept : origin(this), copies(0) {}
Tracker(const Tracker& t) noexcept : origin(t.origin), copies(t.copies + 1) {}
Tracker(Tracker&& t) noexcept : origin(t.origin), copies(t.copies) {}
Tracker& operator=(const Tracker& t) noexcept
{
origin = t.origin;
copies = t.copies + 1;
return *this;
}
Tracker& operator=(Tracker&& t) noexcept
{
origin = t.origin;
copies = t.copies;
return *this;
}
};
}
BOOST_AUTO_TEST_CASE(test_tracked_vector)
{
Tracker t1;
Tracker t2;
Tracker t3;
BOOST_CHECK(t1.origin == &t1);
BOOST_CHECK(t2.origin == &t2);
BOOST_CHECK(t3.origin == &t3);
auto v1 = Vector(t1);
BOOST_CHECK_EQUAL(v1.size(), 1);
BOOST_CHECK(v1[0].origin == &t1);
BOOST_CHECK_EQUAL(v1[0].copies, 1);
auto v2 = Vector(std::move(t2));
BOOST_CHECK_EQUAL(v2.size(), 1);
BOOST_CHECK(v2[0].origin == &t2);
BOOST_CHECK_EQUAL(v2[0].copies, 0);
auto v3 = Vector(t1, std::move(t2));
BOOST_CHECK_EQUAL(v3.size(), 2);
BOOST_CHECK(v3[0].origin == &t1);
BOOST_CHECK(v3[1].origin == &t2);
BOOST_CHECK_EQUAL(v3[0].copies, 1);
BOOST_CHECK_EQUAL(v3[1].copies, 0);
auto v4 = Vector(std::move(v3[0]), v3[1], std::move(t3));
BOOST_CHECK_EQUAL(v4.size(), 3);
BOOST_CHECK(v4[0].origin == &t1);
BOOST_CHECK(v4[1].origin == &t2);
BOOST_CHECK(v4[2].origin == &t3);
BOOST_CHECK_EQUAL(v4[0].copies, 1);
BOOST_CHECK_EQUAL(v4[1].copies, 1);
BOOST_CHECK_EQUAL(v4[2].copies, 0);
auto v5 = Cat(v1, v4);
BOOST_CHECK_EQUAL(v5.size(), 4);
BOOST_CHECK(v5[0].origin == &t1);
BOOST_CHECK(v5[1].origin == &t1);
BOOST_CHECK(v5[2].origin == &t2);
BOOST_CHECK(v5[3].origin == &t3);
BOOST_CHECK_EQUAL(v5[0].copies, 2);
BOOST_CHECK_EQUAL(v5[1].copies, 2);
BOOST_CHECK_EQUAL(v5[2].copies, 2);
BOOST_CHECK_EQUAL(v5[3].copies, 1);
auto v6 = Cat(std::move(v1), v3);
BOOST_CHECK_EQUAL(v6.size(), 3);
BOOST_CHECK(v6[0].origin == &t1);
BOOST_CHECK(v6[1].origin == &t1);
BOOST_CHECK(v6[2].origin == &t2);
BOOST_CHECK_EQUAL(v6[0].copies, 1);
BOOST_CHECK_EQUAL(v6[1].copies, 2);
BOOST_CHECK_EQUAL(v6[2].copies, 1);
auto v7 = Cat(v2, std::move(v4));
BOOST_CHECK_EQUAL(v7.size(), 4);
BOOST_CHECK(v7[0].origin == &t2);
BOOST_CHECK(v7[1].origin == &t1);
BOOST_CHECK(v7[2].origin == &t2);
BOOST_CHECK(v7[3].origin == &t3);
BOOST_CHECK_EQUAL(v7[0].copies, 1);
BOOST_CHECK_EQUAL(v7[1].copies, 1);
BOOST_CHECK_EQUAL(v7[2].copies, 1);
BOOST_CHECK_EQUAL(v7[3].copies, 0);
auto v8 = Cat(std::move(v2), std::move(v3));
BOOST_CHECK_EQUAL(v8.size(), 3);
BOOST_CHECK(v8[0].origin == &t2);
BOOST_CHECK(v8[1].origin == &t1);
BOOST_CHECK(v8[2].origin == &t2);
BOOST_CHECK_EQUAL(v8[0].copies, 0);
BOOST_CHECK_EQUAL(v8[1].copies, 1);
BOOST_CHECK_EQUAL(v8[2].copies, 0);
}
BOOST_AUTO_TEST_SUITE_END()