What Are SCARY Iterators?
As Stephan announced last September when Visual Studio 11 Developer Preview was released, our STL implementation comes with SCARY iterators. On Stephan’s words,
”(…) as permitted but not required by the C++11 Standard, SCARY iterators have been implemented, as described by N2911 “Minimizing Dependencies within Generic Classes for Faster and Smaller Programs“ and N2980 “SCARY Iterator Assignment and Initialization, Revision 1”.
What are they useful for? What are they, in the first place? What’s so SCARY about them?
In this post I’ll demystify any mystery about SCARY iterators, hopefully inspiring in you some design best practice for your own template classes.
Imagine the following situation:
Does it compile or not? Well, I tried to compile that code using a pre-v11 Visual C++ compiler, getting the following error:
The reason I’ve got this error is that in the last line of the code I’m trying to initialize iter (an iterator over a list of int using the default list allocator std::allocator<int>) with an iterator which looks similar excepts that it corresponds to a list allocated by the alternative stdext::allocators::allocator_unbounded<int>. Sad but true, these are different specializations of list of ints; therefore, conversions between them can’t be handled by default.
From a compiler perspective there is nothing wrong here. From a practical standpoint, however, there isn’t any semantic dependence between list iterators and list allocators. And, in general for all STL containers, iterators only depend (semantically speaking) on the container element type.
Based on research paper N2911 “Minimizing Dependencies within Generic Classes for Faster and Smaller Programs“, the acronym SCARY describes
Assignments and initializations that are Seemingly erroneous (appearing Constrained by conflicting generic parameters), but Actually work with the Right implementation (unconstrained bY the conflict due to minimized dependencies)
… or just SCARY, you know… (Don’t kill the messenger, I wasn’t the inventor of this name!)
In our STL11 implementation, iterator dependencies were minimized so the precedent code compiles fine. The same applies for any other STL container iterator (vector, deque, etc.) This said, you’ll be able to implement novel algorithms in ways that were previously impossible due to type mismatches. Not that scary, after all!
The issue that prevented my program to compile isn’t just tied to a particular STL implementation. In fact, as N2911 “Minimizing Dependencies within Generic Classes for Faster and Smaller Programs“ tells, it’s a more general issue that can happen when designing generic classes. In its authors’ own words:
We advocate a design principle whereby the dependencies between the members and the type parameters of a generic class should be minimized, we propose techniques to realize this principle, and we show that the principle can be leveraged to achieve faster and smaller programs.
Worth reading. Enjoy!
PS. A HUGE THANKS to Stephan T. Lavavej (Mr. STL) for reviewing this post.