Click on prof3.h to get source.

// File: C++Examples/Lists/prof3.h
// overload function generic_lower_bound by container trait type
// in third argument to select container lower_bound 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 generic_lower_bound is overloaded
// by a third argument of the corresponding selector type
template<class  PROF_CONTAINER>
typename PROF_CONTAINER::iterator 
     generic_lower_bound(PROFLIST<PROF_CONTAINER>& 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<class  PROF_CONTAINER>
typename PROF_CONTAINER::iterator 
     generic_lower_bound(PROFLIST<PROF_CONTAINER>& 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<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(*this, goodprof,
		          *(new typename PROFLIST<PROF_CONTAINER>::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

   this->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
                  = 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
 
   this->erase(p);
   return 0;
} // end fire
#endif