#include <vector>
#include <iostream>
#include <functional>

using namespace std;

class Member;
using VMember = Member*;  //widok na obiekt, nie zarzadza obiektem
//Powinno być (C++17): using VMember = reference_wrapper<Member>
//ale w tym zadaniu poprzednia definicja wystarczy

using Team = vector<VMember>;

class Student;
class Staff;

class Visitor {
public:
    virtual void visit(const Student& s) = 0;
    virtual void visit(const Staff& a) = 0;
};

class Member {
public:
    Member() { }
    virtual ~Member() = default;
    virtual void accept(Visitor& v) const = 0;
};
class Student : public Member {
public:
    Student() : Member() {}
    void accept(Visitor& v) const override { v.visit(*this); }
};

class Staff : public Member {
public:
    Staff() {}
    void accept(Visitor& v) const override { v.visit(*this); }
};


class VisitorEqual : public Visitor {
public:
    VisitorEqual() : student_(0), staff_(0) {}

    bool isEqual() { return student_ == staff_; }

    void visit(const Student& ) override {
        ++student_;
    }
    void visit(const Staff& ) override {
        ++staff_;
    }
private:
    int student_;
    int staff_;
};

bool checkProper(const Team& t) {
    VisitorEqual v;
    for(const VMember& m : t ) {
        m->accept(v);
    }
   return v.isEqual();
}


int main() {
    Student s1;
    Student s2;
    Staff s3;
    Staff s4;

    Team t1 { &s1, &s2, &s3, &s4 };
    Team t2 { &s1, &s3 };
    Team t3 {  };
    Team t4 { &s1 };
    Team t5 { &s3 };
    cout << checkProper(t1) << endl;
    cout << checkProper(t2) << endl;
    cout << checkProper(t3) << endl;
    cout << checkProper(t4) << endl;
    cout << checkProper(t5) << endl;
    return 0;
}
