stl.cc 4.73 KB
#include <set>
#include <functional>
#include <iterator>
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

bool is_even(int a)
{
    return a % 2 == 0;
}

int main()
{
    vector<int> vals { 1,2,3,54,6,7,9,9};
    // find locates the first element matching (compares equal to) 
    // the given value. The firts two arguments defines the half-open range
    // [first, last) spanning the values to search.
    // Returns an iterator to that element. Returns the second arguement
    // if no matching values is found 
    auto it = find(begin(vals), end(vals), 6);
    if ( it != end(vals) )
    {
        cout << "Found " << *it << " at index "
            << it - begin(vals) << endl; // random-access iterators support
                                         // subtraction to count number of
                                         // elements
        // distance(begin(vals), it) // more general way for other iterators
    }

    // find_if returns iterator to the first element that matches a
    // given unary predicate (function taking one element and returning bool).
    // important to pass the function, i.e. the name of the function and not
    // call it here.
    it = find_if(begin(vals), end(vals), is_even);
    cout << "First even number: " << *it << '\n';

    // can also pass a lambda. The lambda creates an unnamed function that
    // is only used in this scope and then disappears
    it = find_if(begin(vals), end(vals), [](int a){return a % 2 == 0;});

    // sort in incrementing order (using operator<)
    sort(begin(vals), end(vals));
    for ( int v: vals )
    {
        cout << v << endl;
    }
    // greater uses operator>
    sort(begin(vals), end(vals), greater<int>{});
    for ( int v: vals )
    {
        cout << v << endl;
    }
    // a lambda can be as complex as needed (but please leave it as
    // simple as possibly for readability)
    sort(begin(vals), end(vals), 
            [](int a, int b)
            {
            if ( !is_even(a) && is_even(b) )
            {
            return true;
            }
            else if ( is_even(a) && !is_even(b) )
            {
            return false;
            }
            return a < b;
            });
    // copy takes a range to copy and a third iterator that defines
    // the start of a destination range. copy requires (but doesn't check!)
    // that the destination range is at least as large as the source. 
    vector<int> v2(vals.size()); // initialize with size() elements
    copy(begin(vals), end(vals), begin(v2));
    { 
        // simpler to use copy constructor...
        vector<int> v2 {vals};
    }
    {
        // can also use constructor that accepts iterators
        vector<int> v3(begin(vals), end(vals)); 
    }
    {
        // can also use a back-insert-iterator. That iterator
        // will call push_back on the container used at initialization
        // when you write to it
        vector<int> v4;
        copy(begin(vals), end(vals), back_inserter(v4));
    }

    // an ostream_iterator is an output-iterator coupled to an ostream.
    // whenever you write to it, the value is printed to the stream.
    // The second value is a delimiter that is inserted after each value
    copy(begin(vals), end(vals), ostream_iterator<int>{cout, ", "});

    // unique removes consecutive repeated values from the range. It is
    // important that the range is sorted.
    // unique will not actually remove the values - it doesn't know how
    // to do that. Instead values are moved towards the end of the range
    // and an iterator to the first repeated value is returned.
    // Use that iterator with the containers erase function.
    sort(begin(vals), end(vals));
    auto trash = unique(begin(vals), end(vals));
    vals.erase(trash, end(vals));
    cout << "\n\n";
    copy(begin(vals), end(vals), ostream_iterator<int>{cout, ", "});
    cout << "\n\n";
    // the same problem can also be solved with set. set stores unique
    // values in sorted order.
    vector<int> v5 {2, 2, 2, 3, 2, 3, 4, 5, 6, 7, 6, 6, 8, 7, 9};
    set<int> s ( begin(v5), end(v5) );
    copy(begin(s), end(s), ostream_iterator<int>{cout, ", "});


    // string is a container (that only stores char) with random-access
    // iterators and will work with standard algorithms. It also has some
    // text-specific member functions, most of which returns an index.
    // string has a special member called npos which will be returned to
    // show that it didn't work.
    // find_first_of returns the index of the first char that is in the
    // string passed as argument
    string str {"this is a string (a container of char)!"};
    auto idx = str.find_first_of("(!)");
    if ( idx != string::npos )
    {
        cout << str[idx] << " found at index " << idx << endl;
    }
}