ostream_iterator
// Print sightings for selected animal:
for(int count = 1; count < 10; count++) {
// Use menu to get selection:
// int i = menu();
// Generate randomly (for automated testing):
int i = rand() % animals.size();
// Iterators in "range" denote begin, one
// past end of matching range:
pair
sightings.equal_range(animals[i]);
copy(range.first, range.second,
ostream_iterator
}
} ///:~
All the data about a sighting is encapsulated into the class DataPoint, which is simple enough that it can rely on the synthesized assignment and copy-constructor. It uses the Standard C library time functions to record the time of the sighting.
In the array of string animal, notice that the char* constructor is automatically used during initialization, which makes initializing an array of string quite convenient. Since it’s easier to use the animal names in a vector, the length of the array is calculated, and a vector
The key-value pairs that make up a Sighting are the string, which names the type of animal, and the DataPoint, which says where and when it was sighted. The standard pair template combines these two types and is typedefed to produce the Sighting type. Then an ostream operator<< is created for Sighting; this will allow you to iterate through a map or multimap of Sightings and print it out.
SightingGen generates random sightings at random data points to use for testing. It has the usual operator( ) necessary for a function object, but it also has a constructor to capture and store a reference to a vector
A DataMap is a multimap of string-DataPoint pairs, which means it stores Sightings. It is filled with 50 Sightings using generate_n( ) and printed out. (Notice that because there is an operator<< that takes a Sighting, an ostream_iterator can be created.) At this point the user is asked to select the animal for which they want to see all the sightings . If you press q, the program will quit, but if you select an animal number, the equal_range( ) member function is invoked. This returns an iterator (DMIter) to the beginning of the set of matching pairs and an iterator indicating past-the-end of the set. Since only one object can be returned from a function, equal_range( ) makes use of pair. Since the range pair has the beginning and ending iterators of the matching set, those iterators can be used in copy( ) to print out all the sightings for a particular type of animal.
Multisets
You’ve seen the set, which allows only one object of each value to be inserted. The multiset is odd by comparison since it allows more than one object of each value to be inserted. This seems to go against the whole idea of "setness," in which you can ask, "Is ‘it’ in this set?" If there can be more than one "it," what does that question mean?.
With some thought, you can see that it makes little sense to have more than one object of the same value in a set if those duplicate objects are
Like any STL container that must order its elements, the multiset template uses the less template by default to determine element ordering. This uses the contained classes’ operator<, but you can of course substitute your own comparison function.
Consider a simple class that contains one element that is used in the comparison and another that is not:
//: C07:MultiSet1.cpp
// Demonstration of multiset behavior
#include
#include
#include
#include
#include
using namespace std;
class X {
char c; // Used in comparison
int i; // Not used in comparison
// Don't need default constructor and operator=
X();
X& operator=(const X&);
// Usually need a copy-constructor (but the
// synthesized version works here)
public:
X(char cc, int ii) : c(cc), i(ii) {}
// Notice no operator== is required
friend bool operator<(const X& x, const X& y) {
return x.c < y.c;
}
friend ostream& operator<<(ostream& os, X x) {
return os << x.c << ":" << x.i;
}
};
class Xgen {
static int i;
// Number of characters to select from:
enum { span = 6 };
public:
Xgen() { srand(time(0)); }
X operator()() {
char c = 'A' + rand() % span;
return X(c, i++);
}
};