Topic : STL Newbie Guide
Author : Mumit Khan
Page : << Previous 8  Next >>
Go to page :


ListElem& elem) const {
        return id_ < elem.id_;
    }
    bool operator== (const ListElem& elem) const {
        return id_ == elem.id_;
    }
    void print(ostream& os) const {
        os << "(" << id_ << " " << name_ << ")";
    }
};

void print_list(ostream& os, const list<ListElem>& list1) {
    for(
        list<ListElem>::const_iterator it = list1.begin();
        it != list1.end();
        ++it
    ) {
        const ListElem& elem = *it;
        elem.print(os);
    }
}

int main(int, char*[]) {
    list<ListElem> list1;
    list1.push_back(ListElem(5, strnew("5")));
    list1.push_back(ListElem(0, strnew("0")));
    list1.push_back(ListElem(99, strnew("99")));
    list1.push_back(ListElem(-1, strnew("-1")));
    list1.push_back(ListElem(31, strnew("31")));

    cerr << "Initial list: ";
    print_list(cerr, list1);
    cerr << endl;

    //
    // cannot use sort(list1.begin(), list1.end()) here; instead, must use
    // sort() member of list class. Hint: lists don't support random access
    // iterators.
    //
    list1.sort();

    cerr << " Sorted list: ";
    print_list(cerr, list1);
    cerr << endl;

    return 0;
}


And here's the output:

% ./stl-list-sort
Initial list: (5 "5")(0 "0")(99 "99")(-1 "-1")(31 "31")
Sorted list: (-1 "-1")(0 "0")(5 "5")(31 "31")(99 "99")


Sorting vector of user-defined objects
#include <iostream.h>
#include <stdlib.h>
#include <stl.h>
#include <string.h>

inline char* strnew(const char* str) {
    char* newstr = 0;
    if (str) {
        newstr = new char[strlen(str) + 1];
        strcpy(newstr, str);
    }
    return newstr;
}

struct ListElem {
    int id_;
    char* name_;
    ListElem() :
        id_(0),
        name_(strnew("unknown"))
    { }
    ListElem(const ListElem& elem) :
        id_(elem.id_),
        name_(strnew(elem.name_))
    { }
    ListElem(int id, const char* name) :
        id_(id),
        name_(strnew(name))
    { }
    ~ListElem() {
        delete[] name_;
    }
    ListElem& operator= (const ListElem& elem) {
        id_ = elem.id_;
        delete[] name_;
        name_ = strnew(elem.name_);
    }
    bool operator< (const ListElem& elem) const {
        return id_ < elem.id_;
    }
    bool operator== (const ListElem& elem) const {
        return id_ == elem.id_;
    }
    void print(ostream& os) const {
        os << "(" << id_ << " " << name_ << ")";
    }
};

void print_vector(ostream& os, const vector<ListElem>& vector1) {
    for(
        vector<ListElem>::const_iterator it = vector1.begin();
        it != vector1.end();
        ++it
    ) {
        const ListElem& elem = *it;
        elem.print(os);
    }
}

int main(int, char*[]) {
    vector<ListElem> vector1;
    vector1.push_back(ListElem(5, strnew("5")));
    vector1.push_back(ListElem(0, strnew("0")));
    vector1.push_back(ListElem(99, strnew("99")));
    vector1.push_back(ListElem(-1, strnew("-1")));
    vector1.push_back(ListElem(31, strnew("31")));

    cerr << "Initial vector: ";
    print_vector(cerr, vector1);
    cerr << endl;

    sort(vector1.begin(), vector1.end());

    cerr << " Sorted vector: ";
    print_vector(cerr, vector1);
    cerr << endl;

    return 0;
}


And here's the output:

% ./stl-list-sort
Initial list: (5 "5")(0 "0")(99 "99")(-1 "-1")(31 "31")
Sorted list: (-1 "-1")(0 "0")(5 "5")(31 "31")(99 "99")


Shuffling a deck of cards
Someone asked how to shuffle a deck of cards in c.l.c++ and rec.games.bridge a few days and there were lots correct (but long) answers using all sorts of tricks to avoid duplicate numbers in the random sequence produced. Here's a simple one using STL random_shuffle. To do it right, however, you should have a look at the random_shuffle (especially iter_swap) and make sure the seed is dynamically chosen (eg., use the current clock value) instead of the hard coded seed value used in most STL implementations.

#include <stl.h>                // or individual includes if you like
#include <iostream.h>

int main(int, char*[]) {
    const unsigned ncards = 5;
    int cards[ncards];
    for(int i = 0; i < ncards; ++i) {
        cards[i] = i + 1;
    }

    // print out the initial list (should be 1 ... ncards).
    ostream_iterator<int> out(cout, " ");
    cout << "initial: ";
    copy(cards, cards + ncards, out);
    cout << endl;

    // shuffle and print out the shuffled list
    random_shuffle(cards, cards + ncards);
    cout << "shuffled: ";
    copy(cards, cards + ncards, out);
    cout << endl;

    return 0;
}



And here's the output:

initial: 1 2 3 4 5
shuffled: 3 1 5 2 4


Deducing type from iterator
Sometimes it is useful to be able to deduce the type of the container element given only the iterator(s) to the container in question. There is a global function, value_type, just for this purpose. The following code snippet shows the usage:

    template <class InputIterator, class T>
    void __do_something(InputIterator first, InputIterator last, T*) {
 T tmp;
 //
 // now we can create variables of type T!
 //
    }
    
    template <class InputIterator>
    void do_something(InputIterator first, InputIterator last) {
        __do_something(first, last, value_type(first));
    }



Persistent STL
I'm making available an extremely simple and crude implementation of Persistent STL using libg++-2.6.2 hacked STL as the base implementation. Send me email if you'd like to know more about it. My current prototype is based on Texas Persistent Store v0.3 from UT-Austin OOPS research group. Click here for a GNU zip'd and tar'd copy of the current prototype (v0.1.1).


A look at ObjectSpace STL<ToolKit>
[A slightly modified excerpt from one of my postings in c.l.c++]
I've been using ObjectSpace STL<ToolKit> with gcc-2.6.3 quite heavily in the last few weeks and it turns out to be pretty solid. You obviously only get what GCC supports, but ObjectSpace did a pretty good job in squeezing out everything possible out of GCC in their implementation. I've run into a few problems (other than the well-known ones mentioned in the release notes), but there are easy work-arounds. Recently I have switched to ObjectSpace STL<ToolKit< with GCC 2.7.0.

GCC 2.7.0 users: ObjectSpace is providing bug fixes for STL <ToolKit> version 1.1 to make it work GCC 2.7.0. Please get in touch with ObjectSpace tehnical support for more information on how to acquire the fixes.

If you're using GCC 2.6.3, two things before you start:

patch 2.6.3 with the template fix ftp://ftp.cygnus.com/pub/g++/gcc-2.6.3-template-fix This solves the multiple definition problem.
learn the art of manual template instantiation if you want to avoid incredible code bloat in reasonable sized programs.
If you're using GCC 2.7.0, two things before you start:

patch 2.7.0 with the template repository fix ftp://ftp.cygnus.com/pub/g++/gcc-2.7.0-repo.gz This allows you to use template repositories to instantiate templates.
learn how to instantiate templates using the Cygnus -frepo.
Things in favor of ObjectSpace implementation:

GREAT install utility, esp if you want to use it for multiple compilers.
TONS of example programs. I believe these are now donated to the public domain and archived at the HP STL site (butler.hpl.hp.com).
Terrific manual. Just the manual is worth the $149 or so you pay for OS STL.
source code (guess it'll be kind of hard not to supply source :-)
Not so good:
Not the greatest telephone support.
crippled by the limitations of GCC (2.7.0 should make this a lot easier), the least of which are:
no just-used-member instantiation. One side effect is the extra unnecessary

Page : << Previous 8  Next >>