// File: C++Examples/Lists/prof3.h #ifndef __prof #define __prof #include #include #include #include #include #include #include using namespace std; class PROF { basic_string lname; // concept demo'd: basic_string template class // avoid the use of char[] altogether basic_string fname; char MI; double salary; int rank; float TPA; // ``teaching point average'' public: PROF(const basic_string& LN, const basic_string& FN, const char M, const double S, int R, float T) : lname(LN), fname(FN), MI(M), salary(S), rank(R), TPA(T) {} // constructor initializes fields bool operator<(const PROF& professor) const // needed in STL lower_bound algo {return lname < professor.lname; } bool operator==(const PROF& professor) const // needed in hire {return lname == professor.lname; } class comp_w_lastname { // needed by find_if in fire // concepts demo'd: predicate object, encapsulated class basic_string last_name; public: comp_w_lastname(const basic_string& name) : last_name(name) {} bool operator()(const PROF& professor) const {return professor.lname >= last_name;} }; // end class comp_w_lastname friend class PROF::comp_w_lastname; // accesses lname friend ostream& operator<<(ostream&, const PROF&);// accesses lname,fname template friend class PROFLIST; // needed in fire }; // end class PROF // These are the traits for the various STL containers struct algo_lower_bound {}; struct member_lower_bound {}; template class PROF_LIST_TRAITS { // by default, use lower_bound algo public: typedef algo_lower_bound select_lower_bound; }; template<> class PROF_LIST_TRAITS< list > {// for list<>, use lower_bound algo public: typedef algo_lower_bound select_lower_bound; }; template<> class PROF_LIST_TRAITS< vector > {// for vector<>, use lower_bound algo public: typedef algo_lower_bound select_lower_bound; }; template<> class PROF_LIST_TRAITS< deque > {// for deque<> use lower_bound algo public: typedef algo_lower_bound select_lower_bound; }; template<> class PROF_LIST_TRAITS< set > {// for set<> use member function; this is more efficient public: typedef member_lower_bound select_lower_bound; }; template class PROFLIST : public PROF_CONTAINER { // PROF_CONTAINER can be list or vector (STL sequence container) // or set (STL associative container) public: // define the lower_bound selector type for PROF_CONTAINER typedef typename PROF_LIST_TRAITS< PROF_CONTAINER >::select_lower_bound lb_selector; int fire(const basic_string&); int hire(const PROF&); // friend ostream& operator<< <>(ostream&, const PROFLIST&); }; // end template class PROFLIST // the template function generic_lower_bound is overloaded // by a third argument of the corresponding selector type template typename PROF_CONTAINER::iterator generic_lower_bound(PROFLIST& container, const PROF& goodprof, algo_lower_bound& tag) { cout << "Calling std::lower_bound" << endl; return std::lower_bound(container.begin(), container.end(), goodprof); } // end generic_lower_bound(...,algo_lower_bound&) template typename PROF_CONTAINER::iterator generic_lower_bound(PROFLIST& container, const PROF& goodprof, member_lower_bound& tag) { cout << "Calling container.lower_bound" << endl; return container.lower_bound(goodprof); } // end generic_lower_bound(...,member_lower_bound&) template int PROFLIST::hire(const PROF& goodprof) {// insert goodprof in alphabetic order; // returns 0 if successful, 1 if goodprof already there, // -1 if no more memory bool found; typename PROF_CONTAINER::iterator p = generic_lower_bound(*this, goodprof, *(new typename PROFLIST::lb_selector()) ); // STL search using PROF::operator< // returns the first valid place to insert goodprof and preserve order // concept demo'd: lower_bound; the use of traits if (p == PROF_CONTAINER::end()) found = false; else if (*p == goodprof) found = true; else found = false; if(found) return 1; // already there if( PROF_CONTAINER::size() == PROF_CONTAINER::max_size() ) return -1; // out of memory // max_size is how large the list can get at most insert(p, goodprof); // STL insertion into the list // concept demo'd: STL insert return 0; } // end hire template int PROFLIST::fire(const basic_string& badprof) {// remove element from sorted list; // return 0 if removal was successful; typename PROF_CONTAINER::iterator p = find_if(PROF_CONTAINER::begin(), PROF_CONTAINER::end(), PROF::comp_w_lastname(badprof)); // STL search using (encapsulated) predicate object // concept demo'd: STL find_if, usage of function object // Note: lower_bound could be more efficient, as it only // performs log(size) comparision. if (p == PROF_CONTAINER::end()) return 1; // not found if ((*p).lname != badprof) return 1; // not found erase(p); return 0; } // end fire #endif