Created
November 4, 2013 13:53
-
-
Save aldrin/7302769 to your computer and use it in GitHub Desktop.
Code for http://aldrin.co/esft.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Copyright (C) 2013, Aldrin D'Souza. | |
// License: http://opensource.org/licenses/BSD-2-Clause | |
#include <memory> | |
#include <vector> | |
#include <cassert> | |
using namespace std; | |
// forward declaration | |
struct student; | |
// models a course being offered | |
struct course | |
{ | |
// enroll a student for this course | |
void enroll(const shared_ptr<student>& s){ enrolled_.push_back(s); } | |
private: | |
// the list of enrolled students. | |
vector<shared_ptr<student >> enrolled_; | |
}; | |
// models a student | |
struct student | |
{ | |
// offer a course and the student enrolls if interested | |
void offer(course& c) { if(interested_in(c)) { c.enroll(shared_from_this()); } } | |
// how do we implement this? | |
virtual shared_ptr<student> shared_from_this() = 0; | |
private: | |
// internal implementation of what interests a student | |
bool interested_in(course& c) { return true; } | |
}; | |
void test_wp_expected_usage() | |
{ | |
shared_ptr<int> p(new int); // a shared pointer | |
weak_ptr<int> w(p); // make a weak reference | |
{ | |
assert(1 == p.use_count()); // only 1 owner: p | |
shared_ptr<int> q = w.lock(); // encash the weak ref | |
assert(2 == q.use_count()); // 2 owners now: p, q | |
} // q goes out of scope | |
assert(1 == w.use_count()); // we're back to one owner | |
p.reset(); // explicitly reset p. | |
assert(w.expired()); // w knows it is dangling now. | |
} | |
void test_sp_expected_usage() | |
{ | |
int *i = new int; // the raw pointer | |
shared_ptr<int> p(i); // wrap it up | |
assert(p.unique()); // p is the sole owner | |
{ | |
shared_ptr<int> q(p); // share owner ship | |
assert(2==q.use_count()); // 2 onwers for the pointer | |
assert(!(q.unique() || p.unique())); // both p & q know they're not unique. | |
assert(p.use_count()==q.use_count()); // use counts agree | |
} | |
assert(1==p.use_count()); // q out of scope | |
assert(p.unique()); // p is the sole owner again. | |
} | |
void test_sp_bad_usage() | |
{ | |
int *i = new int; // the raw pointer | |
shared_ptr<int> p(i); // wrap it up | |
shared_ptr<int> q(i); // wrap it again (bad) | |
} // <- invalid delete (double delete) | |
void test_sp_bad_usage2() | |
{ | |
int i; // on the stack | |
shared_ptr<int> p(&i); // wrap it up | |
} // <- invalid delete (bad free) | |
struct obviously_bad_student: public student | |
{ | |
shared_ptr<student> shared_from_this(){ return shared_ptr<student>(this); } | |
}; | |
struct self_aware_leaky_student: public student | |
{ | |
// let an instance know its wrapped in a shared pointer | |
void know_thyself(shared_ptr<student> s) { self_ = s; } | |
// return the stored pointer | |
shared_ptr<student> shared_from_this() { return self_; } | |
private: | |
shared_ptr<student> self_; | |
}; | |
struct almost_right_student: public student | |
{ | |
// let an instance know its wrapped in a shared pointer | |
void know_thyself(shared_ptr<student> s) { self_ = s; } | |
shared_ptr<student> shared_from_this() { return self_.lock(); } | |
private: | |
weak_ptr<student> self_; | |
}; | |
int main() | |
{ | |
course math; | |
shared_ptr<almost_right_student> s = make_shared<almost_right_student>(); | |
s->know_thyself(s); | |
s->offer(math); | |
assert(s.use_count()==2); // enrolled_, s | |
} | |
/* | |
// The solution | |
struct student : public enable_shared_from_this<student> | |
{ | |
// offer a course and the student enrolls if interested | |
void offer(course& c) { if(interested_in(c)) { c.enroll(shared_from_this()); | |
} } | |
private: | |
// internal implementation of what interests a student | |
bool interested_in(course& c) { return true; } | |
}; | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment