# ### Weak Pointers and Circular References in C++ 11: Listing 4

A generic solution to circular references.

```// circular_ptr.h
#ifndef CIRCULAR_PTR_H_
#define CIRCULAR_PTR_H_

#include <memory>

using namespace std;

template <typename T>
class circular_ptr;

// this header only offers the prototype of this template function.
// Implementors of a concrete types T should provide specific versions, and make this
// function friend to T (see class person in Listing 5).
template <typename T>
circular_ptr<T> *get_circular_ptr(const shared_ptr<T>&);

template <typename T>
class circular_ptr {
public:
circular_ptr() : strong_{nullptr}, weak_{} {}

// copy constructor
circular_ptr(shared_ptr<T> &t) : strong_{nullptr}, weak_{} {
set(t);
}

// copy assignment operator
circular_ptr& operator=(shared_ptr<T> &t) {
return set(t);
}

shared_ptr<T> get() const {
if (strong_!=nullptr)
return strong_;
else
return weak_.lock();
}

// whether circular_ptr uses a weak link to refer to a T instance.
bool is_weak() {
return !(weak_.expired());
}

// releases its link, whichever it is (strong or weak).
bool reset() {
// looks for a weak link that directly or not points to the this circular_ptr

// if found, means that there was a circular reference. That circular reference is
// being broken in this reset. Consequently, the weak ptr must become strong.
if (weak_one) {
weak_one->strong_ = weak_one->weak_.lock();
weak_one->weak_.reset();
}

strong_.reset();
weak_.reset();

return (weak_one);
}

bool operator==(const circular_ptr &other) const {
return get()==other.get();
}

bool operator!=(const circular_ptr &other) const {
return !(*this==other);
}
protected:
// this function is O(n) in non-deterministic cases. A deterministic circularity
// scenario may override this function to get constant order of complexity.
virtual bool is_this_reachable_from(const shared_ptr<T> &start) const {
shared_ptr<T> current = start, currents_next;

// it basically performs a walkthrough from start argument to see whether it reaches
// this instance or null. If the former, returns true. False otherwise.
if (current!=nullptr) {
do {
currents_next = get_circular_ptr(current)->get();
if ((currents_next!=nullptr)&&(this==get_circular_ptr(currents_next))) {
return true;
}

current = currents_next;
}
while ((current!=nullptr)&&(current!=start));
}

return false;
}

// same comment: if circularity is deterministic, this function could be overridden and
// thus optimized
circular_ptr *current = this, *weak_one = nullptr;
// provided that there's no strong circular reference, either the chain ends in nullptr
// or we reach a member that is weak
while (current!=nullptr) {
if (current->is_weak()) {
weak_one = current;
// now, it must be confirmed that *this is reachable from weak_one.
do {
if ((current = get_circular_ptr(current->get()))==this)
return weak_one;
}
while (current!=weak_one);
// provided that weak_one is reachable from current, as weak_one is weak
// because participates in a loop.
break;
}

if (shared_ptr<T> t = current->get()) current = get_circular_ptr(t);
else break;
}

return nullptr;
}
private:
shared_ptr<T> strong_;
weak_ptr<T> weak_;

circular_ptr& set(shared_ptr<T> &t) {
if (t==nullptr) {
reset();
}
else {

if (get()!=nullptr) {
}

// checking for cycle_already_detected helps avoid an extra round
weak_ = t;
else
strong_ = t;
}

return *this;
}
};

#endif /* CIRCULAR_PTR_H_ */
```

Diego Dagum is a software architect and developer with more than 20 years of experience. He can be reached at [email protected]
{"ft_lang_label":"__label__en","ft_lang_prob":0.5824362,"math_prob":0.88895243,"size":3760,"snap":"2020-34-2020-40","text_gpt3_token_len":906,"char_repetition_ratio":0.17066027,"word_repetition_ratio":0.003944773,"special_character_ratio":0.2795213,"punctuation_ratio":0.16234888,"nsfw_num_words":0,"has_unicode_error":false,"math_prob_llama3":0.98328406,"pos_list":[0,1,2,3,4,5,6],"im_url_duplicate_count":[null,null,null,4,null,4,null],"WARC_HEADER":"{\"WARC-Type\":\"response\",\"WARC-Date\":\"2020-09-27T14:13:12Z\",\"WARC-Record-ID\":\"<urn:uuid:398e2b79-1c95-4f42-aab4-21c46f1a74bf>\",\"Content-Length\":\"136532\",\"Content-Type\":\"application/http; msgtype=response\",\"WARC-Warcinfo-ID\":\"<urn:uuid:bdc6fc03-4d99-4f47-b895-5eba4824ce0b>\",\"WARC-Concurrent-To\":\"<urn:uuid:4f29d24e-f6ef-45d7-84b5-649ce75067e8>\",\"WARC-IP-Address\":\"104.26.7.55\",\"WARC-Target-URI\":\"https://visualstudiomagazine.com/articles/2012/10/19/circular-references/listing4.aspx\",\"WARC-Payload-Digest\":\"sha1:33J3E6NJLINGSAP6BCSNTTJZYO4OLTA4\",\"WARC-Block-Digest\":\"sha1:UCPU5LBIU44DILP75WC3BJDLKYW37ZD7\",\"WARC-Identified-Payload-Type\":\"text/html\",\"warc_filename\":\"/cc_download/warc_2020/CC-MAIN-2020-40/CC-MAIN-2020-40_segments_1600400279782.77_warc_CC-MAIN-20200927121105-20200927151105-00488.warc.gz\"}"}