Exercise: Bag Of Items, By Shared Reference

Step 1: Transform into std::shared_ptr

Continuing from Exercise: Bag Of Items, By Unique Reference, create a similar class BagShared that contains pointers of type std::shared_ptr<Item> such that the tests below pass.

#include "bag-shared.h"

#include <gtest/gtest.h>

TEST(bag_shared_suite, find_by_int_ok)
{
    BagShared bag;
    bag.insert(std::make_shared<BagShared::Item>("something", 42));

    auto item2 = std::make_shared<BagShared::Item>("anything", 666);
    bag.insert(item2);

    ASSERT_EQ(item2.use_count(), 2);

    auto item = bag.find_by_int(42);
    ASSERT_NE(item, nullptr);
    ASSERT_EQ(item->first, "something");
    ASSERT_EQ(item->second, 42);
}

TEST(bag_shared_suite, find_by_int_nok)
{
    BagShared bag;
    bag.insert(std::make_shared<BagShared::Item>("something", 42));
    bag.insert(std::make_shared<BagShared::Item>("anything", 666));

    auto item = bag.find_by_int(7);
    ASSERT_EQ(item, nullptr);
}

TEST(bag_shared_suite, remove_by_int_ok)
{
    BagShared bag;
    bag.insert(std::make_shared<BagShared::Item>("something", 42));
    bag.insert(std::make_shared<BagShared::Item>("anything", 666));

    std::size_t nremoved = bag.remove_by_int(42);
    ASSERT_EQ(nremoved, 1);
}

Did the remove_by_int() method have to be modified?

Step 2: Accidental Move-Insert?

To make sure you did not accidentally leave the move-version of insert() from Exercise: Bag Of Items, By Unique Reference in place, make sure that the following test passes:

#include "bag-shared.h"

#include <gtest/gtest.h>

TEST(bag_shared_suite, insert_const_ref)
{
    auto p = std::make_shared<BagShared::Item>("something", 42);

    BagShared bag;
    bag.insert(p);

    p->second = 43;
    auto found = bag.find_by_int(43);
    ASSERT_NE(found, nullptr);
}

Step 3: Move-Insert, And std::weak_ptr

Implement a move version of insert() that returns a std::weak_ptr to the inserted object, such that the following test passes,

#include "bag-shared.h"

#include <gtest/gtest.h>

TEST(bag_shared_suite, insert_move)
{
    auto p = std::make_shared<BagShared::Item>("something", 42);

    BagShared bag;
    auto weakref = bag.insert(std::move(p));
    ASSERT_EQ(p, nullptr);

    {
        auto found = bag.find_by_int(42);
        ASSERT_EQ(found->first, "something");
        ASSERT_EQ(found->second, 42);
    }

    {
        auto sharedref = weakref.lock();
        ASSERT_NE(sharedref, nullptr);

        ASSERT_EQ(sharedref->first, "something");
        ASSERT_EQ(sharedref->second, 42);
    }

    // remove item again, and see how weak_ptr behaves
    {
        bag.remove_by_int(42);
        auto sharedref = weakref.lock();
        ASSERT_EQ(sharedref, nullptr);
    }
}