Sasha
Sasha

Reputation:

Most used STL algorithm, predicates, iterators

I am wondering how people use STL (No fancy boost)... just an ol' fashion STL. Tricks/tips/mostly used cases acquired over many, many years... and perhaps gotchas...

Upvotes: 6

Views: 3364

Answers (11)

Loki Astari
Loki Astari

Reputation: 264401

I love the istream_iterator and the ostream_iterator.

A nice easy way of reading a stream and making it look like any other container:

// Copies a stream of integers on the std input
// into a vector.
int main()
{
    std::vector<int>    data;
    std::copy(std::istream_iterator<int>(std::cin),
              std::istream_iterator<>(),
              std::back_inserter(data)
             );

    // By uisng the istream_iterator<> the input just becomes another container.
}

// Or even simpler:

int main()
{
    std::vector<int>    data(std::istream_iterator<int>(std::cin),
                             std::istream_iterator<>()
                            );

    // By uisng the istream_iterator<> the input just becomes another container.
}

Upvotes: 6

leander
leander

Reputation: 8727

The following is somewhat "evil", but it has saved us from many bugs.

(Update, thanks to @Ricky65's comment for drawing me back here.) C++11 has a range-based for loop that is far superior to this, if your compiler supports it; we still work with some really old compilers, though.

#define FOREACH(iter,stlContainer)  \
for ( typeof(stlContainer.begin()) iter = stlContainer.begin(), \
                                   iter##End_Cached = stlContainer.end(); \
      iter != iter##End_Cached; \
      ++iter )

(Further update, credit to the Boost devs.) It is loosely based on the more complicated but more capable BOOST_FOREACH macro, but has the advantage of being much easier to step through in debug builds for small cases, and not requiring a small pile of boost headers (which in some codebases/groups is verboten).

Using std::for_each is generally preferable, but has some disadvantages:

  • users must know a lot about the interactions between bind1st / bind2nd / ptr_fun / mem_fun to use it effectively for non-trivial "visitation" -- boost fixes a lot of these issues, but not everyone has or knows boost
  • users may need to provide their own separate functor (usually a struct) for just a single point of use; said structs cannot be declared within the function surrounding the loop, leading to "non-locality" of related code -- it doesn't read as well as having the logic in-line with the flow of the rest of the function in some cases
  • it doesn't always nicely inline, depending on compiler

The FOREACH macro as listed above provides a few things:

  • like std::for_each, you won't get your boundary tests wrong (no iterating one past the end, etc)
  • it will use const_iterators over constant containers

Note that it does require a somewhat nonstandard "typeof" extension.

A typical usage might be:

list< shared_ptr< Thing > > m_memberList;
// later
FOREACH( iter, m_memberList )
{
   if ( (*iter)->getValue() < 42 ) {
      doSomethingWith( *iter );
   }
}

I'm not entirely happy with this macro, but it has been invaluable here, especially for programmers without as much experience in STL-aware design.

(Please feel free to point out pros/cons/flaws, I'll update the answer.)

Upvotes: 1

Anonymous
Anonymous

Reputation: 18631

The functional stuff: bind1st, bind2nd, mem_fun, equal_to, etc. is pretty useful if for some reason one doesn't have access to Boost Bind.

It's very subjective question and much depends on your team coding style, project type, and other unknown factors.

Upvotes: 2

T.E.D.
T.E.D.

Reputation: 44804

I love vector. It's what C++ arrays should have been. I do a lot of real-time work though. Folks who don't need determinisim might prefer list.

Just about everyone uses the heck out of string.

I don't get to use algorithm much, as we still use VS6 here (which can't handle complex template instatiations). That will pass soon though.

Upvotes: 4

user65628
user65628

Reputation:

I can't recall having a favorite or most used algorithm/predicate/iterator, just the one that did the best job for what I was trying to accomplish at the time.

Upvotes: 2

bayda
bayda

Reputation: 13581

Ask painter "what your favorite/most used brush?" :)

Upvotes: 1

X-Istence
X-Istence

Reputation: 16667

I use the STL in almost all of my projects, for things from loops (with iterators) to splitting up the input into a program.

Tokenise an input string by spaces and input the result into an std::vector for parsing later:

std::stringstream iss(input);
std::vector<std::string> * _input = new std::vector<std::string>();

std::copy(std::istream_iterator<std::string>(iss), 
          std::istream_iterator<std::string>(), 
          std::back_inserter<std::vector<std::string> >(*_input));

Other favourites off course are std::reverse and various other algorithms defined in <algorithm>.

Upvotes: 7

Paul
Paul

Reputation: 13238

There are no most used STL algorithms, predicates or iterators. It's like asking what is the most used operator in C++ language. What do you use more often, operator+ or operator-? Do you prefer if to while? Or maybe to throw?

Everything is used when it has to be used.

PS: I suggest you to read Effective STL by Scott Meyers before asking such questions.

Upvotes: 1

anon
anon

Reputation:

My favourite is the following to change anything streamable to a string:

template <class TYPE> std::string Str( const TYPE & t ) {
    std::ostringstream os;
    os << t;
    return os.str();
}

Then:

string beast = Str( 666 );

Upvotes: 9

Eric Petroelje
Eric Petroelje

Reputation: 60498

Most useful algorithm (IMHO) - std::for_each

Upvotes: 3

Mark Ransom
Mark Ransom

Reputation: 308176

Using vector to replace pointer+new. That's huge.

Upvotes: 6

Related Questions