#include <iostream>
#include <vector>
#include <string>

using std::cout;
using std::endl;
using std::vector;

class Node
{
    int _id;
public:
    Node(int id) : _id(id)
    { }
    virtual int GetID() const { return _id; }
};

class DNode : public Node
{
public:
    DNode(int id) : Node(id * 10)
    { }
};

class Branch
{
    vector<Node*> _list;
public:
    void PrintList()
    {
        cout << endl << "Printing the contents of the list:" << endl << endl;
        for(vector<Node*>::const_iterator it = _list.begin(); it < _list.end(); it++)
        {
            cout << "Contained Node:  ID " << (*it)->GetID() << "." << endl;
        }
    }
    Branch& operator <<(Node *op2)
    {
        cout << "Operator << triggered.  Node ID:  " << op2->GetID() << endl;
        cout << "Address received by operator <<:  " << op2 << endl;
        _list.push_back(op2);
        if (dynamic_cast<DNode*>(op2)) cout << "(This is a derived object)" << endl;
        cout << endl;
        return *this;
    }
};

int main()
{
    Node *p;
    Branch B;
    cout << "Simple addition of 1 node:" << endl << endl;
    for(int i = 0; i < 10; i++)
    {
        p = new Node(i);
        cout << "Node's address:  " << p << endl;
        B << p;
    }
    B.PrintList();
    cout << endl << "Chained addition:" << endl << endl;
    for(int i = 10; i < 20; i += 2)
    {
        p = new Node(i);
        Node *q = new DNode(i + 1);
        cout << "Node p's address:  " << p << endl;
        cout << "Node q's address:  " << q << endl;
        B << p << q;
    }
    B.PrintList();
    return 0;
}