Standard Template Library
The Standard Template Library (STL) is a software library for the C++ programming language that influenced many parts of the C++ Standard Library. It provides four components called algorithms, containers, functional, and iterators.[1]
The STL provides a ready-made set of common classes for C++, such as containers and associative arrays, that can be used with any built-in type and with any user-defined type that supports some elementary operations (such as copying and assignment). STL algorithms are independent of containers, which significantly reduces the complexity of the library.
The STL achieves its results through the use of templates. This approach provides compile-time polymorphism that is often more efficient than traditional run-time polymorphism. Modern C++ compilers are tuned to minimize any abstraction penalty arising from heavy use of the STL.
The STL was created as the first library of generic algorithms and data structures for C++, with four ideas in mind: generic programming, abstractness without loss of efficiency, the Von Neumann computation model,[2] and value semantics.
Composition
Containers
The STL contains sequence containers and associative containers. The Containers are objects that store data. The standard sequence containers include vector
, deque
, and list
. The standard associative containers are set
, multiset
, map
, multimap
, hash_set
, hash_map
, hash_multiset
and hash_multimap
.
There are also container adaptors queue
, priority_queue
, and stack
, that are containers with specific interface, using other containers as implementation.
Container | Description |
---|---|
Simple containers | |
pair | The pair container is a simple associative container consisting of a 2-tuple of data elements or objects, called 'first' and 'second', in that fixed order. The STL 'pair' can be assigned, copied and compared. The array of objects allocated in a map or hash_map (described below) are of type 'pair' by default, where all the 'first' elements act as the unique keys, each associated with their 'second' value objects. |
Sequences (Arrays/Linked Lists): ordered collections | |
vector | a dynamic array, like C array (i.e., capable of random access) with the ability to resize itself automatically when inserting or erasing an object. Inserting an element to the back of the vector at the end takes amortized constant time. Removing the last element takes only constant time, because no resizing happens. Inserting and erasing at the beginning or in the middle is linear in time.
A specialization for type bool exists, which optimizes for space by storing bool values as bits. |
list | a doubly linked list; elements are not stored in contiguous memory. Opposite performance from a vector. Slow lookup and access (linear time), but once a position has been found, quick insertion and deletion (constant time). |
slist |
a singly linked list; elements are not stored in contiguous memory. Opposite performance from a vector. Slow lookup and access (linear time), but once a position has been found, quick insertion and deletion (constant time). It has slightly more efficient insertion, deletion and uses less memory than a doubly linked list, but can only be iterated forwards. It is implemented in the C++ standard library as forward_list . |
deque (double-ended queue) | a vector with insertion/erase at the beginning or end in amortized constant time, however lacking some guarantees on iterator validity after altering the deque. |
Container adaptors | |
queue | Provides FIFO queue interface in terms of push /pop /front /back operations.
Any sequence supporting operations |
priority queue | Provides priority queue interface in terms of push/pop/top operations (the element with the highest priority is on top).
Any random-access sequence supporting operations Elements should additionally support comparison (to determine which element has a higher priority and should be popped first). |
stack | Provides LIFO stack interface in terms of push/pop/top operations (the last-inserted element is on top).
Any sequence supporting operations |
Associative containers: unordered collections | |
set | a mathematical set; inserting/erasing elements in a set does not invalidate iterators pointing in the set. Provides set operations union, intersection, difference, symmetric difference and test of inclusion. Type of data must implement comparison operator < or custom comparator function must be specified; such comparison operator or comparator function must guarantee strict weak ordering, otherwise behavior is undefined. Typically implemented using a self-balancing binary search tree. |
multiset | same as a set, but allows duplicate elements (mathematical Multiset). |
map | an associative array; allows mapping from one data item (a key) to another (a value). Type of key must implement comparison operator < or custom comparator function must be specified; such comparison operator or comparator function must guarantee strict weak ordering, otherwise behavior is undefined. Typically implemented using a self-balancing binary search tree. |
multimap | same as a map, but allows duplicate keys. |
hash_set hash_multiset hash_map hash_multimap |
similar to a set, multiset, map, or multimap, respectively, but implemented using a hash table; keys are not ordered, but a hash function must exist for the key type. These types were left out of the C++ standard; similar containers were standardized in C++11, but with different names (unordered_set and unordered_map ). |
Other types of containers | |
bitset | stores series of bits similar to a fixed-sized vector of bools. Implements bitwise operations and lacks iterators. Not a sequence. Provides random access. |
valarray | Another array data type, intended for numerical use (especially to represent vectors and matrices); the C++ standard allows specific optimizations for this intended purpose. According to Josuttis, valarray was badly designed, by people "who left the [C++ standard] committee a long time before the standard was finished", and expression template libraries are to be preferred.[3] A proposed rewrite of the valarray part of the standard in this vein was rejected, instead becoming a permission to implement it using expression template.[4] |
Iterators
The STL implements five different types of iterators. These are input iterators (that can only be used to read a sequence of values), output iterators (that can only be used to write a sequence of values), forward iterators (that can be read, written to, and move forward), bidirectional iterators (that are like forward iterators, but can also move backwards) and random access iterators (that can move freely any number of steps in one operation).
It is possible to have bidirectional iterators act like random access iterators, as moving forward ten steps could be done by simply moving forward a step at a time a total of ten times. However, having distinct random access iterators offers efficiency advantages. For example, a vector would have a random access iterator, but a list only a bidirectional iterator.
Iterators are the major feature that allow the generality of the STL. For example, an algorithm to reverse a sequence can be implemented using bidirectional iterators, and then the same implementation can be used on lists, vectors and deques. User-created containers only have to provide an iterator that implements one of the five standard iterator interfaces, and all the algorithms provided in the STL can be used on the container.
This generality also comes at a price at times. For example, performing a search on an associative container such as a map or set can be much slower using iterators than by calling member functions offered by the container itself. This is because an associative container's methods can take advantage of knowledge of the internal structure, which is opaque to algorithms using iterators.
Algorithms
A large number of algorithms to perform activities such as searching and sorting are provided in the STL, each implemented to require a certain level of iterator (and therefore will work on any container that provides an interface by iterators). Searching algorithms like binary_search
and lower_bound
use binary search and like sorting algorithms require that the type of data must implement comparison operator <
or custom comparator function must be specified; such comparison operator or comparator function must guarantee strict weak ordering. Apart from these, algorithms are provided for making heap from a range of elements, generating lexicographically ordered permutations of a range of elements, merge sorted ranges and perform union, intersection, difference of sorted ranges.
Functions
The STL includes classes that overload the function call operator (operator()
). Instances of such classes are called functors or function objects. Functors allow the behavior of the associated function to be parameterized (e.g. through arguments passed to the functor's constructor) and can be used to keep associated per-functor state information along with the function. Since both functors and function pointers can be invoked using the syntax of a function call, they are interchangeable as arguments to templates when the corresponding parameter only appears in function call contexts.
A particularly common type of functor is the predicate. For example, algorithms like find_if
take a unary predicate that operates on the elements of a sequence. Algorithms like sort, partial_sort, nth_element and all sorted containers use a binary predicate that must provide a strict weak ordering, that is, it must behave like a membership test on a transitive, non reflexive and asymmetric binary relation. If none is supplied, these algorithms and containers use less by default, which in turn calls the less-than-operator <.
History
The architecture of STL is largely the creation of Alexander Stepanov. In 1979 he began working out his initial ideas of generic programming and exploring their potential for revolutionizing software development. Although David Musser had developed and advocated some aspects of generic programming already by year 1971, it was limited to a rather specialized area of software development (computer algebra).
Stepanov recognized the full potential for generic programming and persuaded his then-colleagues at General Electric Research and Development (including, primarily, David Musser and Deepak Kapur) that generic programming should be pursued as a comprehensive basis for software development. At the time there was no real support in any programming language for generic programming.
The first major language to provide such support was Ada (ANSI standard 1983), with its generic units feature. In 1985, the Eiffel programming language became the first object-oriented language to include intrinsic support for generic classes, combined with the object-oriented notion of inheritance.[5] By 1987 Stepanov and Musser had developed and published an Ada library for list processing that embodied the results of much of their research on generic programming. However, Ada had not achieved much acceptance outside the defense industry and C++ seemed more likely to become widely used and provide good support for generic programming even though the language was relatively immature. Another reason for turning to C++, which Stepanov recognized early on, was the C/C++ model of computation that allows very flexible access to storage via pointers, which is crucial to achieving generality without losing efficiency.
Much research and experimentation were needed, not just to develop individual components, but to develop an overall architecture for a component library based on generic programming. First at AT&T Bell Laboratories and later at Hewlett-Packard Research Labs (HP), Stepanov experimented with many architectural and algorithm formulations, first in C and later in C++. Musser collaborated in this research and in 1992 Meng Lee joined Stepanov's project at HP and became a major contributor.
This work undoubtedly would have continued for some time being just a research project or at best would have resulted in an HP proprietary library, if Andrew Koenig of Bell Labs had not become aware of the work and asked Stepanov to present the main ideas at a November 1993 meeting of the ANSI/ISO committee for C++ standardization. The committee's response was overwhelmingly favorable and led to a request from Koenig for a formal proposal in time for the March 1994 meeting. Despite the tremendous time pressure, Alex and Meng were able to produce a draft proposal that received preliminary approval at that meeting.
The committee had several requests for changes and extensions (some of them major), and a small group of committee members met with Stepanov and Lee to help work out the details. The requirements for the most significant extension (associative containers) had to be shown to be consistent by fully implementing them, a task Stepanov delegated to Musser. Stepanov and Lee produced a proposal that received final approval at the July 1994 ANSI/ISO committee meeting. (Additional details of this history can be found in Stevens.) Subsequently, the Stepanov and Lee document 17 was incorporated into the ANSI/ISO C++ draft standard (1, parts of clauses 17 through 27). It also influenced other parts of the C++ Standard Library, such as the string facilities, and some of the previously adopted standards in those areas were revised accordingly.
In spite of STL's success with the committee, there remained the question of how STL would make its way into actual availability and use. With the STL requirements part of the publicly available draft standard, compiler vendors and independent software library vendors could of course develop their own implementations and market them as separate products or as selling points for their other wares. One of the first edition's authors, Atul Saini, was among the first to recognize the commercial potential and began exploring it as a line of business for his company, Modena Software Incorporated, even before STL had been fully accepted by the committee.
The prospects for early widespread dissemination of STL were considerably improved with Hewlett-Packard's decision to make its implementation freely available on the Internet in August 1994. This implementation, developed by Stepanov, Lee, and Musser during the standardization process, became the basis of many implementations offered by compiler and library vendors today.
Criticisms
Quality of implementation of C++ compilers
The Quality of Implementation (QoI) of the C++ compiler has a large impact on usability of STL (and templated code in general):
- Error messages involving templates tend to be very long and difficult to decipher. This problem has been considered so severe that a number of tools have been written that simplify and prettyprint STL-related error messages to make them more comprehensible.
- Careless use of templates can lead to code bloat. This has been countered with special techniques within STL implementations (e.g. using void* containers internally and other "diet template" techniques) and improving compilers' optimization techniques. However, this symptom is similar to naively manually copying a set of functions to work with a different type, in that both can be avoided with care and good technique.
- Template instantiation can increase compilation time and memory usage, in exchange for typically reducing runtime decision-making (e.g. via virtual functions). Until the compiler technology improves enough, this problem can be only partially eliminated by careful coding, avoiding certain idioms, and simply not using templates where they are not appropriate or where compile-time performance is prioritised.
Other issues
- Initialisation of STL containers with constants within the source code is not as easy as data structures inherited from C (addressed in C++11 with initializer lists).
- STL containers are not intended to be used as base classes (their destructors are deliberately non-virtual); deriving from a container is a common mistake.[6][7]
- The concept of iterators as implemented by STL can be difficult to understand at first: for example, if a value pointed to by the iterator is deleted, the iterator itself is then no longer valid. This is a common source of errors. Most implementations of the STL provide a debug mode that is slower, but can locate such errors if used. A similar problem exists in other languages, for example Java. Ranges have been proposed as a safer, more flexible alternative to iterators.[8]
- Certain iteration patterns do not map to the STL iterator model. For example, callback enumeration APIs cannot be made to fit the STL model without the use of coroutines,[9] which are platform-dependent or unavailable, and are outside the C++ standard.
- Compiler compliance does not guarantee that Allocator objects, used for memory management for containers, will work with state-dependent behavior. For example, a portable library can't define an allocator type that will pull memory from different pools using different allocator objects of that type. (Meyers, p. 50) (addressed in C++11).
- The set of algorithms is not complete: for example, the
copy_if
algorithm was left out,[10] though it has been added in C++11.[11]
Implementations
- Original STL implementation by Stepanov and Lee. 1994, Hewlett-Packard. No longer maintained.
- SGI STL, based on original implementation by Stepanov & Lee. 1997, Silicon Graphics. No longer maintained.
- libstdc++ by the GNU Project (was part of libg++)[12]
- libc++ from LLVM
- STLPort, based on SGI STL
- Rogue Wave Standard Library (HP, SGI, SunSoft, Siemens-Nixdorf)
- Dinkum STL library by P.J. Plauger
- The Microsoft STL which ships with Visual C++ is a licensed derivative of Dinkum's STL.
- Apache C++ Standard Library (The starting point for this library was the 2005 version of the Rogue Wave standard library[13])
- EASTL, developed by Paul Pedriana at Electronic Arts and published as part of EA Open Source.
See also
Notes
- ↑ Holzner, Steven (2001). C++ : Black Book. Scottsdale, Ariz.: Coriolis Group. p. 648. ISBN 1-57610-777-9.
The STL is made up of containers, iterators, function objects, and algorithms
- ↑ Musser, David (2001). STL tutorial and reference guide: C++ programming with the standard template library. Addison Wesley. ISBN 0-201-37923-6.
- ↑ Josuttis, Nicolai M. (1999). The C++ Standard Library: A Tutorial and Handbook. Addison-Wesley Professional. p. 547.
- ↑ Vandevoorde, David; Josuttis, Nicolai M. (2002). C++ Templates: The Complete Guide. Addison Wesley. ISBN 0-201-73484-2.
- ↑ Meyer, Bertrand. Genericity versus inheritance, in ACM Conference on Object-Oriented Programming Languages Systems and Applications (OOPSLA), Portland (Oregon), 29 September – 2 October 1986, pages 391-405.
- ↑ Meyers, Scott (2005). Effective C++ Third Edition – 55 Specific Ways to Improve Your Designs. Addison Wesley. ISBN 0-321-33487-6.
- ↑ Sutter, Herb; Alexandrescu, Andrei (2004). C++ Coding Standards: 101 Rules, Guidelines, and Best Practices. Addison-Wesley. ISBN 0-321-11358-6.
- ↑ Andrei Alexandrescu (6 May 2009). "Iterators Must Go" (PDF). BoostCon 2009. Retrieved 19 March 2011.
- ↑ Matthew Wilson (February 2004). "Callback Enumeration APIs & the Input Iterator Concept". Dr. Dobb's Journal.
- ↑ Bjarne Stroustrup (2000). The C++ Programming Language (3rd ed.). Addison-Wesley. ISBN 0-201-70073-5.:p.530
- ↑ More STL algorithms (revision 2)
- ↑ "libstdc++ Homepage".
- ↑ Apache C++ Standard Library. Stdcxx.apache.org. Retrieved on 2013-07-29.
References
- Alexander Stepanov and Meng Lee, The Standard Template Library. HP Laboratories Technical Report 95-11(R.1), 14 November 1995. (Revised version of A. A. Stepanov and M. Lee: The Standard Template Library, Technical Report X3J16/94-0095, WG21/N0482, ISO Programming Language C++ Project, May 1994.)
- Alexander Stepanov (2007). Notes on Programming (PDF). Stepanov reflects about the design of the STL.
- Nicolai M. Josuttis (2000). The C++ Standard Library: A Tutorial and Reference. Addison-Wesley. ISBN 0-201-37926-0.
- Scott Meyers (2001). Effective STL: 50 Specific Ways to Improve Your Use of the Standard Template Library. Addison-Wesley. ISBN 0-201-74962-9.
- Al Stevens (March 1995). "Al Stevens Interviews Alex Stepanov". Dr. Dobb's Journal. Retrieved 18 July 2007.
- David Vandevoorde and Nicolai M. Josuttis (2002). C++ Templates: The Complete Guide. Addison-Wesley Professional. ISBN 0-201-73484-2.
- Atul Saini and David R. Musser, STL Tutorial and Reference Guide: C+ + Programming with the Standard Template Library. Foreword by Alexander Stepanov; [Copyright Modena Software Inc.] Addison-Wesley ISBN 0-201-63398-1
External links
- C++ reference
- C/C++ STL reference, includes C++11 features
- STL programmer's guide guide from SGI
- Apache (formerly Rogue Wave) C++ Standard Library Class Reference
- Apache (formerly Rogue Wave) C++ Standard Library User Guide
- Bjarne Stroustrup on The emergence of the STL (Page 5, Section 3.1)
- C++ Standard Specification