Click on prof3A.h to get source.
// File: C++Examples/Lists/prof3.h
// use container trait as second template class argument in
// template function object generic_lower_bound and (partial) template specialization
// to obtain call to lower_bound container member function when present
#ifndef __prof
#define __prof
#include <iostream>
#include <string>
#include <list>
#include <vector>
#include <deque>
#include <set>
#include <algorithm>
using namespace std;
class PROF {
basic_string<char> lname;
// concept demo'd: basic_string<T> template class
// avoid the use of char[] altogether
basic_string<char> fname;
char MI;
double salary;
int rank;
float TPA; // ``teaching point average''
public:
PROF(const basic_string<char>& LN,
const basic_string<char>& 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<char> last_name;
public:
comp_w_lastname(const basic_string<char>& 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<class C>
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_CONTAINER>
class PROF_LIST_TRAITS { // by default, use lower_bound algo
public: typedef algo_lower_bound select_lower_bound; };
template<>
class PROF_LIST_TRAITS< list<PROF> >
{// for list<>, use lower_bound algo
public: typedef algo_lower_bound select_lower_bound; };
template<>
class PROF_LIST_TRAITS< vector<PROF> >
{// for vector<>, use lower_bound algo
public: typedef algo_lower_bound select_lower_bound; };
template<>
class PROF_LIST_TRAITS< deque<PROF> >
{// for deque<> use lower_bound algo
public: typedef algo_lower_bound select_lower_bound; };
template<>
class PROF_LIST_TRAITS< set<PROF> >
{// for set<> use member function; this is more efficient
public: typedef member_lower_bound select_lower_bound; };
template<class PROF_CONTAINER>
class PROFLIST : public PROF_CONTAINER {
// PROF_CONTAINER can be list<PROF> or vector<PROF> (STL sequence container)
// or set<PROF> (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<char>&);
int hire(const PROF&);
// friend ostream& operator<< <>(ostream&, const PROFLIST<PROF_CONTAINER>&);
}; // end template class PROFLIST
// the template function object generic_lower_bound
template<class PROF_CONTAINER, class LB_SELECTOR>
class generic_lower_bound {
public:
typename PROF_CONTAINER::iterator
operator()(PROFLIST<PROF_CONTAINER>& container,
const PROF& goodprof)
{ cout << "Calling std::lower_bound" << endl;
return std::lower_bound(container.begin(),
container.end(),
goodprof);
} // end operator()
}; // end class generic_lower_bound
// Partial template specialization
template<class PROF_CONTAINER>
class generic_lower_bound<PROF_CONTAINER,member_lower_bound> {
public:
typename PROF_CONTAINER::iterator
operator()(PROFLIST<PROF_CONTAINER>& container,
const PROF& goodprof)
{ cout << "Calling container.lower_bound" << endl;
return container.lower_bound(goodprof);
} // end operator()
}; // end class generic_lower_bound<PROF_CONTAINER,member_lower_bound>
template<class PROF_CONTAINER>
int PROFLIST<PROF_CONTAINER>::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<PROF_CONTAINER,
typename PROFLIST<PROF_CONTAINER>::lb_selector
>() // constructor call
(*this, goodprof); // operator() call in class
// 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
PROF_CONTAINER::insert(p, goodprof);
// STL insertion into the list<PROF>
// concept demo'd: STL insert
return 0;
} // end hire
template<class PROF_CONTAINER>
int PROFLIST<PROF_CONTAINER>::fire(const basic_string<char>& badprof)
{// remove element from sorted list;
// return 0 if removal was successful;
typename PROF_CONTAINER::iterator p
= std::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
PROF_CONTAINER::erase(p);
return 0;
} // end fire
#endif