Weak Pointers and Circular References in C++ 11: Listing 6

Restricting circular references to a conceptual level.

#ifndef PERSON_H_
#define PERSON_H_

#include <string>
#include <memory>
#include <map>

using namespace std;

class person;

// this class models a table of friendship (name, best friend)
class friendship {
public:
  void set_best_friend(shared_ptr<person>, const shared_ptr<person>);
  shared_ptr<person> get_best_friend(const shared_ptr<person>) const;
  void set_no_best_friend(shared_ptr<person>);
private:
  // hashtable
  map<string, shared_ptr<person>> container_;
};

class person {
public:
  person()=delete;
  person(const string);
  ~person();

  string get_name() const;
private:
  string name_;
};

#endif /* PERSON_H_ */
/* ---------------------------------- */
// person.cpp
#include "person.h"
#include <iostream>
#include <stdexcept>

using namespace std;

void friendship::set_best_friend(shared_ptr<person> p, const shared_ptr<person> best_friend) {
  if (p.get()==best_friend.get())
    throw invalid_argument("Best friend can't be self person");

  auto name = p->get_name();
  container_.erase(name);
  if (best_friend)
    container_[name] = best_friend;
}

shared_ptr<person> friendship::get_best_friend(const shared_ptr<person> p) const {
  auto i = container_.find(p->get_name());
  if (i==end(container_))
    return nullptr;
  else
    return i->second;
}

void friendship::set_no_best_friend(shared_ptr<person> p) {
  set_best_friend(p, nullptr);
}

person::person(const string name) : name_ {name} {
  if (name_=="") throw invalid_argument("A person must have a non-empty name");
  cout << name_ << " instance created." << endl;
}

person::~person() {
  cout << name_ << " instance to be disposed." << endl;
}

string person::get_name() const {
  return name_;
}
/* ---------------------------------- */
// main.cpp
#include <iostream>
#include <string>
#include <memory>
#include <vector>
#include "person.h"

using namespace std;

void print_friendship(const vector<shared_ptr<person>> &vp, const friendship& f) {
for (auto p : vp) {
      auto q = f.get_best_friend(p);
      cout << p->get_name() << "'s best friend is " << (q ? q->get_name() : "nobody") << endl;
    }
}

void make_friends() {
  shared_ptr<person> john = make_shared<person>("John"),
                     charles = make_shared<person>("Charles"),
                     emma = make_shared<person>("Emma"),
                     cindy = make_shared<person>("Cindy"),
                     arthur = make_shared<person>("Arthur"),
                     laurie = make_shared<person>("Laurie");

  friendship f;
  vector<shared_ptr<person>> vp = {john, charles, emma, cindy, arthur, laurie};

  // now friendship is kept outside person instances, to eliminate all chance of circular
  // references
  f.set_best_friend(john, charles);
  f.set_best_friend(charles, emma);
  f.set_best_friend(emma, cindy);
  f.set_best_friend(cindy, arthur);
  f.set_best_friend(arthur, laurie);
  f.set_best_friend(laurie, john);
  print_friendship(vp, f);

  f.set_best_friend(cindy, charles);
  print_friendship(vp, f);

  f.set_best_friend(john, cindy);
  f.set_best_friend(emma, arthur);
  print_friendship(vp, f);

  f.set_no_best_friend(charles);
  print_friendship(vp, f);
}

int main() {
  make_friends();

  return 0;
}

About the Author

Diego Dagum is a software architect and developer with more than 20 years of experience. He can be reached at [email protected]

comments powered by Disqus

Featured

  • Death of the Dev Machine?

    Here's a takeaway from this week's Ignite 2020 event: An advanced Azure cloud portends the death of the traditional, high-powered dev machine packed with computing, memory and storage components.

  • COVID-19 Is Ignite 2020's Elephant in the Room: 'Frankly, It Sucks'

    As in all things of our new reality, there was no escaping the drastic changes in routine caused by the COVID-19 pandemic during Microsoft's big Ignite 2020 developer/IT pro conference, this week shifted to an online-only event after drawing tens of thousands of in-person attendees in years past.

  • Visual Studio 2019 v16.8 Preview Update Adds Codespaces

    To coincide with the Microsoft Ignite 2020 IT pro/developer event, the Visual Studio dev team shipped a new update, Visual Studio 2019 v16.8 Preview 3.1, with the main attraction being support for cloud-hosted Codespaces, now in a limited beta.

  • Speed Lines Graphic

    New for Blazor: Azure Static Web Apps Support

    With Blazor taking the .NET web development world by storm, one of the first announcements during Microsoft's Ignite 2020 developer/IT event was its new support in Azure Static Web Apps.

  • Entity Framework Core 5 RC1 Is Feature Complete, Ready for Production

    The first release candidate for Entity Framework 5 -- Microsoft's object-database mapper for .NET -- has shipped with a go live license, ready for production.

Upcoming Events