Description

There are two STLs: the Standard Template Library and Stephan T. Lavavej

Advanced STL covers the gory details of the STL's implementation -> you will therefore need to be versed in the basics of STL, competent in C++ (of course), and be able to pay attention! Stephan is a great teacher and we are so happy to have him on Channel 9—the only place you'll find this level of technical detail regarding the internals of the STL. There are no books. There are no websites. This is Stephan taking us into what is uncharted territory for most, even those with a more advanced STL skill set.

In fact, STL was so impressed that he decided to try it out himself and see how generic he could make it. He uses only those STL features available in VC10 SP1 (for example, variadic templates are not used in his solution because the feature is not implemented in VC 2010 SP1...).

What did Stephan come up with? Get STL's PrettyPrinter implementation, then watch this great episode to learn the details behind the code. Thanks STL, KerrekSB, and Sven Groot for an excellent exercise!

I have a std::function question that I started on Stack Overflow ( http://stackoverflow.com/questions/6628442/can-tr1function-swallow-return-values and http://stackoverflow.com/questions/6653531/workaround-to-allow-tr1function-to-swallow-return-values).

To summarize, with the original boost::function I can hold a function that returns any type of value in a function wrapper that returns void, effectively "swallowing" the return value.

int Foo();boost::function<void()> Bar = Foo;

But this doesn't work in MSVC2008 using tr1::function (error C2562: 'std::tr1::_Callable_fun<_Ty>::_ApplyX' : 'void' function returning a value), and I'm told on Stack Overflow that it doesn't work in MSVC2010 either. Someone pointed out that the wording for the definitions of "callable" and the "INVOKE" meta-function that are used to describe std::function has changed between TR1 and C++0x, and that this change effectively rules out the boost::function behavior (since no types are implicitly convertible to void).

This is great, thanks so much! Very nice that you got the raw array covered without special treatment, I'll try to do improve our pretty printer similarly! In the meantime, have a look at this complete const_iterator/begin/end type trait -- does it work in MSVC? https://gist.github.com/1076849

Ivan, Part 5's comments> why would you want to "include subheader repeatedly"

As I recall mentioning in an earlier video, VC10 simulates variadic templates like "template <typename T, typename... Args> shared_ptr<T> make_shared(Args&&... args)" with the preprocessor. We have a subheader, <xxshared>, that lacks idempotency guards and uses special macros. <memory> then includes <xxshared> repeatedly, defining the macros differently each time - for 0 arguments, 1 argument, 2 arguments, all the way up to 10 arguments. This "stamps out" overloads of make_shared<T>(), simulating the single variadic template.

Josh K> That code will hopefully work in vs next.

It contains an exact major version check for VC10 because VC11 will need something different. I can't say what, yet.

Tominator2005> How would you write a pretty print function for a Binary Tree.

It depends on how fancy you want to get. Do you want a linear string (e.g. with parentheses), or an ASCII art tree?

Chris> Can you comment on this issue?

Looks like we conform to C++0x (Howard Hinnant is a Committee member and knows what he's talking about). Which is nice, since I had previously identified this as a bug in our TR1 conformance.

STL, thanks for this episode! I didn't know about the global begin()/end(), I've now included that in our pretty-printer as well to handle static arrays -- cool. I also added the full type trait check for const_iterator, begin and end which I posted above.

I like the generality you get with your formatter class, that's great!

Perhaps a few notes about our own implementation:

A small aside: Type erasure isn't generally used in our approach, everything is done at compile time. TE only comes in when you use a custom delimiter class via "cout << custom_delims<MyDelimClass>(x) << endl;", where you erase the type of "x". The standard formatter doesn't need this, and neither do specializations of the standard formatter.

I'm curious about your special treatment of strings (because we also discussed that). Since we decided to overload op<< directly, I always assume that any string class will have defined that overload already and thus our template never comes in. But I suppose since you have an explicit print function, you do need to catch special cases like types with iterators that aren't containers...?

A final note on our design choice to overload op<<: The one thing I personally really really feared was the need to remember a function name, and I was ready to give anything to be able to just say "cout << x << endl;" without thinking. I like your more powerful general formatter, but the zero-memory op<<-overload is something I cherish a lot

Anyway, great episode, with lots to learn from it -- keep it up, and looking forward to next month!

(Also, there appeared to be a bug in this website: After typing all this and submitting, I got a "system error" response, possibly because you were posting just before my submission. Not being able to go "back" in my browser (Iron), I could only press "reload" to repost, but with no avail - I finally resorted to tcpdump to capture the resubmit, URL-decoded the POST and recovered the raw HTML of this post. Phew.)

Fair enough - I didn't look very closely at the guts of your implementation. But mine doesn't use type erasure anywhere. :->

If you look at the STL, as a general principle, customization never involves additional costs. std::vector with a custom allocator or std::sort() with a custom comparator don't involve space or time costs beyond whatever's in the custom machinery itself. std::shared_ptr and std::function also follow this principle - they're performing type erasure anyways, so there's no additional cost for erasing custom deleters/allocators. (I have a todo to make them avoid storing empty allocators, which is something that we've already done to the containers.)

> But I suppose since you have an explicit print function, you do need to catch special cases like types with iterators that aren't containers...?

That's right. std::string could be handled within the general container machinery, by giving it a prefix and suffix of "\"" and a separator of "", but that would inefficiently print the string character-by-character. I built my pretty printer on top of iostreams, so performance is almost a lost cause anyways, but adding additional penalties would be even worse.

> The one thing I personally really really feared was the need to remember a function name

"print" is easy to remember. :->

The problem with op<<() is that it mixes code and data. I believe that Boost.Format's machinery is ideal, with two exceptions - it needs variadic templates instead of its op%() trick for C++98/03, and it needs to be built from scratch instead of above iostreams. My ideal I/O mechanism would look like print("format string", stuff, stuff, stuff), with customization along the lines of my pretty printer.

@STL: Your philosophy of not mixing code and data is interesting, perhaps I should rethink how I print things in general. Cheers.

Speaking of, if iostreams is such a drag and you have an idea how to do it better, would you care to share? I'm sure many people would love to see a high-performance and easy to use alternative! (Can your solution can beat "printf("%06X", myMACaddr)" in compactness and ease of use? )

When printing hex, I overwhelmingly want three things: zero padding, hexits equal to the width of the data type, and uppercase. I want to be able to say %X and have that work for unsigned char and unsigned long long equally.

It looks like MAC addresses are 12 hexits, not 6. If they had their own type, they could be annotated with their width.

@ STLAnother great video(although I cant seem to think in template way- I miss my precious if statements, and template tricks are above my level :) ). That being said I really like the advanced series on The Next Generation of C++ although it is harder to understand than the The Original Series :P

BTW I have two STL questions1.often I use set s<T> and then I check if the element is in the set( .count ). Problem is that I think that sorted vector<T>(because it is in sequential memory locations ) + binary_search() is faster way to do it? Am I right?BTW I know you probably arent allowed to tell the details but if you were working on Office or VS GUI would you bother with this optimization? 2. Also if I call MULTIset insert with 100 elements-how many malloc calls is that? 1(you know the required space because it is multiset) or 100.

P.S. Tnx for drawing the dbl_linked list on the white-board-as an ComSci student I'm always trying to find a reason to claim that my college wasnt a waste of time. :)P.P.S Regarding my stupid question about multiple includes, I now remember that you mentioned the MACRO_TRICK I just forgot how it was done.

@STL: Any idea why INVOKE was changed in this way? Is there some rationale - some gotcha that I can't see? Or is there some obvious workaround/alternative that renders it unnecessary? This could be a good topic for the next talk :) - it would likely touch on the machinery of std::function, possibly std::bind, lambda functions, forwarding, variadic templates, etc. and how they interact.

@STL: In regards to your comments around 12:56-13:10, will you be paying my company to do the upgrades and the necessary (and expensive) 3rd party library upgrades that would need to occur? Will you say something similar about Vs2010 when VsNext is issued? Just wondering. It's easy to say everybody should upgrade to the latest, just not easy to do. If you can convince my boss to pay for that, you're better than me. I'm sure he'll gladly accept free copies though if you or Charles or any other MS employee are willing to donate to my company. You should have seen the fight we had to undertake to move from VC6 to VS2008! So, in about another 7 years we may upgrade if current trends continue.

I have a topic for you; std::codecvt. C++ and Unicode. How do you convert between the different encoding in a standard and portable way. Some say C++ support for unicode is embarrassing, but that's all changed with C++0x, right?

C++ unicode issues are something I would very much like to see some coverage of ... but it really doesn't fall into STL's area I don't think. That's why (as I have suggested previously) I think there is room for a more general series of topics that ventures beyond STL's "turf" in the library. The challenge would be to find someone of STL's caliber to deliver such lectures. It would probably be a good place for rotating presenters.

..... I think there is room for a more general series of topics that ventures beyond STL's "turf" in the library. The challenge would be to find someone of STL's caliber to deliver such lectures. It would probably be a good place for rotating presenters.

Would you like to see a monthly show focusing on native dev with a rotating cast of characters and topics? Would you like a native-focused show that thrills and delights, educates and challenges? Well, hold on pardners... It's a comin'!

Would you like to see a monthly show focusing on native dev with a rotating cast of characters and topics? Would you like a native-focused show that thrills and delights, educates and challenges? Well, hold on pardners... It's a comin'!

@petke, @ryanb: The C++ language standard has no notion of "encoding". Moreover, it has no notion of "text" and "binary representation of text". Any explicit Unicode-related operations are strictly outside the scope of the language.

What C/C++ do do is to acknowledge that the historically misnamed type `char`, which should probably have been called `byte`, is insufficient for textual purposes, and it provides a platform-dependent, unspecified textual type `wchar_t` to hold a platform-dependent text character primitive. Acknowledging further that the outside world communicates in byte streams, the standard assumes that there exists a (platform-dependent) method to translate between fixed-width wide strings and variable-width byte streams, provided by `mbsrtowcs` and `wcsrtombs`. (I wrote a little rant about this on SO a while ago.)

In this sense, the native MSVC environment only supports UCS-2, or otherwise it gives you varibable-width 16-bit strings internally with no genuine "character" functions built into the language. It's also worth noting that most file systems accept null-terminated byte strings as file names (again with no notion of encoding or textual semantics), and NTFS is one of the rare kind to use null-terminated 16-bit strings (not: unicode) as filenames, necessitating non-standard file functions like `_wfopen`.

Personally, I think the notion of "text" is just very high-level, and instead of burdening a general purpose language like C or C++ with it, it's best left to something like ICU that can perform normalization and other deep text operations.

Ivan> often I use set s<T> and then I check if the element is in the set( .count ).

I prefer s.find(key) != s.end() because it's equally efficient for sets and multisets.

Ivan> Problem is that I think that sorted vector<T>(because it is in sequential memory locations ) + binary_search() is faster way to do it?

It depends on what you're doing with your data.

If you build up your data structure in one phase, then repeatedly access it in another phase, then it's probably going to be more efficient to build up a vector, sort it, and then do lots of binary searches.

However, if your insertions are interleaved with lookups, and especially erasures, then a sorted vector is totally inappropriate and you definitely want a set.

Ivan> if you were working on Office or VS GUI would you bother with this optimization?

Only if (1) profiling identified the set as a bottleneck, and (2) I had the access pattern guarantee allowing me to use a sorted vector instead.

By the way, I dealt with this kind of issue in my Nurikabe solver.

> Also if I call MULTIset insert with 100 elements-how many malloc calls is that?

@STL First tnx for the answ and the FizzBuzz suggestion. Will look it up. To be clear my question about vector vs set was for case where there are no removals or new insertions. Disregarding my compsci knowledge erase-remove idiom is enough to scare me away from using vector in that way. BTW I prefer .count() instead of find() because it allows me to do the horrible if(s.count(74656)) ."Ivan> Also if I call MULTIset insert with 100 elements-how many malloc calls is that?

100. The node-based containers (list, forward_list, set/multiset/map/multimap, and their unordered variants) store elements in separate nodes."Isnt that a wasted opportunity? Tp be clear I'm not talking about for (i=0;i<100;++i) ms.insert(v[i]), I'm talking about ms.insert(v.begin(),v.end());//v.size()==100this overloadtemplate<class InputIterator> void insert( InputIterator _First, InputIterator _Last );Is this inherent limitation of the C++ allocators or choice by library implementers?Again this might be a stupid question, but my knowledge of allocators is really limited...

@Ivan: Contiguous allocation is exactly the underlying idea of a vector. In an node-based container, you do want to have quick insertion and removal, so how could that work if elements didn't have their own memory? You'd end up with exactly the problem that vector has when you erase something from the middle. Or perhaps, since you don't require contiguousness, you would need a mechanism to free() a smaller chunk from amidst a larger allocated region -- as far as I know, no OS supports that sort of memory management. (Note that free() is only defined on a pointer that was previously allocated, you cannot say things like free(p+1).)

Yes. As I'm living in the future with VC11, VC10 already feels old to me.

Oh, this is unfair Stephan, you are tempting us.

For next topics, I recently got a translated version of Effective C++ and I get fascinated with std::function and his friends (like bind) and how it interact with the containers. Expanding std::function and bind looks a nice topic, with examples of how wrap old/legacy algorithm with STL (one example i like is the sorting the vector with C str wrapped functions) or using it in some pattern like a visitor or observers.

As always, nice video, thank you @STL

@Charles, keep it comming

(edited/added) I just remember another topic that could be nice (but don't know if it fits on "advanced"):std::hash, and how make our own types container/STL friendly.

@petke, @ryanb: The C++ language standard has no notion of "encoding". Moreover, it has no notion of "text" and "binary representation of text". Any explicit Unicode-related operations are strictly outside the scope of the language.

What C/C++ do do is to acknowledge that the historically misnamed type `char`, which should probably have been called `byte`, is insufficient for textual purposes, and it provides aplatform-dependent, unspecified textual type `wchar_t` to hold a platform-dependent text character primitive. Acknowledging further that the outside world communicates in byte streams, the standard assumes that there exists a (platform-dependent) method to translate between fixed-width wide strings and variable-width byte streams, provided by `mbsrtowcs` and `wcsrtombs`. (I wrote alittle rant about this on SO a while ago.)

...

Personally, I think the notion of "text" is just very high-level, and instead of burdening a general purpose language like C or C++ with it, it's best left to something like ICU that can perform normalization and other deep text operations.

Yes, Unicode/Multibyte operations are outside the scope of the language, which is why I said it is beyond the scope of this series (and I never suggested it should be part of the language). But the fact that the language will physically handle the representation of different encodings has little to do with being able to work with those encodings in the real world. Especially when a lot of us need to produce portable code in the real world, these platform dependent and encoding dependent differences make things very difficult (as you are well aware). Having some coverage of strategies for structuring code (using the existing language features) to deal with these situations would be of value.

If normalization libraries and a common internal representation are the only means of working with mixed-encoding environments, that raises the question of whether a normalization library (such as ICU, already a quasi-standard) needs to be provided as a language standardized, portable library.

With the advent of domain specific libaries such as <atomic> and <thread> I'd say Unicode operations and data types could very well be part of the standard. It is exactly those platform specific functions and types that drive people to higher level languages like Java, even if those are heavily dumbed down; they at least provide this cross-platform functionality with easy to use interfaces.

Of course, Qt could be an option but I despise it. It's not even a library, it's a complete application framework that takes over your programming environment with custom build-tools and tries to reinvent the STL.

@ KerrekSBIMHO you could have a vector of the adresses of the freed nodes so that map can use freed stuff for the new nodes. Ofc returning memory when (any node is deleted) to the os is a big no no because remembering when all the nodes allocated in one big alloc is hard(for me, it might be very very easy for someone smarter/more educated, best I can think of is atomic<size_t> n_block_nodes_in_use-when it reaches 0 you can return the memory). Again this leads to other problems you could alloocate 100x1M nodes, remove all but 20 and still end up with lets say 20X1M memory used(1 remaining node in each block). Then you end up with inserting memory usage balancing into the already hellish process of inserting a node in the RBTree. :) But still c++ vector also "wastes" memory. STL explained why. Standard smartly says that amortized cost of insertion must be O(1) when it is resized you get new_size=k+old_size(k=1.5 for VC, 2 for GCC if i remember corectly).

Regarding the FizzBuzz task you recommended to Ivan, I guess I'll have to do the same thing.

In C# I have no problems with generics (which is IMO far from templates), but I can imagine when using it. In C++ I have the problem (and it is a problem IMO), that I can't detect when templates would be valuable. In C# we have e.g. a generic Presenter (MVP), where we can pass some other class that the derived class depends on (IOC) or some other examples, where I know when to use generics when I see it. I'm sure I have a lot of code that could be optimized using templates. Of course I should be creating a few, so I see/learn the benefits of when to use them.

C++/OpenGL I do for fun on some evenings, after doing C# all day at work (learnt a lot about C++ in the last 1.5 years -- if I compare myself to questions from KerrekSB etc. I've got tons to learn).

I like this diagram for choosing containers: http://linuxsoftware.co.nz/cppcontainers.html (at the bottom. unordered_... not included), though I usually do look at a C++ reference site to see what's better for what case, i.e. inserting in middle, reading from middle, etc.

Previous video you mentioned in the comments, you can't comment on legal things, but you can say if we can use your code commercially/non-commercially etc. like the code above for printing an ASCII tree.

You actually used an ifstream this time I often use "pure" C++ classes (including ifstream). What I don't get, I recently saw this on cplusplus.com: ifstream provides an interface to read data from files as input streams. IMO that means, it's an interface, so I'm suppose to use an fstream if it's not meant to be an interface or to pass it an fstream to a function I could use Do(const ifstream& aStream);??? Or what am I misunderstanding. Does interface in this case mean a facade/wrapper, and not an interface (i.e. C#'s meaning of interface). Must be, since its functions are obviously not pure virtual.

Another question that someone may know. If I inherit from a base class, is it a bad idea to do an inline on an overriden (for virtual)/implemented (pure virtual) function in the derived class (obviously)?

Would you like to see a monthly show focusing on native dev with a rotating cast of characters and topics? Would you like a native-focused show that thrills and delights, educates and challenges? Well, hold on pardners... It's a comin'!

That sounds great: thanks Charles!

I'm looking forward to some of the Windows devs, like Larry Osterman and someone from lower-level too (e.g. Doron Holan, device drivers).

Some questions I'd like to ask to Larry is discussing why in their team they don't use C++ exceptions and prefer error codes, and what tools do they use to "develop Windows" (what editors? what debuggers? The great WinDBG? Some other tool?).

3. It doesn't spell multimap and multiset properly. (That's not a big deal in and of itself, but if you can't spell a container's name correctly, you probably haven't used it very much...)

4. It makes the whole process look way more complicated than it is.

Here's what I recommend:

1. Be familiar with the container adaptors: stack, queue, and priority_queue. They intentionally have very narrow, highly restricted interfaces (e.g. you can't iterate through a stack's elements). In fact, stack and queue don't do anything *except* restrict the interface of an underlying container. (priority_queue does a bit of real work by gluing the heap algorithms to an underlying container.) When your needs can be satisfied by a container adaptor, then use it. Otherwise, don't. (For example, I use a queue in my Nurikabe solver, and a priority_queue in my Huffman tree code above. Note that priority_queue::top() returns the "highest priority" element, but Huffman wants the lowest frequency nodes, so I use greater-than to reverse the ordering accordingly.)

2. Be familiar with the ordered associative containers: set/multiset/map/multimap. It's pretty obvious when you need them, and it's pretty easy to determine whether you care about duplicates.

3. Be aware of the unordered associative containers and their different guarantees. They're less convenient (no auto-sorting, no worst-case logarithmic guarantees) and harder to use (providing equality and a good hash is harder than providing less-than), so I recommend using them only when you know that you really want their properties.

4. Be familiar with the sequence containers: vector, vector, vector, list, forward_list, and deque. vector is by far the best general-purpose sequence container - it is both extremely efficient and extremely powerful (random-access is a very important power). Use vector unless you specifically need the unique abilities of another container. This is actually pretty rare!

4a. list is significantly less efficient than vector and significantly less powerful (it's bidi instead of random-access). Summarizing its advantages: (1) list has true O(1) push_front() whereas vector intentionally lacks push_front() because it would be O(N) (you have to specifically request that with insert() which is more verbose), (2) list::push_back() is true O(1) whereas vector::push_back() is amortized O(1) (this is a theoretical advantage but I have never seen it matter in practice), (3) list has true O(1) arbitrary insertion, but you have to have an iterator to the insertion location in the first place, making this not nearly as useful as it sounds at first, and (4) most importantly, as a node-based container, list insertion/erasure never invalidates iterators/pointers/references to other elements. list does other things (e.g. splicing), but those are the big ones as far as I'm concerned. Actually needing them is quite uncommon.

4b. forward_list is slightly more space-efficient than list (one pointer per node instead of two, no sentinel node), but even less powerful (forward instead of bidi) and with a more unusual interface. I have extreme difficulty imagining real uses for forward_list. But in the ridiculously improbable event that you need it, it's there.

4c. deque is the strangest container in the STL, and really in the world. In wall-clock terms, it supports amortized O(1) push_front() and push_back(), and is yet true O(1) random-access. It also has really special invalidation guarantees (it is the only STL container capable of invalidating iterators while preserving pointers and references). In absolute terms, it's not very efficient, especially in VC's implementation. You should use deque only when you need its strange properties, which is virtually never.

Deraynger> Previous video you mentioned in the comments, you can't comment on legal things, but you can say if we can use your code commercially/non-commercially etc. like the code above for printing an ASCII tree.

I can point to the notice at the bottom of every C9 page, which may or may not apply to my C9 code, and wouldn't be useful if it did!

I could also ask my bosses and boss-like entities about releasing my C9 code under the Boost Software License, which would actually be useful. But that sounds like work.

Deraynger> I recently saw this on cplusplus.com: ifstream provides an interface to read data from files as input streams.

They didn't mean interface in the special polymorphic sense (even though iostreams is full of virtuals). Interpret this as: "ifstream is a thingy that reads data from files".

Deraynger> IMO that means, it's an interface, so I'm suppose to use an fstream if it's not meant to be an interface

ifstream is a thingy that reads data from files.ofstream is a thingy that writes data to files.fstream is a thingy that can read data from and write data to files.

iostreams are hideously complicated in general, but this part is simple.

Deraynger> Do(const ifstream& aStream);???

Doing anything to an ifstream/ofstream/fstream involves modifying it, so const is erroneous here.

Deraynger> If I inherit from a base class, is it a bad idea to do an inline on an overriden (for virtual)/implemented (pure virtual) function in the derived class (obviously)?

The "inline" keyword (both when it's explicitly written, and implicitly granted to a member function defined in a class definition) has two effects. First, it's a non-binding hint to actually inline the function. This will typically be ignored for virtuals except in the presence of a very advanced compiler. Second, it grants the Partial ODR Exemption (also granted to templates) allowing header-only code. It has no other semantic effects.

To what extent is it arbitrary? If I have an interface/abstract base class, then it's not arbitrary anymore, although with templates I could probably skip the base class and use a template that checks that the class contains the functions I need.

Deraynger> I like this diagram for choosing containers

STL> I strongly disagree with that diagram for several reasons

As I mentioned, I never really used the diagram, but "I usually do look at a C++ reference site to see what's better for what case, i.e. inserting in middle, reading from middle, etc."

Regarding vectors, that's what I mainly use (especially for vertices etc.), map/multimap and in one case a stack<x, vector<x>()>.

STL> I can point to the notice at the bottom of every C9 page, which may or may not apply to my C9 code, and wouldn't be useful if it did!

[Edit] I sent an e-mail to C9 regarding the different questions. Theoretically I consider it quite open for interpretation, so IMO your code falls under user-posted content (see: http://channel9.msdn.com/info)">http://channel9.msdn.com/info), where you can provide a CC-license (which doesn't state it has to be the same as C9s CC-license), so you could theoretically say that we can use all of your posted code freely and commercially and the license is the following: http://creativecommons.org/licenses/by/3.0/, with the extra permissions that we can use it with or without a copyright notice with your name (provided you want that) , and as the license states, it has to be visible that this license is used.

I'll write when I get an answer from C9.

STL> [Inlines]

I use inline usually for tiny things (not even for calculations), but mainly just for setters/getters. But if I know that it shouldn't be for virtual functions, then I also won't use them there

Small question. If I use a for_each, can't I create a member function (preferably non-static) defined in the same class, or is it like a functor, where a seperate class/struct is necessary?

Thanks again for all your detailed answer (especially on the containers and the diagram).

STL> The problem with op<<() is that it mixes code and data.

Can you explain it, I don't get it

@Charles:

Charles> Would you like to see a monthly show focusing on native dev with a rotating cast of characters and topics? Would you like a native-focused show that thrills and delights, educates and challenges? Well, hold on pardners... It's a comin'!]

@STL is it possible in C++(without adding something to the STL implementation) to add for example .sort() member function to vector? I presume not, but I never understood the reasons. Also I dont know why it isnt defined in the standard. I mean I know that some people dislike Object languages, but C++ is supposed to give options to programmer , right?

@Ivan: C++ are based on 3 pilars: Containers, Iterators and Algorithm, this way they can provide a generic way to an algorithm like sort be applied to many type of containers through iterators interface. Here an except from sgi:

"Iterators are central to generic programming because they are an interface between containers and algorithms: algorithms typically take iterators as arguments, so a container need only provide a way to access its elements using iterators. This makes it possible to write a generic algorithm that operates on many different kinds of containers, even containers as different as a vector and a doubly linked list. "

@Ivan: Each container have begin and end because this is the way C++ had to implement interfaces (C++ don't have the interface keyword like other languages) and decouple it from the algorithms.

I can be wrong but, Sort as a member function looks like that sort belongs only to that container and need be implemented by it. Its not "C++ don't like Object", it was the solution they find when developing a library that fits on most generic way possible. As a member it only make inflate the container with a functionally that not belongs to it. Witch type of sort algorithm to use if an algorithm fits on more than one type of container, replicate code? Even if you think in sort member as a way to shortcut a call to sort(s_begin, s_end, d_begin) it only looks duplicating code and defeat the purpose of iterator (why make a iterator interface if sort will be on the object anyway?)

It's like the pretty printer above, you could want overload ostream and operator <<, but other prefer a separate print(...). What I know from now reading more and more C++ books and articles (and I'm aligning to it) is make a print(...) could be more interesting for keep the algorithm generic, decoupled and self-contained. In the way to chose commodity or discipline, choose the later

@new2STLI dont really reakly understand that it would be hard to implement it. Every .sort could be {sort(this->begin,this->end());}Maybe I'm wrong. :) That is why I would like STLs answer. He knows the standard very well and the reasons for certain decisions.

@Ivan the reason is: code duplication, maintenance and the like. You have std::sort which already does the job, why would you want to have another sort specific to a container? That's the whole beauty of generic programming. You've got an algorithm and it works on many different containers. Exponential growth (of number of algorithms/methods/fncs) is something what you want to avoid.

@aasss like I replied before member function could be a wrapper around the real sort so I dont see a code duplication problem. Also why I want it? Because like I said it is easier for me to thing in object way. Again I would like STLs opinion because he is the expert. P.S. there is a std::count, map::count, multimap::count

@aasss like I replied before member function could be a wrapper around the real sort so I dont see a code duplication problem. Also why I want it? Because like I said it is easier for me to thing in object way. Again I would like STLs opinion because he is the expert.P.S. there is a std::count, map::count, multimap::count

Following your way of reason, you should add a sort() method to several containers, not only vector. Then why not adding also a binary_search() or search() method where applicable, to vector and to other containers? And add other do_some_cool_algorithm() method? Then the public interface of STL classes become bloated, contrary to STL's philosophy.

As I understand it, the STL's philosophy has a strong decoupling between containers and algorithms (iterators are the "glue"), and they try to keep container public interfaces minimal.

But I agree with you that is better waiting for STL's (Stephan) answer.

In the template world, "arbitrary" means exactly what it says on the box: the whole universe of types, until you choose to constrain it.

Deraynger> If I have an interface/abstract base class, then it's not arbitrary anymore, although with templates I could probably skip the base class and use a template that checks that the class contains the functions I need.

Think back to the intro series, where I believe I ranted against pre-STL containers (now extinct) that required their elements to derive from a common base class. (If I didn't rant against them, I should have.) That's obnoxious (and inefficient!) for lots of reasons, but the simplest one is that int doesn't have a base class. Inheritance schemes can't handle the built-in types, while templates can.

There is a time and place for inheritance (e.g. type erasure is powered by it), but it shouldn't be used when templates are more appropriate.

Deraynger> IMO your code falls under user-posted content

Remember that I am not a user, I am a Microsoft employee. The company owns everything I write on company time.

Deraynger> I use inline usually for tiny things (not even for calculations), but mainly just for setters/getters.

"getters" and "setters" are two of my least favorite words - especially "setters". Most classes should provide abstractions higher than the level of individual data members. When you provide a "getter", you're essentially exposing the existence of a data member. That's two steps away from having a public data member, which is thoughtcrime. (Two steps, because it's read-only, and the data member doesn't have to physically exist - but to outside users looking at the interface, it may as well, which is almost as bad.) "Setters" are even worse, only one step away from public data members.

The correct way to design a class is to think about the abstraction you want, devise an interface to provide that abstraction, and finally implement it. Sometimes you do end up with member functions that directly return data members without doing anything else (or more rarely, directly modify without doing anything else), but it should not be an explicit goal of your design. If it happens too often, that may be a sign that your abstractions are too low-level.

Deraynger> Small question. If I use a for_each, can't I create a member function (preferably non-static) defined in the same class, or is it like a functor, where a seperate class/struct is necessary?

Are you asking about the operation provided to for_each() that will be executed on each element of the range? That has to be a functor. However, there are lots of ways to provide functors: function pointers, function object classes, lambdas, and helpers. mem_fn() from <functional> is such a helper - it takes a pointer-to-member-function (PMF) and returns a functor, because the syntax to invoke functors (which is func(obj, args) or func(*ptr, args)) differs from the syntax to invoke PMFs (which is (obj.*pmf)(args) or (ptr->*pmf)(args)). You can pass mem_fn(&YourClass::YourMethod) to an STL algorithm, which will adapt the syntax for you (but not quite as efficiently as a lambda due to optimizer limitations). Note that mem_fn() is super smart - the returned functor can be executed on objects/references, raw pointers, and smart pointers, and it just works.

Also note that mem_fun() and mem_fun_ref() (note the extra U) are C++98/03 tech, and are vastly inferior to TR1/C++0x mem_fn() (note: no U).

STL> The problem with op<<() is that it mixes code and data.

Deraynger> Can you explain it, I don't get it

Consider: cout << "I have " << n << " " << animals;

Now suppose that I want to internationalize my program. I can use Unicode, and load strings at runtime for different languages. But what if I have to deal with a language where the word order is different from English (e.g. putting the number after the "kittens" or "puppies" that I have, etc.)? The order is controlled by the *code*. That is not good.

With Boost.Format, this looks like format("I have %1% %2%") % n % animals. Now the order is controlled by the *data*, the string passed to boost::format. A language with a different word order can simply load the string "blah blah %2% %1%" and that'll reverse the order of n and animals.

Ivan> is it possible in C++(without adding something to the STL implementation) to add for example .sort() member function to vector?

No. Other languages have a feature called "extension methods", allowing people to glue member functions onto a class without being that class's author. In general, I believe that it's an anti-feature.

Ivan> Also I dont know why it isnt defined in the standard.

This was one of Alexander Stepanov's greatest insights, and I believe I talked about it in the intro series.

Remember that sort() isn't the only STL algorithm. There's something like over a hundred of them, and they usually come in pairs (default version, functor version). There are also lots of STL containers. Do you really want the STL to define X * Y member functions, where X is the number of algorithms and Y is the number of containers? Even worse, what if when writing a custom container, you had to define X member functions to wrap the algorithms? That is a recipe for interface bloat (look at std::string for an example of a bloaty interface, which Herb Sutter has explained in his books).

With the STL's container-iterator-algorithm scheme, we end up with X + Y definitions, which is much better than X * Y.

(Additionally, algorithms taking iterators are more general for two reasons. First, you can operate on subranges of a container, which isn't necessary that often, but when you want it, you really want it. Second, you can use custom iterators that do something special. back_inserter() is an example.)

There's no essential difference between (hypothetically) v.sort() and (actually) sort(v.begin(), v.end()). One puts the container on the outside, and one on the inside. It is slightly verbose to have to say begin and end in pairs, but the correct way to address that is to wrap pairs of iterators as ranges (which will probably appear in the STL someday in some form).

There's also nothing stopping you from writing container-based algorithm wrappers like sort(v). The STL could provide such things in a separate namespace, but it hasn't done so. (It would have to be a separate namespace, for an interesting reason. Putting iterator-based algorithms and container-based algorithms in the same namespace would lead to conflicts between sort(RanIt, RanIt) and sort(Container, Comparator) - with 1998-era tech there's no way to prevent conflicts there, and it wouldn't be especially fun even today.)

aasss> C++ is beautiful in this and every other way.

Heh, even I wouldn't say that (and I love C++ more than just about anyone). It's a big, complicated language and it has warts. But unlike everything else, it allows you to write extremely efficient code with a high level of abstraction in an elegant manner. You just have to be willing to tolerate low-level verbosity and clumsiness when judging elegance. For example, I think my pretty printer is elegantly structured.

Ivan> P.S. there is a std::count, map::count, multimap::count

The STL does make exceptions to its general rule of insulating algorithms from containers via iterators. This happens when algorithms can be implemented more efficiently (or at all) with "secret" knowledge of a container's internals. You've provided an excellent example. std::count() takes input iterators and is O(N), which is optimal in general (you have to look at every element in the range), even if the iterators are stronger, like bidi or random-access (it doesn't need and can't take advantage of those powers). However, the associative containers like multimap are special, because they're autosorted. multimap::count() is O(K + log N) where K is count()'s return value. This is much better than O(N). (If you're familiar with the basics of multimap's representation, as covered in the intro series, and the basics of computational complexity, then it should be obvious why it's O(K + log N).)

STL> There is a time and place for inheritance (e.g. type erasure is powered by it), but it shouldn't be used when templates are more appropriate.

Ok, so I'll see about rewriting everything . I have an idea for you or the authors, provided you/they have enough time: Rewrite the Design Patterns: Elements of Reusable Object-Oriented Software book using templates instead of inheritance

STL> Remember that I am not a user, I am a Microsoft employee. The company owns everything I write on company time.

Yes, I asked with enough details in the e-mail. But Your ASCII tree etc. was probably written in your own time. Anyhow, then I'll just have to rewrite the code from scratch provided that I ever sell a product containing your code.

Deraynger> I use inline usually for tiny things (not even for calculations), but mainly just for setters/getters.

STL> The correct way to design a class is to think about the abstraction you want, devise an interface to provide that abstraction, and finally implement it. Sometimes you do end up with member functions that directly return data members without doing anything else (or more rarely, directly modify without doing anything else), but it should not be an explicit goal of your design. If it happens too often, that may be a sign that your abstractions are too low-level.

As I mainly do OpenGL stuff, I do need a getter/setter for X, Y, Z etc., of course providing other functions too, based on those members. So it is a bit low level, but necessary IMO. Otherwise I agree that the functions should provide other things than just get/set. Other areas are when using inline is when checking e.g.

@STL Beauty is very subjective term. One likes when violins are playing and the other when he has dirty socks . To me C++ is beautiful. In every way. To you may not be but that just you and me and the way we see world (C++). There is no reason to discuss it further, those are very subjective and personal opinions.

And as for you loving C++ just about more than anyone? Bet to dissagree. You may think you do but that's just you, you cannot possibly know other people's feeling.

Regards.

P.S.

Would you mind and confirm that what you've said about not having member sort in vector and reasons for that is practically the same what I've said in my previous post?

@STLFirst again tnx for the great answers. I know that it is getting old but it is really interesting to hear opinion on this stuff from the expert. Regarding the MxN problem(see I was listening carefully before, here you used X and Y :) ). why there arent templates based on container types. I mean why cant you define your own sort template that works on every container that meets certain requirement(has any iterator, has rand_access iterator)? That would avoid the MxN problem, I think. Regarding multimap count I was a bit confused about the K part but then I remembered that it is a (multi)map. BTW does this mean that mm.count() is faster than count(mm.begin(),mm.end()); I presume that you can specialize count based on the input container..., but if you dont it will go through entire range(again I presume).

@STL "We do that for other algorithms, as I explained in Advanced Part 2. But not std::count(). Note that multimap::count()'s trick requires knowledge of the tree structure, not just bidirectional iterators. Therefore it must be a member function."Isnt it possible to check if the input container is map? Again my understanding of TMP is pathetic, but cant you do something like "if container is map"return container.count(element)?I presume you cant because you can only get info about built in types(like is_integral) and not about STL containers. And thre is no is_RB_TreeLike in standard :( :)BTW compiler probably has enough info to print a warning about that, but I presume that it would be a bad business decision because you dont want people complaining that MS compiler gives warnings on legit code. regarding the next topics:I read something about "implicitly-generated move operations" being broken. If you find it interesting you could do a quick video on it(I presume it is not 50 min lecture material).

Also regarding map and memory allocation(I know , "not again"). Are allocators powerful enough to "present" map in memory as one "vector of nodes" and memory allocation is just adding one node to the vector and pointers to the nodes are indexes in the vector. Ofc you would need a stack of freed nodes, and you would be unable to free the memory because of the fragmentation (unless you do an evil O(n) moving of nodes and restamping of idxs) . Again this is just my not so smart implementation, recently I did an implementation of node based structure that had all the deletes "in one place"(no inserts between first and last delete) in the program so I did it that way. Ofc not with allocators, I had std::vector of nodes. I presume it is impossible to this with allocators but if you can it would be a cool episode even before VC11 is no longer top secret.

Ivan> I presume you cant because you can only get info about built in types(like is_integral) and not about STL containers.

The STL can and does conspire with itself. However, given an iterator to an element, we can't find the parent container (without additional machinery that's expensive at runtime - we have such machinery to power our debug checks, as I explained in Advanced Part 3). Therefore, iterator-based algorithms can't perform trickery that requires access to the parent container.

(Technically, we could detect multimap iterators, and walk upwards until we found the root node. However, calling multimap::count() would be more efficient, since it can just start at the root node.)

> I read something about "implicitly-generated move operations" being broken.

That's "rvalue references v3", which isn't implemented in VC10. Additionally, the problems there were corrected before the Final Draft International Standard was released.

> Are allocators powerful enough to "present" map in memory as one "vector of nodes"

std::map gets memory from its allocator (by default std::allocator). It doesn't care where the memory comes from, only that the allocator obeys the STL's requirements (which, for example, forbid "internal storage" allocators that return memory from "inside" themselves). This allows you to use a pool allocator if you want.

Note that Windows (which ultimately powers std::allocator/new/malloc()) already does something very much like this. Their Low Fragmentation Heap is a bucket-based heap for small allocation sizes, such as tree nodes.

Off-topic: Great news everybody! New Visual Studio User Voice, a place for you make suggestions and vote for what wish in VS.Next

[edited7-24] Adding an interesting blog I found about the theme I suggested before (more insight on functional header) Some interesting usages of std::function, he touch std::function, std::shared_ptr and lambdas for an event dispatcher. The other posts on blog are interesting too (Pushing and pulling data in C++0x). Perhaps can inspire some usages like use C++11 on UI (adding here the back of Kenny Kerr in MSDN Magazine in Windows with C++)

Note that Suggestion One is more efficient than Suggestion Two, because std::function implements the Small Functor Optimization - resulting in zero dynamic memory allocations instead of two (you aren't using make_shared) for sufficiently small functors.

The tricky thing about doing this (usually referred to as a "scope guard") is that in order to provide automatic rollback in the presence of exceptions, the machinery shouldn't throw exceptions of its own.

So here's an E-mail that I sent to our internal C++ mailing list back in May:

Here's ScopeWarden, which has the following properties:

1. It stores a single raw pointer.

2. It's non-copyable and non-movable.

3. It doesn't copy or move the functor it's going to execute.

4. It never emits exceptions. Accordingly, it's marked __declspec(nothrow) to make the optimizer happier.

5. It can't be constructed from a temporary functor, preventing obvious badness.

7. SCOPE_WARDEN stamps out a lambda with a reference capture-default, [&], which means that it can access anything in its enclosing scope without performing a copy, and can both observe mutations and perform mutations.

8. SCOPE_WARDEN even avoids constructing identifiers with unintentional double underscores. The helper lambda for a ScopeWarden g2 is xxg2xx.

> I was trying to demonstrate how i would have liked the scoped class usage syntax to look like.

It looks like you want unique_ptr.

What scope guards (including ScopeWarden) do is remember an arbitrary action to be performed in the event of their premature destruction (and they're dismissable so they do nothing if they reach their full life expectancy). They're most useful for achieving the strong guarantee (transaction semantics) when copy-modify-swap isn't an option. As you perform actions, you create scope guards to exactly undo those actions in the event of an exception. If everything succeeds, you dismiss the scope guards, committing all of your actions.

Scope guards can be used for resource management (I did that with Boost in Advanced Part 5, when I didn't want to write wrappers for Windows' bcrypt.h), but dedicated resource managers like unique_ptr, shared_ptr, and vector should be used whenever possible.

> While your class ScopeWarden looks very nice can it be done i a different way with the same efficiency ?

ScopeWarden avoids both dynamic memory allocation and virtuals. (Remember that virtuals inhibit inlining, except with very advanced compilers, and even then the stars must align perfectly.)

> Is there any way to remove this dynamic allocation in scoped::reset:

You can with the Small Functor Optimization (keep a local buffer, placement-new your object into it), but it's rather tricky machinery.

> You will always use a function with 'scoped' and with that information you should be able to do some> template magic without this dynamic allocation trick to store the function for later use.

If you know you're going to have a function *pointer*, then just store the function pointer. You need placement new trickery for arbitrary functors.

Yes you can enclose the ptr in a class and pass it to unique_ptr but if you're only going to use it once that extra work and messes with locality etc...

I did see Advanced Part 5. But as i've said i don't like macros and the way boost does it is impossible to understand. I've tried to understand that macro but i got lost every time in the macro jungle oh and it's ugly and sort of unsafe if you compare it to say your ScopeWarden as far as i know.

I'm having a hard time finding information on Small Functor Optimization.

>If you know you're going to have a function *pointer*, then just store the function pointer.

When i said function i meant (function, functor and lambda) We need a general group name for these :/

> You need placement new trickery for arbitrary functors. Does this include lambdas too ?

That's sad news indeed, you would think c++0x would have fixed this issue so new trickery wasn't needed.

autoLOL, I was looking at the STL's code and I felt like an idiot, because I couldnt understand couple of lines ... then I noticed the horizontal bar. xD@ CharlesOne business question that you probably cant answer, but Im curious in case you can. AFAIK VS cpp regex machinery has a fair amount of bugs. Was it ever considered to buy the boost regex code(because it is so old and part of the boost that has high standards I presume it is pretty much bug free). Also that would be a huge boost for boost community IMHO. :)Regarding Boost would it be against the C9 rules if you would kidnap autors of some of the most used boost libs and asked them to do a couple of lectures on their library. I know boostcon has videos but they are relatively poor sound quality and relatively short.P.S. First going native show had some flying code that was too simple, please use some epic STL's stuff for the ep2. :D@ Charles && STLI like the new Native show(again I found the PR parts about fresh CPP a bit boring, but it was first show and a very good intro for non cpp people IMHO), but I hope that STL will continue with this series. Native show is OK as general talk about, present feature in couple of mins, but I really really like STLs "deep" lectures.

@ STL1) I know that you mentioned many times that you had a bunch of free time :P , so is there any chance to that you might review (some parts ofc, not entire manual) of the:"Optimizing software in C++: An optimization guide for Windows, Linux and Mac platforms"http://www.agner.org/optimize/#manualsI know that it is a strange request, but manual seems very interesting and I would feel much better following if they have your stamp of approval .2)I dont know if you remember your FizzBuzz suggestion(do it with templates). Im not asking for a solution(please please dont post the solution, I hate when I cant solve something and then I found out solution before I had time to figure it out) but could you explain the printing part of it. I mean AFAIK you cant cout during compilation. wikibook example for prime numbers uses function that is called at runtime:http://en.wikibooks.org/wiki/C%2B%2B_Programming/Templates/Template_Meta-Programming#History_of_TMP3)recently I realized how my knowledge is fragile. I thought that i understand (theoretically ofc) implementation of all STL containers, but then i realized that i dont understand how dequeue is done. I presume that it is like a vector with half of the reserved space before begin() and half of the reserved space after the end(). Am I right?Regarding topics for the future shows: 1. you could do more on TMP but please explain slowly because I presume that most people(including me) have only basic understanding of it and arent familiar with all the tricks. 2. Ofc doing something like "Modern CPP: why very good Cpp programmer from 2001 needs to update himself". could be useful:) Just please keep it hardcore :)and specific without generic :P PR stuff. 3. Random problem solving using modern CPP is cool. eg http://en.wikipedia.org/wiki/Directed_acyclic_word_graph

Jonas_No: unique_ptr wants to store a pointer, so it can't work with things that aren't pointers (e.g. arbitrary handles), but yourSecureZeroMemory example can easily be achieved by using custom deleters with unique_ptr.

Jonas_No> I'm having a hard time finding information on Small Functor Optimization.

It's an STL implementation detail.

Jonas_No> When i said function i meant (function, functor and lambda) We need a general group name for these :/

Different authors use different terminology, but I use "functor" to mean "anything callable" ("arbitrary functor" if I want to be very precise), "function object" to mean "class overloading op()" ("function object of class type" to be very precise), and "function" to mean "real function".

STL> You need placement new trickery for arbitrary functors.

Jonas_No> Does this include lambdas too ?

Yes. Lambdas with captures can contain an arbitrary amount of arbitrary state. Only stateless lambdas are convertible (in VC11) to function pointers.

Jonas_No> That's sad news indeed, you would think c++0x would have fixed this issue so new trickery wasn't needed.

There is no issue to fix, as far as I can tell.

Jonas_No> So now what, got any ideas or suggestions ?

Use ScopeWarden.

Ivan> so is there any chance to that you might review

No time, sorry.

Ivan> could you explain the printing part of it.

Oh, you can use cout (or printf, or puts) to print the fizzing and the buzzing. The trick is to avoid runtime testing, runtime iteration, and runtime recursion.

Ivan> i realized that i dont understand how dequeue is done.

deque is magic - probably the most magical STL container.

It stores elements in contiguous blocks. Unlike vector, which is a single contiguous block of memory, deque can contain multiple blocks. (Therefore, as far as users are concerned, deque does NOT provide the contiguity guarantee that vector and string have.) There can be 1 element in each block, or more (e.g. 16). deque has a "map" of pointers to blocks, to keep track of where they all are (this is essentially a vector of pointers, not a std::map).

When you push_front or push_back, the deque can allocate new blocks to store elements. From time to time, it has to reallocate its "map", which is why deque has the strangest invalidation guarantee in the whole STL - push_front and push_back can invalidate iterators, but they preserve pointers and references to elements (because the underlying blocks don't move around).

deque also has some truly complicated machinery to handle paired push_backs and pop_fronts, etc. for efficiency. (So complicated, it was broken in VC10. We've fixed that in VC11.)

@ STL super interesting answers esp deque(except the part about being the most magical container, RB_Tree based ones are my favs <3 :))... I know, I know it is just because I ask great questions :PBut seriously this deque really intrigues me.a) i dont understand the last paragraph. Can you explain it a bit. If the explanation is to complicated can you just provide a example of program that uses "paired push_backs and pop_fronts". And I dont understand how can an "old" container be broken. Did you reimplemented it in VC10?b) my model of the world is crumbling :) how can container that has RA access (AFAIK) not weaker one like BID have nonsequential implementation. I know that it can have amortized O(1) but that implementation doesnt fee like amortized O(1). I know that it doesnt have to be "one operation" to be O(1)(in fact vector implementation that takes 73 seconds to return single element for any size of the array is O(1) :)) but that vector of pointers just feels strange. :)And ofc I have other questions about the vector of pointers, how is dq[74656] translated to same internal block and the position in the block, but it is too long to explain I presume.

> except the part about being the most magical container, RB_Tree based ones are my favs <3

Red-black trees appear in textbooks, though. I can't name any other language/library that has a deque (specifically one with the trick of being random-access).

> i dont understand the last paragraph. Can you explain it a bit.

Imagine a program that repeatedly calls push_back(), pop_front(), push_back(), pop_front(). It would be lame if the deque had to constantly allocate new blocks (because one end of the deque is growing) and deallocate old blocks (because the other end of the deque is shrinking). Instead, the deque "wraps around", reusing its blocks. It needs to allocate new blocks only when the overall size of the deque is constantly expanding.

> If the explanation is to complicated can you just provide a example of program that uses "paired push_backs and pop_fronts".

Here's my regression test, which fails with VC10 SP1 and passes with VC11.

@ STLso if I understand correctly deque has n(variable ofc) blocks of same size(same size so that it can do division to get the block from the idx( like when finding an row in a axb matrix from 1D idx , but this is not continuous memory ofc so "map" of pointers ), and also uses modulo trick(it also (I presume) knows where in the block is the "start" )to achieve circularity (for eg(numbers are idxs): 3 4 5 ...(free space)...0("start") 1 2 )to make the full use of all but the last allocated block. Again this is kind of "trivia"(although I remember u saying something like "most of the time you dont need deque but when you need it, YOU NEED IT" :)) but I find it really interesting, if nothing else it made me think about the vector vs deque. Vector "cant" allocate +10 or +47 elements because of the copying(all elements must be continuous in the mem). Deque can, so it can use the trick that you mentioned. Again this is AFAIK from what I have understood from your comments, lets hope that I'm right. :)

@Ivan: I like the definition on here and the articles about memory management here (The Visual C++ Weekly). Vector is the abstraction of an array with a plus you can grow it if needed (efficiency on only one side for insertion and removes) , the contiguous guaranty of vector make it able o use even on C function that waits pointer and size.

Deque are good when you need insertions and removes frequently and efficiently like a vector on both ends (that article about memory management: double stack), one could use deque for jitter buffers (perhaps not the best example) with consumer and producers on a non-reliable line where you can use a reasonable 'buffer' length but cause bursts or starves the size could vary greatly.

>Vector "cant" allocate +10 or +47 elements because of the copying

It can, you can create a vector with a chunk increase of 10, so it will be prepared and changes bellow this threshold will be efficient, but if you insert 47 will had cost (worst if do it frequently). Even when you use a deque you need measure the correct needs of your application

@STL: this cool discussion sure are equivalent to an episode itself! We gained an extra before the next video

@STL can you tell us if this solution is the correct fizzbuzz solution (I took the code from http://codegolf.stackexchange.com/questions/23/fizz-buzz-in-tmp and modified it slightly when it wasnt working, probably i could make it not take 3 ints as template args, but if that is the only problem then it is not a problem xD ):

Regarding part 7- I think that people understand that you are very busy, but if it means something(if you are thinking that nobody cares if you make video or not) please know that I(and a bunch of other people I presume) found these videos very valuable.

First sorry it took me so long to say than you(I was kind of busy :)). Secondly, thank you. :)Regarding Boost.Peporcessor -it is out of my league. Only for now I hope. Also do you consider it "really useful" or "cool" or both?1. BTW Stephen do you have opinion about this article:http://cpptruths.blogspot.com/2011/07/want-speed-use-constexpr-meta.htmlDon't be scared to click, it is short one. 1 b)do you know why it isnt possible (AFAIK) for example to calculate something during compile time using regular functions, not TMP. For example I want to have an vector or array of sqrts. It would be much nicer if I could write something like const vector<int> roots=sqrt({0,1,2,3,4,5,6,7,8,9,10});(sqrt is idempotent function ofc) and have it calculated at the compiler at the run time. Do you know why is that not possible, is it a bad idea, or just very hard to do it withing c++ syntax rules,or proving idempotence is "hard", or...

Hi. Not sure if this is the right place to ask this question, but here goes. I am using vector in C++/CLI, I have: static vector<CPerson^>^ people = gcnew vector<CPerson^>();. I am adding people to the vector at runtime to get people[0], people[1], etc. I give the user the option to delete a person (people[n]) if he/she would like. My question: How would I go about doing this? I tried people->erase(people->begin());, among other things. I appreciate your help. Thank you very much. Brian.

first it is not the right place, secondly for the usage you want you should learn the differences between STL containers. vector doesn't look right for this task, I think list or set is better choice.Again wrong place, but if you like you should check out STL's video where he mentions remove erase idiom, or just look it up on wikipedia. Please note that erase remove idiom has bad performance if you remove just one element, then again just one element, ...

@STL - joined the party a bit late, I'm working through all of the videos now. Your style of teaching is first class as is your mastery of the subject. I hope to see more videos from you on C++.

Some suggestions for future episodes;

a) exceptions - when to use and when not to. also performance detailsb) design patterns - intro into modern design patterns and which to usec) intro into concurrency with Boost or c++11d) compiler optimisations, inlining, STV vectorisation etc

Ivan> Regarding Boost.Peporcessor -it is out of my league. Only for now I hope. Also do you consider it "really useful" or "cool" or both?

It's interesting. I haven't used it in real projects yet, but there's one place (stamping out a bunch of typedefs) where I believe it would be useful.

Matt> @STL - joined the party a bit late, I'm working through all of the videos now. Your style of teaching is first class as is your mastery of the subject. I hope to see more videos from you on C++.

Thanks! I'm very busy with VC11 right now, but I'm definitely planning to do more videos in the future.

Matt> a) exceptions - when to use and when not to. also performance details

This is probably worth a video (although I view it as more Core Language than Standard Library).

Matt> b) design patterns - intro into modern design patterns and which to use

I am actually not a fan of Design Patterns. I've read the book, and I didn't think it was that useful. I think in terms of C++ idioms instead (e.g. iterators, functors, non-virtual interfaces).

Matt> c) intro into concurrency with Boost or c++11

Definitely on the agenda. First we need to squash a bunch of bugs, though.

Matt> d) compiler optimisations, inlining, STV vectorisation etc

I'm not really the right person for this one - the compiler back-end is mostly a black box to me. C++ goes in, assembly comes out. I know "stuff", but not at an extreme level of detail - mostly what I need to get the STL to generate reasonably performant code.

(For example, vector's empty() is more efficient than size() == 0, so in VC11 I audited <vector> to internally call empty() whenever possible.)

Ivan> VS11 preview is out, can you show us some stuff.

I'd like to when I get some time. Plus I'd have to get VC11's IDE set up.

Ivan> P.S. I hope STL is fine, I presume that he was a bit sad to hear about no var templates in VS11

I heard about it long ago - as the compiler's first and best customer, I hear about their feature decisions long before everyone else. Variadic templates would certainly make my life much easier, but we have a new scheme for faking them (as I alluded to in Part 6) and I believe that it is better than the old scheme and already paying dividends.

@STL: I understand what you mean, but I think it's a good way to communicate intent. I still think you should do some STL videos regarding generally used "Patterns", I took ages to google, and find the right wording, to find CRTP. I think those are basics that anyone writing C++ should know. I would have written my code completely differently if I had known that. Especially I use the patterns quite often (the quality of it is another thing), so I knew, I need something that does X, and remembered something regarding that, by having read the Design Patterns book. Looked it up and implemented it. Now when I see the code I know, oh yeah, that's this or that pattern and works like this or that. Just my 2 cents.

I assume you used the patterns all before, just never thought of it as a pattern. If someone not so smart like you would look at it, I believe if they see certain constituents, they'd know what pattern you used, and if naming the methods/classes etc. in a similar way, it's even easier, like MakeXyz() or class AbcStrategy etc.

Matt> b) design patterns - intro into modern design patterns and which to use

I am actually not a fan of Design Patterns. I've read the book, and I didn't think it was that useful. I think in terms of C++ idioms instead (e.g. iterators, functors, non-virtual interfaces).

I recently stumbled across the useful pretty_printer implementation STL presents in this nice lecture. Thinking about it, I have rewritten the code a little bit to use a traits class to detect tuple types. The traits class relies on std::tuple_element<0,T>::type being valid. The code works with vc2010 and g++ 4.6.1. You can find the code here: