One question about slicing: You suggest forbidding any assignment operator and copy constructor in the polymorphic base class. However, how would you in that situation implement the derived class's copy constructor and assignment operator?
I was always under the impression that slicing was precisely required to say Base(rhs) and Base::operator=(rhs); in the derived implementations.
@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).)
@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.
@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? )
Also, I'm comparing our pretty-print implementations; for simple examples they produce identical assembly!
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.)
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
Charles, first off many thanks for all the work you put into this website - that's really cool. Second, don't feel compelled to force anything, if it doesn't come naturally, nobody needs to be on screen just for the sake of it. That said, it's a genuine pleasure listening to anything STL or Herb Sutter have to say (his last video Q&A on C++0x was actually pretty substantial!); I guess the pleasure comes from hearing someone who has a deep understanding of the matter and a clear way of thinking about it (e.g. any interview or talk by Bruce Schneier is equally enjoyable to watch).
If you have more people like that who would bring that clarity and insight to the screen, then by all means try and record them! I'm sure that substantial content on any sort of programming (but native especially) would always be appreciated!
When's the new episode coming online? Here's a tenuous suggestion -- "Extra Advanced STL"! Are you familiar with EASTL (https://github.com/paulhodge/EASTL) in any way? Why would someone need an alternative for the standard library, and why aren't the ideas of EASTL useful in the general standard? Is there anything a non-game programmer could learn from it?
@STL: Great, looking forward to your solution! By the way, I also thought at first I should look for the existence of begin/end member functions, but I found the check for the iterator type sufficient in the end. One could have used expression SFINAE with pointer-to-member-function type for that, but I didn't see the need for it in the end.
That's great, I look forward to the episode! In the meantime, I've put our pretty-printer on GitHub, here's the project website. There's a type-erasing helper class for convenient one-off delimiter overriding, too.
KerrekSB>> There's also the fact that in the STL you can only specify one single allocator, but that allocator gets used both for the actual contained objects and also for the internal bookkeeping data in an opaque way that you cannot control.
STL> Well, we need to allocate our internal helper objects, and you REALLY want us to do that with your (rebound) allocator, instead of std::allocator. (This is actually how I broke the compiler immediately after joining VC.) This inherently requires the whole rebinding scheme.
Are you saying that it just can't be made to work or doesn't make sense to permit two separate allocators, one for objects and one for bookkeeping, like:
@Ivan: There's also the fact that in the STL you can only specify one single allocator, but that allocator gets used both for the actual contained objects and also for the internal bookkeeping data in an opaque way that you cannot control. Well, I don't really know how much one can say about them, but I thought they're one part of the STL that's sort of always there but never really prominent, so it'd be cool to hear about it..