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

People and their best friends: a non-deterministic circular reference example.

// person.h
#ifndef PERSON_H_
#define PERSON_H_

#include <string>
#include <memory>
#include "circular_ptr.h"

using namespace std;

class person {
  friend circular_ptr<person> *get_circular_ptr(const shared_ptr<person>&);
public:
  person()=delete;
  person(const string);
  ~person();

  string get_name() const;
  void set_best_friend(shared_ptr<person>);
  shared_ptr<person> get_best_friend() const;
  void set_no_best_friend();
private:
  class best_friend_ptr : public circular_ptr<person> {
  public:
    best_friend_ptr();
    best_friend_ptr(shared_ptr<person>&);
    best_friend_ptr& operator=(shared_ptr<person>&);
  };

  string name_;
  best_friend_ptr best_friend_;
};

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

using namespace std;

person::person(const string name) : name_ {name}, best_friend_ {} {
  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_;
}

void person::set_best_friend(shared_ptr<person> best_friend) {
  if (this==best_friend.get())
    throw invalid_argument("Best friend can't be self person");
  best_friend_ = best_friend;
}

shared_ptr<person> person::get_best_friend() const {
  return best_friend_.get();
}

void person::set_no_best_friend() {
  best_friend_.reset();
}

person::best_friend_ptr::best_friend_ptr() : circular_ptr::circular_ptr() {}
person::best_friend_ptr::best_friend_ptr(shared_ptr<person> &p) : circular_ptr::circular_ptr(p) {}

person::best_friend_ptr& person::best_friend_ptr::operator=(shared_ptr<person> &t) {
  return static_cast<person::best_friend_ptr&>(circular_ptr::operator=(t));
}

circular_ptr<person> *get_circular_ptr(const shared_ptr<person> &p) {
  return &(p->best_friend_);
}
/* ---------------------------------- */
// main.cpp
#include <iostream>
#include <string>
#include <memory>
#include <vector>
#include "person.h"

using namespace std;

void print_friendship(vector<shared_ptr<person>> vp) {
for (auto p : vp) {
      auto q = p->get_best_friend();
      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");

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

  john->set_best_friend(charles);  // strong
  charles->set_best_friend(emma);  // strong
  emma->set_best_friend(cindy);    // strong
  cindy->set_best_friend(arthur);  // strong
  arthur->set_best_friend(laurie); // strong
  laurie->set_best_friend(john);   // weak! See Figure 3
  print_friendship(vp);

  cindy->set_best_friend(charles); // weak, but also laurie’s ptr to john
                                   // becomes strong (see Figure 4)
  print_friendship(vp);

  john->set_best_friend(cindy);    // strong
  emma->set_best_friend(arthur);   // weak, but also cindy’s ptr to charles
                                   // becomes strong (see Figure 5)
  print_friendship(vp);

  charles->set_no_best_friend();   // emma’s ptr to arthur becomes strong
  print_friendship(vp);            // See Figure 6
}

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@diegodagum.com.

comments powered by Disqus

Featured

  • What's New in Visual Studio 2019 v16.5 Preview 2

    The second preview of Visual Studio 2019 v16.5 has arrived with improvements across the flagship IDE, including the core experience and different development areas such as C++, Python, web, mobile and so on.

  • C# Shows Strong in Tech Skills Reports

    Microsoft's C# programming language continues to show strong in tech industry skills reports, with the most recent examples coming from a skills testing company and a training company.

  • Color Shards

    Sharing Data and Splitting Components in Blazor

    ASP.NET Core Version 3.1 has at least two major changes that you'll want to take advantage of. Well, Peter thinks you will. Depending on your background, your response to one of them may be a resounding “meh.”

  • Architecture Small Graphic

    Microsoft Ships Preview SDK, Guidance for New Dual-Screen Mobile Era

    Microsoft announced a new SDK and developer guidance for dealing with the new dual-screen mobile era, ushered in by the advent of ultra-portable devices such as the Surface Duo.

  • How to Create a Machine Learning Decision Tree Classifier Using C#

    After earlier explaining how to compute disorder and split data in his exploration of machine learning decision tree classifiers, resident data scientist Dr. James McCaffrey of Microsoft Research now shows how to use the splitting and disorder code to create a working decision tree classifier.

.NET Insight

Sign up for our newsletter.

Terms and Privacy Policy consent

I agree to this site's Privacy Policy.

Upcoming Events