Download | Plain Text | Line Numbers


#include <cstddef> // for std::size_t
#include <cassert> // for assert
#include <utility> // for std::move
#include <stdexcept> // for std::out_of_range
 
struct Person
{
  Person (){}
  virtual int mark(){ return 0; }
  virtual ~Person(){}
};
 
struct Student : Person
{
  int m_mark;
  Student (int mark) :
    m_mark(mark)
  {}
  int mark()
  {
    return m_mark;
  }
};
 
struct Pupil : Person
{
  int m_mark;
  Pupil (int mark) :
    m_mark(mark)
  {}
  int mark()
  {
    return m_mark;
  }
};
 
#include <memory>
#include "shared_ptr.hpp"
 
#ifdef SOLVED_1
using Ti::shared_ptr;
using Ti::make_shared;
using Ti::shared_dynamic_cast;
#else
using std::shared_ptr;
using std::make_shared;
#endif
 
#include <array>
#include "array.hpp"
 
#ifdef SOLVED_2
using Ti::array;
using Ti::make_array;
#else
using std::array;
#endif
 
#include "mean_mark.hpp"
#ifdef SOLVED_3
using Ti::mean_mark;
using Ti::mean_mark_student;
using Ti::remove_greater;
#endif
 
#include <vector>
using std::vector;
 
int main()
{
  try {
    // initialize with new expression
    shared_ptr<Student> n1 (new Student(5));
    assert (n1.get() != 0);
    shared_ptr<Person> n2 (new Person);
    assert (n2.get() != 0);
 
    throw 0; // must be exception safe
  } catch (...)
  {}
 
  {
    // derived1 is 0.
    shared_ptr<Student> derived1;
    assert(derived1.get() == 0);
 
    // Other way for object creation
    derived1 = make_shared<Student>(3);
    assert(derived1.get() != 0);
 
    // Call object member
    derived1->mark();
 
    // Object creation with constructor parameters
    shared_ptr<Student> derived2 = make_shared<Student>(4);
    assert (derived2.get() != 0);
 
    shared_ptr<Person> base1 = make_shared<Person>();
    assert (base1.get() != 0);
 
    // Implicit upcast possible. The object make_sharedd in the previous line is
    // destroyed, because there are no more pointers referencing it.
    base1 = derived1;
 
#ifdef SOLVED_1
    // Explicit downcast possible. Some casts that are available: constCast,
    // staticCast, dynamicCast
    derived2 = shared_dynamic_cast<Student>(base1);
 
    // You can compare pointers.
    assert(derived1 == derived2);
#endif
 
    // Destroy most references to derived instance. References
    // (but not the object itself) are destroyed if they go out
    // of scope, or you can force reference destruction by multiple ways.
    derived1.reset();     // release reference
    assert(derived1.get() == 0);
  }
 
 
  {
    // array<int, 0> x; // Should fail with static assertion
 
    typedef array<shared_ptr<Student>, 5> sarray;
    sarray a;
    a [0] = shared_ptr<Student>(new Student(2));
    a [1] = shared_ptr<Student>(new Student(1));
    a [2] = shared_ptr<Student>(new Student(5));
    a [3] = shared_ptr<Student>(new Student(4));
    a [4] = shared_ptr<Student>();
    assert(a[0].get() != 0);
    assert(a[4].get() == 0);
    a [4] = shared_ptr<Student>(new Student(4));
 
    try {
      a.at(5); // throws exception
      assert(0);
    } catch (std::out_of_range const& oor) {
      oor.what();
    } catch (...) {
      assert(0);
    }
 
#ifdef SOLVED_2
    array<int,3> a1 = make_array<int,3>();
    a1.fill(3);
 
    array<int,3> a2 = make_array<int,3>();
    a2.fill(4);
 
    a1.swap(a2);
    assert(a1[0] == 4);
    assert(a2[2] == 3);
#endif
 
#ifdef SOLVED_3
    double mean = mean_mark(a.begin(), a.end());
    assert (mean >= 3.1 && mean <= 3.3);
 
    double mean_student = mean_mark_student(a.begin(), a.end());
    assert (mean_student >= 3.1 && mean_student <= 3.3);
 
    sarray::iterator end = remove_greater(a.begin(), a.end(), 3);
    double mean2 = mean_mark(a.begin(), end);
    assert (mean2 >= 1.4 && mean2 <= 1.6);
#endif
  }
 
  {
    typedef array<shared_ptr<Person>, 5> parray;
    parray m;
    m [0] = shared_ptr<Student>(new Student(2));
    m [1] = shared_ptr<Pupil>(new Pupil(1));
    m [2] = shared_ptr<Student>(new Student(5));
    m [3] = shared_ptr<Student>(new Student(4));
    m [4] = shared_ptr<Person>(new Person());
 
#ifdef SOLVED_3
    double mean = mean_mark(m.begin(), m.end());
    assert (mean >= 2.3 && mean <= 2.5);
 
    double mean_student = mean_mark_student(m.begin(), m.end());
    assert (mean_student >= 3.6 && mean_student <= 3.8);
 
    parray::iterator end = remove_greater(m.begin(), m.end(), 3);
    double mean2 = mean_mark(m.begin(), end);
    assert (mean2 >= 0.9 && mean2 <= 1.1);
#endif
  }
 
  {
    vector<shared_ptr<Person>> m;
    m.push_back(shared_ptr<Student>(new Student(2)));
    m.push_back(shared_ptr<Pupil>(new Pupil(1)));
    m.push_back(shared_ptr<Student>(new Student(5)));
    m.push_back(shared_ptr<Student>(new Student(4)));
    m.push_back(shared_ptr<Person>(new Person()));
 
#ifdef SOLVED_3
    double mean = mean_mark(m.begin(), m.end());
    assert (mean >= 2.3 && mean <= 2.5);
 
    double mean_student = mean_mark_student(m.begin(), m.end());
    assert (mean_student >= 3.6 && mean_student <= 3.8);
 
    assert(m.size() == 5);
    m.erase(remove_greater(m.begin(), m.end(), 3), m.end());
    assert(m.size() == 3);
 
    double mean2 = mean_mark(m.begin(), m.end());
    assert (mean2 >= 0.9 && mean2 <= 1.1);
#endif
  }
 
}
 
/* vim: set et sw=2 ts=2: */