STL map[k]=.. Always uses assignment@runtime

The focus is on the value2, of type Trade.

— someMap[key1] = value2; //uses default-ctor if needed. Then Unconditionally invokes Trade::operator=() for assignment! See P344 [[Josuttis]]

Without default-ctor or operator=, then Trade class probably won’t compile with this code.

— someMay.emplace(key1, value2); //uses some ctor, probably the copy-ctor, or the cv-ctor if value2 type is not Trade

Advertisements

STL vector bug(@@) – assigning an object to a particular index

Very inconsistent behavior!

vector ints(2);
cout<<ints.size()<<endl;
ints[4]=4; // silently ignored sometimes
copy(ints.begin(), ints.end(), ostream_iterator (cout, ” “));

Sometimes the assignment actually goes in and you can retrieve it at ints[4], though size() still stays at 2!

If you put a very large index, then crash is more likely.

not-b4-not-af : position-check in sorted data structure

[[more eff c++]] raised many points about the difference between equality check vs equivalence (i call it “ranking-check”) check. My short summary is

– not-before-not-after (based on comparison)
vs
– regular equality check as in java

Ranking-check — checking among existing data items in the container to determine where (if any) to put in an “incoming guest”. If the check shows incoming guest would hit the same position as an existing item, then a set/map (without prefix “multi-“) would reject.

Note standard STL set and map are all red-black-tree-based and all use ranking-check. There’s no hash container in standard STL. C++11 added unordered_*

The other points in the book tend to overwhelm a beginner, who is better off with a firm grip on just one concept — the real difference between the 2 checks.

3 basic container-cloning techniques (STL)

Note: I have never needed to clone a container.

STL containers have 3 similar (confusing) operations. Target container ends up with exactly the same content as the source container[1]. I consider them “cloning” operations, including swap.

1) generalized copy construction — from a source container to a new-born container
** I think you pass in a pair of iterators. [[c++StandardLibPracticalTips]] P96 shows the list and vector constructors

2) assignment — from a source container to an Existing target container
** I think most containers offer an operator= and also a this->assign() method. [[c++StandardLibPracticalTips]] P102 shows both.
[[ObjectSpace]] P14 covers operator=().

3) swap content — A ends up with B’s content, and B ends up with A’s content.
** Usually we use swap for one-way cloning. We clone from A to B and discard A.
** I think swap is a favorite among experts.

?) How about insert()? No. Insertion doesn’t meet the criteria in [1]. However, I feel insertion is often more useful more versatile more consistent. See http://bigblog.tanbin.com/2012/05/versatile-technique-to-populate-1.html

std::copy-print array of pointers

Suppose you already have a friend operator<<(ostream&, YourClass &) for YourClass, but you need to print out an array of pointers —

YourClass* array[99]

Here’s a first attempt —

copy(array, array+99, ostream_iterator(cout,” “); // prints the addresses

Simple solution —

Simply overload operator<<(ostream&, YourClass* const) using the existing operator<<

5 implicit conversions by c++ compiler — STL

See also posts on the “same” topic.

#50) [STL] when you use STL copy() to print any container, you implicitly call the ostream_iterator ctor

#40) [STL] when you specify a pred func in a STL algo, there’s a ton of implicit conversions behind the scene. Here’s one example. The pred func is invoked as

  bool flag = pred(*the_iterator_in_this_func_call) // for a unary predicate

#30) [STL] when you put a functor TYPE into  , the specialized template class’s constructor instantiates a functor OBJECT. In short, you specify functor TYPE only — functor Object instantiation is implicit. See P91 [[effective STL]]. P154[[STL tutorial]] shows

 set<char, less > mySetOfChar;

#20) [STL] converting a func name to a func ptr — when you pass the func name as arg to some STL algo. P 202 [[effective STL]]

function entities can be stateful in c++

Most function entities should be stateless — clean and simple, but in the real world there are exceptions —

localtime() and other standard system functions maintain local state in a local static variable (and create problem for threads). If you keep calling such a function, its internal state keeps changing

– STL generator functors — should return different values each time, so usually stateful

– Dinkumware’s hash tables have hashing traits/policies as state in the hashing functors. Does the state change from call to call? Not sure.

– P165 [[eff STL]] shows a clearly stateful functor. In practice we need such functors in special circumstances.

dump()for Any STL container #2 template func enough

template<typename M> void dumpMap(M const & cont) {
    for(auto const & i: cont)        cout<<i.first<<" -> "<<i.second<<endl;
}
template<typename CT> void dump(CT const & cont) {
    for(auto const & i: cont)        cout<<i<<endl;
}
/////////// above uses c++11 features
template<typename CT> void dump(const CT& cont) {
    typedef typename CT::const_iterator iterator; //typedef -- no choice
    iterator i;
    //non-compile --
    //CT::const_iterator i;
    for(i = cont.begin(); i!= cont.end(); ++i){
        cout<<*i <<" "<<endl;
    }
}
//! Better use iterator arguments
//! Better use iterator arguments
template<typename M>
void dumpMap(const M& cont) {
    typedef typename M::const_iterator iterator; //no choice
    iterator i;
    for(i = cont.begin(); i!= cont.end(); ++i){
        cout<<i->first<<" "<<i->second<<endl; // ->first may be unsupported. Checked during template expansion
    }
}
int main() {
    vector<int> v;
    v.push_back(12);
    v.push_back(24);
    map<char const *, int> map; // c-string i.e. char-pointer in a container
    map["1)"] = 11;
    map["3)"] = 33;
    dump(v);
    dumpMap(map);
}

transform/copy with push_back on yourself (i.e. a container)

    // abbreviations is a container.
    transform(abbreviations.begin(), abbreviations.end(),
        back_inserter(abbreviations), suffixAdder(c));

Broken, because abbreviations.end() dereferences to a special sentinel “value”. When you push_back on abbreviations, that sentinel “value” shifts to the right.

For example, If initially end() points past the 5th and last node, then after 1st push_back, the 6th position is populated, and the sentinel “item” is now after the 6th node. Initially you wanted to call insert() (and suffixAdder()) 5 times, but now you need to call it 6 times! In fact, it's a infinite loop as we keep shifting the finishing line.

Solution — use front_inserter instead of back_inserter.

essential pseudo-containers in STL

* arrays
* string — class template
* stream family — class templates

These are *extremely* essential utility containers.

For each pseudo-container, please answer these questions

Q: Provides iterators? I think so.
Q: Can use STL algo? yes if iterable, since STL algo only “cares about” iterators
Q: Allocator? not arrays or streams. Google search returns none

Fabric methods in c++ DTO classes (STL etc

The insert(),pop(),erase() etc are actually easy for most developers. Clear semantics. More tricky are the implicit “fabric” methods that convert from one type to another —

* Constructors esp. conversion constructors (cvctor)
* regular methods that converts *THIS to another type
* mysterious implicit type converters
* operator-overload converters
* operator[](), operator()()

You need to know them well for writing and esp. reading code. Remember the Millennium manager’s comment about implicit, context…? Seldom covered in phone interviews.