Jump to content

  • Log In with Google      Sign In   
  • Create Account

We need your help!

We need 1 more developer from Canada and 12 more from Australia to help us complete a research survey.

Support our site by taking a quick sponsored survey and win a chance at a $50 Amazon gift card. Click here to get started!


Like
0Likes
Dislike

The C++ Standard Library Part 1

By Howard "SiCrane" Jeng | Published May 18 2006 02:13 PM in General Programming

namespace using void aoi class library template dependent standard
If you find this article contains errors or problems rendering it unreadable (missing images or files, mangled code, improper text formatting, etc) please contact the editor so corrections can be made. Thank you for helping us improve this resource




Introduction

Much of the power and productivity of the C++ language comes from its standard library. However, the standard library is a fairly complicated collection of functions and classes, which can make it
hard to use and hard to get the most out of. This article series aims to introduce basic usage and best practices for using the C++ standard library. As much as I will try to make each article only
depend on the articles before hand, the standard library can be considered to be more or less an integrated whole, and as such I will be mentioning things that will be covered in later articles, and
some things I will only partially cover and leave the details for later.


Also, I will not be covering parts of the C++ standard library that have been incorporated from the C standard library, such as the C file I/O functions or the math functions.


This first article focuses on some features of C++ important to the use of the standard library that may not familiar to beginning C++ programmers or programmers coming from another language like
C. However, I will assume knowledge of the basic C++ language features like how to create and call functions, how to create classes, loops, if statements and using header files. ["fnt1" id="fnt1">1] I also assume that you are familiar with the basics of using iostreams for input and output. Not necessarily anything fancy with iostreams, but the basics like using
cout for output and fstreams to read numbers.


In this article I will be going over namespaces, templates and exceptions. The coverage of these topics in this article is not meant to be comprehensive. Templates, for instance, are complicated
enough that an entire book can be dedicated towards them (and has). However, the coverage should be sufficient to use most of the features of the C++ standard library.



A Note About Standards

C++ is a constantly evolving language, so it's important to know what version a given article is talking about. The C++ language was originally created by Bjarne Stroustrup, and was released in a
series of versions along with the compiler CFront. The C++ Standards committee was formed in 1989 and the first version of the standard was released in 1998 in the document ISO/IEC 14882:1998. In
2003, a technical corregenda was released in the form of the document ISO/IEC 14882:2003. This is an essentially an errata version, no major changes were introduced in 14882:2003, only clarifications
and corrections. The standards committee is currently working on the next version of the standard, which is anticipated to be released in 2009 and will have major changes. In the meantime, the
standard library committee is working on a series of additions to the library that are being released in a documents called technical reports. At this time, Technical Report 1 has been released, and
Technical Report 2 is still in the process of accepting proposals.


This article series is being written at the beginning of 2006, and so covers the C++ Standard with Technical Corregenda 1 (document ISO/IEC 14882:2003), and the C++ Standard Library committee's
Technical Report 1. At this point, recent compilers are almost all mostly in compliance with ISO/IEC 14882:2003, but almost none of Technical Report 1. [2]
However, many of the library additions detailed in Technical Report 1 are implemented in the Boost C++ Library. So while Boost is not part of the C++ Standard Library, I will be referring to parts of
Boost in this article series as they form the basis of parts of the Standard Library not implemented by current C++ compilers.



Namespaces

One trend in programming, and especially game programming, is the increased use of libraries from different sources. For example, a game might use a 3D rendering engine from Company A, a physics
engine from Company B, a sound effects library from Company C and a networking library from Company D. On one hand, this is a good thing as it increased productivity; the game programmers can focus
on making a game rather than implementing yet another 3D engine. On the other hand, the game programmer now needs to make sure that these different components work well together. One problem in
getting components from different sources to work together is name collision.


Name collision happens when there are two or more functions with the same name, or even two or more classes with the same name. This usually manifests as duplicate symbol linking errors. To
continue the game example, the 3D rendering engine may have a function process_BSP() and the 3D audio library might also have a function called "code">process_BSP().


To address this problem, C++ has namespaces. Namespaces are used to group identifiers together in named logical bundles. In the game example, the developer might try to put all the video
functions in a video namespace and all the audio functions in an audio namespace. In this way, the function names will no longer collide.


Putting things in a namespace is a lot like putting things into a class. For example, my personal code library lives in namespace aoi, so declaring things in that
namespace can look like:



<span class="codekeyword">namespace</span> aoi {

  <span class="codekeyword">class</span> MyClass {

    <span class="codecomment">// stuff</span>

  };

  <span class="codekeyword">void</span> my_function(<span class="codekeyword">void</span>);

}


Of course the syntax of namespaces and classes aren't exactly the same. The namespace syntax is different from a class in that it doesn't need a semi-colon at the end of the closing brace (though
putting one there doesn't hurt), and you can define the elements of a namespace over different files.



<span class="codecomment">// header one:</span>

<span class="codekeyword">namespace</span> aoi {

  <span class="codekeyword">class</span> MyFirstClass {

  };

}

 

<span class="codecomment">// header two:</span>

<span class="codekeyword">namespace</span> aoi {

  <span class="codekeyword">class</span> MySecondClass {

  };

}


To access elements inside a namespace you use the :: operator much like you would use to get at static members in a class.



aoi::MyClass my_object;

aoi::my_function();


Things inside the aoi namespace don't need to use the aoi:: prefix.



<span class="codekeyword">namespace</span> aoi {

  <span class="codekeyword">class</span> MyClass {

    <span class="codekeyword">public</span>:

      MyClass();

      <span class="codecomment">// stuff</span>

  };

  <span class="codekeyword">void</span> my_function(<span class="codekeyword">void</span>);

 

  MyClass::MyClass() {

    my_function();

  }

}


Also when writing code outside of the namespace, you don't need to use the :: operator on functions if the functions takes an argument defined in the same namespace.
[3]



<span class="codekeyword">namespace</span> aoi {

  <span class="codekeyword">class</span> MyClass {

    <span class="codecomment">// stuff</span>

  };

  <span class="codekeyword">void</span> another_function(const MyClass &);

}

<span class="codecomment">// outside the namespace</span>

<span class="codekeyword">void</span> some_other_function(<span class="codekeyword">void</span>) {

  aoi::MyClass my_object;

  another_function(my_object); <span class="codecomment">// doesn't need the aoi:: in front of another_function</span>

}


This is usually transparent on the end of the person using the types in the namespace. However, this is a good reason to put non-member functions that work on a type in the same namespace as the
type, especially overloaded operators.



<span class="codekeyword">namespace</span> aoi {

  <span class="codekeyword">namespace</span> string {

    <span class="codekeyword">class</span> sortable_string {

      <span class="codecomment">// stuff</span>

    };

    <span class="codekeyword">bool</span> operator<(const sortable_string & lhs, const sortable_string & rhs); <span class="codecomment">// good</span>

  }

  <span class="codekeyword">bool</span> operator>(const string::sortable_string & lhs, const string::sortable_string & rhs); <span class="codecomment">// bad</span>

}



using

Another way to access identifiers in a namespace is by a using declaration or a using directive. With a using declaration, you can specify an identifier in a namespace to be treated
as part of the current scope. For example:



<span class="codekeyword">namespace</span> aoi {

  <span class="codekeyword">class</span> MyClass {

    <span class="codecomment">// stuff</span>

  };

}

<span class="codecomment">// outside the namespace</span>

<span class="codekeyword">void</span> some_other_function(<span class="codekeyword">void</span>) {

  <span class="codekeyword">using</span> aoi::MyClass; <span class="codecomment">// You can use MyClass without the aoi:: for the rest of the function</span>

 

  MyClass my_object;

}

 

MyClass global_object; <span class="codecomment">// error: MyClass lives in namespace aoi and the using declaration was only

                       //   for the function's scope.</span>


A using directive is a lot like a using declaration, but it pulls everything from a given namespace into a scope.



<span class="codekeyword">namespace</span> aoi {

  <span class="codekeyword">class</span> MyClass {

    <span class="codecomment">// stuff</span>

  };

  <span class="codekeyword">void</span> my_function(<span class="codekeyword">void</span>);

}

 

<span class="codekeyword">using</span> <span class="codekeyword">namespace</span> aoi; <span class="codecomment">// using directive brings everything from aoi into the current scope</span>

                     <span class="codecomment">//   which is the global scope in this case</span>

 

<span class="codekeyword">void</span> some_other_function(<span class="codekeyword">void</span>) {

  MyClass my_object; <span class="codecomment">// neither of these need to use aoi:: to access the identifiers because</span>

  my_function();     <span class="codecomment">//   they are in a scope that has a using namespace aoi directive</span>

}


You can also use a using declaration in the global scope or a using directive in a function scope. What you can't do is put either in a class scope, as the using keyword means something different
inside a class definition. [4] You also can't declare a namespace inside a class.



<span class="codekeyword">struct</span> SomeStruct {

  <span class="codekeyword">using</span> aoi::MyClass;  <span class="codecomment">// illegal</span>

  <span class="codekeyword">using</span> <span class="codekeyword">namespace</span> aoi; <span class="codecomment">// also illegal</span>

  <span class="codekeyword">namespace</span> aoi {      <span class="codecomment">// this one too</span>

  }

 

  <span class="codekeyword">void</span> some_function(<span class="codekeyword">void</span>) {

    <span class="codekeyword">using</span> aoi::MyClass; <span class="codecomment">// perfectly legal, lasts for the rest of the function</span>

  }

};


One thing that is legal, but you shouldn't do, is put a using directive in a header file, as it can introduce subtle and hard to track down errors related to name lookups.


Also, when you don't explicitly put things inside a namespace, the identifier goes inside the global namespace, which you can access with operator:: with nothing before
the ::.



<span class="codekeyword">void</span> some_function(<span class="codekeyword">void</span>); <span class="codecomment">// this declares a function in the global namespace</span>

<span class="codekeyword">namespace</span> aoi {

  <span class="codekeyword">void</span> some_function(<span class="codekeyword">void</span>); <span class="codecomment">// this declares a different function with the same name in

                            //   namespace aoi.</span>

 

  <span class="codekeyword">void</span> some_other_function(<span class="codekeyword">void</span>) {

    some_function();      <span class="codecomment">// calls aoi::some_function()</span>

    aoi::some_function(); <span class="codecomment">// also calls aoi::some_funciton()</span>

    ::some_function();    <span class="codecomment">// calls the first some_function() in the global namespace</span>

  }

}


Also, even though you can't put a namespace in a class definition, you can put a namespace inside another namespace.



<span class="codekeyword">namespace</span> aoi {

  <span class="codekeyword">namespace</span> memory {

    <span class="codekeyword">class</span> SegmentManager;

  }

}

 

aoi::memory::SegmentManager   sm1; <span class="codecomment">// memory is nested inside aoi</span>

::aoi::memory::SegmentManager sm2; <span class="codecomment">// and aoi is nested inside the global namespace</span>

 

<span class="codekeyword">using</span> <span class="codekeyword">namespace</span> aoi;

memory::SegmentManager sm3;   <span class="codecomment">// still need the memory:: prefix</span>

<span class="codekeyword">using</span> memory::SegmentManager; <span class="codecomment">// since there's a using namespace aoi, don't need to

                              //   prefix aoi:: here </span>

SegmentManager sm4;           <span class="codecomment">// all good</span>


However, using directives or declarations can introduce ambiguity.



<span class="codekeyword">namespace</span> aoi {

  <span class="codekeyword">void</span> foo(<span class="codekeyword">void</span>);

}

<span class="codekeyword">namespace</span> jun {

  <span class="codekeyword">void</span> foo(<span class="codekeyword">void</span>);

}

<span class="codekeyword">using</span> aoi::foo;

<span class="codekeyword">using</span> jun::foo;

<span class="codekeyword">void</span> bar(<span class="codekeyword">void</span>) {

  foo(); <span class="codecomment">// error, doesn't know if this should be aoi::foo() or jun::foo()</span>

}


This, however, becomes reasonable with one small change:



<span class="codekeyword">namespace</span> aoi {

  <span class="codekeyword">void</span> foo(<span class="codekeyword">void</span>);

}

<span class="codekeyword">namespace</span> jun {

  <span class="codekeyword">void</span> foo(<span class="codekeyword">int</span>);

}

<span class="codekeyword">using</span> aoi::foo;

<span class="codekeyword">using</span> jun::foo;

<span class="codekeyword">void</span> bar(<span class="codekeyword">void</span>) {

  foo();  <span class="codecomment">// void aoi::foo(void);</span>

  foo(1); <span class="codecomment">// void jun::foo(int);</span>

}


Here, because the two functions have different signatures, the compiler can resolve the ambiguity, much in the same way it can resolve the ambiguity from normal operator overloading. All the same,
to prevent some subtle (and some not so subtle) errors, it's best to restrict using directives and declarations to the smallest needed scope.


Finally, preprocessor definitions don't respect namespace scoping (or any other scoping). Because macros work via text substitution before the code ever reaches the compiler, a macro defined
inside one namespace will still affect code outside that namespace with or without a using directive.



<span class="codekeyword">namespace</span> aoi {

  #define SILLY fred

}

 

<span class="codekeyword">int</span> SILLY = 0; <span class="codecomment">// creates a variable named fred, not SILLY</span>


This also means using declarations for macro names will probably not do what you expect, if it compiles at all.



Namespaces and the Standard Library

So why are namespaces important for using the standard library? Most components of the standard library live in the namespace std. The classic "Hello World" program often
looks like this:



#include <iostream>

 

<span class="codekeyword">int</span> main(<span class="codekeyword">int</span>, <span class="codekeyword">char</span> **) {

  std::cout << "Hello World!" << std::endl;

 

  <span class="codekeyword">return</span> 0;

}


Here cout and endl are parts of the standard library that live in namespace std. Of course, you can also use using
directives and using declarations with namespace std.



#include <iostream>

<span class="codekeyword">using</span> <span class="codekeyword">namespace</span> std;

 

<span class="codekeyword">int</span> main(<span class="codekeyword">int</span>, <span class="codekeyword">char</span> **) {

  cout << "Hello World!" << endl;

 

  <span class="codekeyword">return</span> 0;

}

 

#include <iostream>

 

<span class="codekeyword">int</span> main(<span class="codekeyword">int</span>, <span class="codekeyword">char</span> **) {

  <span class="codekeyword">using</span> std::cout;

  <span class="codekeyword">using</span> std::endl;

 

  cout << "Hello World!" << endl;

 

  <span class="codekeyword">return</span> 0;

}


Though, for "Hello World", it's less typing just to put the std:: in front of cout and endl.


One other thing to note is that a using directive, like using namespace std, will only bring in the parts of the namespace that have already been declared in the headers
included so far. For example, if you've only included <iostream> then using namespace std won't magically import the declarations from the
<vector> header [5].


Also, the guideline not to put a using directive in a header file goes double for the std namespace. Because almost everything in the standard library is in namespace std, and because the standard
library is so large, if you have using namespace std in a header, the opportunities for the aforementioned strange and subtle errors is nearly unbounded. In particular, some
older compilers have a hard time dealing with a using directive followed by more entries in to the namespace.



<span class="codecomment">// the moral equivalent of this may happen if you have a using directive in a header</span>

#include <iostream>

<span class="codekeyword">using</span> <span class="codekeyword">namespace</span> std;

#include <vector>

 

vector<int> int_vector; <span class="codecomment">// may not work properly</span>


Other important namespaces include std::tr1 and boost. std::tr1 is the namespace where the components specified in
Technical Report 1 have been placed in the few compilers that current support them. boost is the namespace used by the Boost C++ library which contains many implementations
of components specified in Technical Report 1. At this point in time it is more portable to use the boost namespace, but hopefully in the future, "code">std::tr1 will be more useful.



Templates

Templates are a C++ feature that allow you to write families of functions or types. One common example in game programming is the 3D vector class. For example, in one game, it might store vector
information as floats most of the time since they take up less memory. However, in one part of the physics engine, it needs additional accuracy for the computations so it
does everything with doubles. Without templates you might end up developing two vector classes and a lot of functions that were the same except for the type used.



<span class="codekeyword">struct</span> Vector3Float {

  <span class="codekeyword">float</span> x;

  <span class="codekeyword">float</span> y;

  <span class="codekeyword">float</span> z;

};

 

<span class="codekeyword">struct</span> Vector3Double {

  <span class="codekeyword">double</span> x;

  <span class="codekeyword">double</span> y;

  <span class="codekeyword">double</span> z;

};

 

<span class="codekeyword">float</span> dot_product(const Vector3Float & lhs, const Vector3Float & rhs) {

  <span class="codekeyword">return</span> lhs.x * rhs.x + lhs.y * rhs.y + lhs.z * rhs.z;

}

 

<span class="codekeyword">double</span> dot_product(const Vector3Double & lhs, const Vector3Double & rhs) {  

  <span class="codecomment">// exactly the same as the above except for the types it takes</span>

  <span class="codekeyword">return</span> lhs.x * rhs.x + lhs.y * rhs.y + lhs.z * rhs.z;

}


So instead of duplicating all that code for the different types, you can write class and function templates.



<span class="codekeyword">template</span> <typename T>

<span class="codekeyword">struct</span> Vector3 {

  T x;

  T y;

  T z;

};

 

<span class="codekeyword">template</span> <typename T> 

T dot_product(const Vector3<T> & lhs, const Vector3<T> & rhs) {

  <span class="codekeyword">return</span> lhs.x * rhs.x + lhs.y * rhs.y + lhs.z * rhs.z;

}


The first definition defines a class template Vector3<>. Vector3<> can be instantiated with different types. For
example, you can have a Vector3 of floats or a Vector3 of doubles. When you refer to a specific
template instantiation, you put the template arguments in angle brackets after the template class' name. For example Vector3<float> or "code">Vector3<double>. You can even have a Vector3<bool>, though that rarely makes sense, or a Vector3<long double>. The
second definition defines a function template dot_product<>(). This function takes Vector3<> arguments that depend on what
template argument the dot_product<>() function is instantiated with.



Vector3<float> a;

Vector3<float> b;

<span class="codekeyword">float</span> dot = dot_product<float>(a, b);


One convenient thing about function templates is that if the compiler can figure out what the template arguments should be from the function arguments, then you don't need to explicitly specify
the template argument for the function.



Vector3<float> a;

Vector3<float> b;

<span class="codekeyword">float</span> dot = dot_product(a, b); <span class="codecomment">// compiler can figure out this should be dot_product<float>()

                               //   by itself</span>


However, there are cases where the compiler can't figure out what the template arguments should be.



<span class="codekeyword">template</span> <typename T>

T multiply(T a, T b) {

  <span class="codekeyword">return</span> a * b;

}

 

multiply(5, 5);           <span class="codecomment">// good; compiler knows that it should be multiply<int>()</span>

multiply(5, 4.0);         <span class="codecomment">// confusion; compiler can't decide between multiply<int>()

                          //   and multiply<double>()</span>

multiply<double>(5, 4.0); <span class="codecomment">// good; explicit template argument</span>


When you declare a template type parameter you can use both the typename keyword and the class keyword. ["fnt6">6]



<span class="codekeyword">template</span> <typename T>

<span class="codekeyword">struct</span> Vector3 {

  T x;

  T y;

  T z;

};

 

<span class="codecomment">// means exactly the same thing</span>

<span class="codekeyword">template</span> <class T>

<span class="codekeyword">struct</span> Vector3 {

  T x;

  T y;

  T z;

};


Template arguments don't need to be primitives like float or double, they can also be class types, or even template instantiations.



<span class="codekeyword">class</span> Rational {

  <span class="codecomment">// implements rational numbers</span>

};

Rational <span class="codekeyword">operator</span>*(const Rational & lhs, const Rational & rhs) {

  <span class="codecomment">// stuff</span>

}

Rational <span class="codekeyword">operator</span>+(const Rational & lhs, const Rational & rhs) {

  <span class="codecomment">// stuff</span>

}

 

Vector3<Rational> a;                 <span class="codecomment">// a vector of rational numbers</span>

Rational dot_a = dot_product(a, a);  <span class="codecomment">// happily calculates the dot product in terms of Rationals</span>

 

Vector3<Vector3<float> > b;               <span class="codecomment">// I don't know what this would mean, but you can do it</span>

Vector3<float> dot_b = dot_product(b, b); <span class="codecomment">// but this will blow up since Vector3<float> doesn't </span>

                                          <span class="codecomment">//   define either binary operator * or operator+</span>

                                          <span class="codecomment">//   which are both used to calculate the dot product</span>


One note about syntax: when instantiating a template with a template instantiation, you should put a space between the angle brackets at the end of the declaration. In the above example, you need
a space between the > for the Vector3<float> and the closing > for the "code">Vector3<Vector3<float> >. If you leave the space in, the compiler will interpret the brackets as operator >> instead, which will make the
declaration illegal. [7]


A class template can have virtual functions and you can define member function templates for both class templates and normal classes. However, you cannot have a templated virtual function.



<span class="codekeyword">struct</span> BaseClass {

  <span class="codekeyword">virtual</span> <span class="codekeyword">void</span> update(<span class="codekeyword">void</span>);

};

 

<span class="codekeyword">template</span> <typename T>

<span class="codekeyword">struct</span> TemplateClass : BaseClass {

  <span class="codekeyword">virtual</span> <span class="codekeyword">void</span> update(<span class="codekeyword">void</span>); <span class="codecomment">// OK</span>

};

 

<span class="codekeyword">struct</span> NonTemplateClass {

  <span class="codekeyword">template</span> <typename T>

  <span class="codekeyword">void</span> twiddle(T t); <span class="codecomment">// OK</span>

 

  <span class="codekeyword">template</span> <typename T>

  <span class="codekeyword">virtual</span> <span class="codekeyword">void</span> twaddle(T t); <span class="codecomment">// Error</span>

};


Also, the compiler often can only do limited checking on the body of a class or function template until it is instantiated. With some compilers, the best they can do is detect unbalanced
parenthesis or brackets inside function definitions. For example, MSVC 7.1 will let this code compile unless you try to instantiate it:



<span class="codekeyword">template</span> <typename T>

T function(const T & a, const T & b) {

  <span class="codekeyword">return</span> a -- b; 

}



Dependent Names

Inside the definition of a template class or function, there are some identifiers that are called dependent names. Basically anything that depends on the template parameters is a dependent
name. So if the template parameter list looks like template <typename T, typename U> then T and U are dependent
names.



<span class="codekeyword">template</span> <typename T>

<span class="codekeyword">void</span> some_function(const T & t) {

  T temp = 0;            <span class="codecomment">// T is a dependent name, but so is temp</span>

  Vector3<T> vec;        <span class="codecomment">// Both Vector3<T> and vec are dependent names</span>

  temp += vec.x * vec.x; <span class="codecomment">// vec.x is a dependent name since it depends on vec </span>

  Vector3<float> fred;   <span class="codecomment">// no dependent names here</span>

  foo();                 <span class="codecomment">// nor here</span>

}


Names that refer to types are called dependent types. In the above example, T and Vector3<T> are dependent types. Other dependent
names are called type dependent expressions. temp, vecand vec.x are all type dependent expressions. In most cases,
it's easy for the compiler to determine if something should be a dependent type or a type dependent expression. However, there is one place where there is an ambiguity: if the :: operator is used on
a dependent type. In this case it could be either a nested type or typedef or it could be a static member variable. In this case, the compiler will assume that the name refers to a static member
variable unless you tell it that it should be a type name. This is done with the typename keyword. In this case, you cannot substitute the class
keyword.



<span class="codekeyword">template</span> <typename T>

<span class="codekeyword">void</span> function1(T t) {

  <span class="codekeyword">typename</span> T::some_type variable; <span class="codecomment">// T::some_type interpreted as a nested type</span>

  variable = T::some_value;       <span class="codecomment">// no typename keyword, T::some_value is interpreted as</span>

                                  <span class="codecomment">//   a static member variable</span>

}

 

<span class="codekeyword">template</span> <typename T>

<span class="codekeyword">struct</span> Vector3 {

  <span class="codecomment">// stuff</span>

  <span class="codekeyword">typedef</span> T member_type;

};

 

<span class="codekeyword">void</span> function2(<span class="codekeyword">void</span>) {

  Vector3<float>::member_type some_variable; <span class="codecomment">// no typename needed, not a template function</span>

}

 

<span class="codekeyword">template</span> <typename T> 

<span class="codekeyword">void</span> function3(<span class="codekeyword">void</span>) {

  Vector3<float>::member_type some_variable;             <span class="codecomment">// no typename needed, Vector3<float>

                                                         //   doesn't depend on T</span>

  Vector3<T>::member_type some_other_variable;           <span class="codecomment">// error: need typename because

                                                         //   Vector3<T> depends on T</span>

  <span class="codekeyword">typename</span> Vector3<T>::member_type yet_another_variable; <span class="codecomment">// good; typename keyword used</span>

}

 

<span class="codekeyword">template</span> <class T>

<span class="codekeyword">class</span> AnotherTemplateClass {

  Vector3<double>::member_type     some_variable;    <span class="codecomment">// good, Vector3<double> doesn't depend on T</span>

  <span class="codekeyword">typename</span> Vector3<T>::member_type another_variable; <span class="codecomment">// also good, typename used and Vector3<T>

                                                     //   depends on T</span>

};


The difference between dependent names and non-dependent names shows up in another different way: non-dependent names are looked up when the template is defined, and dependent names are looked up
when the template is instantiated.



<span class="codekeyword">void</span> foo(<span class="codekeyword">int</span> bar);

 

<span class="codekeyword">template</span> <typename T>

<span class="codekeyword">void</span> function(T t) {

  foo(t); <span class="codecomment">// not a dependent name so it always refers to the</span>

          <span class="codecomment">//   foo(int) above (assuming that no other foo()s</span>

          <span class="codecomment">//   have been defined previously)</span>

}

 

<span class="codekeyword">void</span> foo(<span class="codekeyword">double</span> bar);

 

<span class="codekeyword">void</span> other_function(<span class="codekeyword">void</span>) {

  foo(1);        <span class="codecomment">// calls foo(int)</span>

  foo(1.0);      <span class="codecomment">// calls foo(double)</span>

  function(1);   <span class="codecomment">// calls foo(int)</span>

  function(1.0); <span class="codecomment">// also calls foo(int)</span>

}


This rule was introduced so that code between the point of the template definition and the point of instantiation won't accidentally change the meaning of a template. However, it has one nasty
side effect: member function calls to base classes may not be looked up properly.



<span class="codekeyword">template</span> <typename T>

<span class="codekeyword">struct</span> A {

  <span class="codekeyword">void</span> foo(<span class="codekeyword">void</span>);

};

 

<span class="codekeyword">template</span> <typename T>

<span class="codekeyword">struct</span> B : A<T> {

  <span class="codekeyword">void</span> bar(<span class="codekeyword">void</span>) {

    foo(); <span class="codecomment">// may cause a compiler error</span>

  }

};


Inside B<T>::bar() foo() appears to be a non-dependent name, so it's looked up as a global function. If no global function is found, then
the compiler may generate an error. [8] In order to get the compiler to search for the name at the point of instantiation, when the base class will be
resolved, you need to get foo() to look like a dependent name. The easiest method is to replace the call to foo() with "code">this->foo(). Since the class is a instance of a class template, this is a dependent name, and thus so is this->foo().



Compilation

One other tricky detail about templates is that class templates and function templates are not actual classes or functions. Only specific instances are classes and functions. This means, for
example, you can't create a pointer to a function template. And because they aren't actual classes or functions, the compiler doesn't generate code for the class or function template, it only
generates code for the specific instantiations. This means that even though you can separate templates function declarations from their definitions, you usually can't put the definitions in a
separate source file.



<span class="codecomment">// header file</span>

<span class="codekeyword">template</span> <typename T>

<span class="codekeyword">struct</span> SomeClass {

  <span class="codekeyword">void</span> some_member_function(<span class="codekeyword">void</span>);

};

<span class="codecomment">//---------------------------------</span>

 

<span class="codecomment">// some_file.cpp</span>

SomeClass<int> s;

s.some_member_function();

<span class="codecomment">//---------------------------------</span>

 

<span class="codecomment">// some_other_file.cpp</span>

<span class="codekeyword">template</span> <typename T>

<span class="codekeyword">void</span> SomeClass<T>::some_member_function(<span class="codekeyword">void</span>) {

  <span class="codecomment">// do something</span>

}


This will most likely cause unresolved symbol linker errors. Basically the problem is that in some_file.cpp the compiler says it needs the definition for "code">SomeClass<int>::some_member_function(). However, in some_other_file.cpp when the function is defined, the compiler doesn't know it needs to create a
instantiation of that function for int. There are three ways to deal with the problem. The first way is to put the definition of the function in the header with the template
declaration, or in some other inline file that the header includes.



<span class="codecomment">// header file</span>

<span class="codekeyword">template</span> <typename T>

<span class="codekeyword">struct</span> SomeClass {

  <span class="codekeyword">void</span> some_member_function(<span class="codekeyword">void</span>);

};

 

#include "some_class.inl"

<span class="codecomment">//---------------------------------</span>

 

<span class="codecomment">// some_file.cpp</span>

SomeClass<int> s;

s.some_member_function();

<span class="codecomment">//---------------------------------</span>

 

<span class="codecomment">// some_class.inl</span>

<span class="codekeyword">template</span> <typename T>

<span class="codekeyword">void</span> SomeClass<T>::some_member_function(<span class="codekeyword">void</span>) {

  <span class="codecomment">// do something</span>

}


This allows the compiler to generate code for the function calls in much the same way that inline functions work. [9]


The second way is called explicit template instantiation. With this method, you keep the template function definitions in a separate source file, but then you tell the compiler which
template instantiations you need.



<span class="codecomment">// header file</span>

<span class="codekeyword">template</span> <typename T>

<span class="codekeyword">struct</span> SomeClass {

  <span class="codekeyword">void</span> some_member_function(<span class="codekeyword">void</span>);

};

<span class="codekeyword">template</span> <typename T>

T another_function(T t);

<span class="codecomment">//---------------------------------</span>

 

<span class="codecomment">// some_file.cpp</span>

SomeClass<int> s;

s.some_member_function();

another_function(1.0f);

<span class="codecomment">//---------------------------------</span>

 

<span class="codecomment">// some_other_file.cpp</span>

<span class="codekeyword">template</span> <typename T>

<span class="codekeyword">void</span> SomeClass<T>::some_member_function(<span class="codekeyword">void</span>) {

  <span class="codecomment">// do something</span>

}

<span class="codekeyword">template</span> <typename T>

T another_function(T t) {

  <span class="codekeyword">return</span> t + t;

}

<span class="codekeyword">template</span> SomeClass<int>; <span class="codecomment">// explicit template instantiation for a class</span>

<span class="codekeyword">template</span> <span class="codekeyword">float</span> another_function<float>(<span class="codekeyword">float</span>); <span class=

"codecomment">// for a function</span>


Of course this means that every time a different template instantiation is require you'll need to modify the source file with the definitions in it.


The third way is to use the export keyword. Unfortunately, the export keyword is implemented in very few compilers, so chances are you won't
have the opportunity to use it. [10]



Templates and the Standard Library

Templates are important to the standard library since the vast majority of the C++ standard library consists of class and function templates. For a simple example, take "code">std::swap<>(). std::swap<>() is a function template who's job is to swap the value of two objects. One implementation of "code">std::swap<>() looks like:



<span class="codekeyword">template</span> <typename T>

<span class="codekeyword">void</span> swap(T & a, T & b) {

  T temp = a;

  a = b;

  b = temp;

}


Also, some parts of the standard library that look like non-templated classes are actually typedefs for specific instantiations of class templates. For example, "code">std::string is actually a typedef for std::basic_string<char>.


One interesting side effect of this is that it means that most of the source code of the standard library is available to you in the headers. Usually it's hard to read, but most of it is there for
you to see how things are implemented.



Exceptions

One problem in programming is how to signal and handle error conditions. One method is to use return values of functions to signal errors. However, one problem with this is that if the code
calling the function doesn't know how to handle the error, it needs to propagate the error somewhere else. Another problem is that there are some places that error codes can't be used. Constructors,
for instance, have no return value. To address these issues, C++ has exceptions. [11]


Exceptions are one of the many topics in C++ that are at the same time both simple and hideously complicated. The concept itself is fairly simple. Instead of returning an error code when something
goes wrong, you can instead throw an exception. The syntax to do so is correspondingly simple.



<span class="codekeyword">void</span> * ptr = some_function_returning_a_pointer();

<span class="codekeyword">if</span> (!ptr) <span class="codekeyword">throw</span> SomeExceptionType("Out of memory");


This causes the function to stop execution and start destroying everything on the stack until it finds something that can handle the exception.



<span class="codekeyword">try</span> {

  function_that_had_the_previous_code();

} <span class="codekeyword">catch</span> (const SomeExceptionType & ex) {

  std::cerr << ex.what() << std::endl;

}


This code essentially says: I'm about to execute code that might throw an exception (the try block). If an exception is thrown, then I'll handle exceptions that I know
about, in this case SomeExceptionType. If I get an exception that I know how to deal with, execute the code in the catch block.


You can throw almost any C++ type, like character literals, integers, or class types. This is one of the instances in C++ that you shouldn't take advantage of the flexibility given to you.
Throwing character literals, integers, floating point numbers or other primitive types is bad practice. When throwing exceptions you should throw exceptions of class types, and throw them by
value.



<span class="codekeyword">throw</span> SomeExceptionType("Some Error String");          <span class="codecomment">// good</span>

SomeExceptionType stack_variable("Some Error String");

<span class="codekeyword">throw</span> &stack_variable;                                 <span class="codecomment">// bad; throwing local variable address</span>

<span class="codekeyword">throw</span> <span class="codekeyword">new</span> SomeExceptionType("Some Error String");      <span class="codecomment">// bad; throwing newly allocated object</span>

<span class="codekeyword">throw</span> "Some Error String";                             <span class="codecomment">// bad; throwing a string literal</span>


When you catch an exception you should catch by reference. [12]



<span class="codekeyword">catch</span> (SomeExceptionType & e) <span class="codecomment">// good</span>

<span class="codekeyword">catch</span> (SomeExceptionType e)   <span class="codecomment">// bad;  catching by value</span>


It's also possible to have multiple catch blocks for different exception types and it's possible to have an catch block that will catch any exceptions thrown in the
try block.



<span class="codekeyword">try</span> {

  <span class="codecomment">// some code that might throw exceptions</span>

} <span class="codekeyword">catch</span>(SomeExceptionType & e) {

  <span class="codecomment">// handles exceptions of type SomeExceptionType</span>

} <span class="codekeyword">catch</span>(...) {

  <span class="codecomment">// handles any other exceptions</span>

}


The catch blocks are tried in order. So having catch(...) before any other catch block makes the other catch blocks pointless. If you catch
multiple types of exceptions then the exception types should come in the order of most derived exceptions before the more general exceptions.



<span class="codekeyword">class</span> DerivedType : <span class="codekeyword">public</span> BaseType {

  <span class="codecomment">// stuff</span>

};

 

<span class="codecomment">// good</span>

<span class="codekeyword">try</span> {

} <span class="codekeyword">catch</span> (DerivedType & e) {

} <span class="codekeyword">catch</span> (BaseType & e) {

} <span class="codekeyword">catch</span> (...) {

}

 

<span class="codecomment">// bad</span>

<span class="codekeyword">try</span> {

} <span class="codekeyword">catch</span> (BaseType & e) {

} <span class="codekeyword">catch</span> (DerivedType & e) {   <span class="codecomment">// will never catch anything since BaseType handler will

                              //   handle DerivedTypes too</span>

} <span class="codekeyword">catch</span> (...) {

} <span class="codekeyword">catch</span> (SomeOtherType & e) { <span class="codecomment">// will never catch anything since (...) traps all exceptions</span>

}


Of course, knowing how to write a catch block is not very useful unless you know what to put in the catch block. In general, one of two things
will be true. Either you don't know how to handle the exception, but you need to clean up resource or you have an idea what the problem is and how to handle it. In the second case you'll generally be
the one who threw the exception, so you know how best to deal with it. For example, if you throw an out of memory condition, you might disable optional features and try to re-run the operation. (But
see set_new_handler() later in this series.) But first, let's see what I mean by cleaning up resources.


So when an exception occurs, the application goes into a meltdown mode. First, it takes the exception thrown, and copies the exception into a safe area. Then the stack unwinds, which means that
everything on the stack is destroyed in the reverse order of their creation.



<span class="codekeyword">void</span> function_that_throws(<span class="codekeyword">void</span>) {

  SomeObject obj1;

  <span class="codekeyword">throw</span> MyException("Whoops.");

}

 

<span class="codekeyword">void</span> function_with_try(<span class="codekeyword">void</span>) {

  SomeObject obj2;

  <span class="codekeyword">try</span> {

    SomeObject obj3;

    SomeObject * obj4 = <span class="codekeyword">new</span> SomeObject();

    function_that_throws();

    SomeObject obj5;

  } <span class="codekeyword">catch</span> (MyException & e) {

    std::cerr << e.what() << std::endl;

  }

}


In the above code, when the exception is thrown, obj1 is destroyed, then obj3 is destroyed. obj5 hasn't been created
yet, so will not be destroyed. The object pointed to by obj4 will not be destroyed since it is not on the stack. obj2 won't be destroyed because it
is outside the try/catch blocks. It would be destroyed if, instead of a MyException, some other exception was thrown, since the catch block
wouldn't handle that.


In any case, this code demonstrates a memory leak. The object pointed to by obj4 is not deleted, and there's no way to get at the object since all pointers to it are lost
when the exception is thrown. So one way to write non-leaking code when you dynamically allocate something via new is to do something like:



SomeObject * obj = <span class="codekeyword">new</span> SomeObject();

<span class="codekeyword">try</span> {

  <span class="codecomment">// do stuff that might throw an exception</span>

  <span class="codekeyword">delete</span> obj;

} <span class="codekeyword">catch</span> (...) {

  <span class="codekeyword">delete</span> obj;

  <span class="codekeyword">throw</span>;

}

<span class="codecomment">// done with obj, continue doing stuff</span>


There are some things to note about this code. The first thing is that in the catch(...) block, there's a throw all by itself. This rethrows the
same object that was caught by the catch block. In this case, I've handled the exception by cleaning up the obj pointer, and I don't know how to actually deal with this
error, so I'm going to punt and hope that some enclosing catch block knows how to deal with things. The other thing to notice is that this is really ugly code.


Keep in mind that destructors of objects are called when the stack is unwound. So if we instead had a class that held the pointer instead of just a normal pointer, and the class destroyed the
pointer automatically, we wouldn't need the try/catch blocks. The standard library does supply such a class, called "code">std::auto_ptr<>.



std::auto_ptr<SomeObject> obj(<span class="codekeyword">new</span> SomeObject());

<span class="codecomment">// do stuff that might throw an exception</span>

obj->some_function();

obj.reset();


This code creates a new SomeObject and gives ownership of the object to a std::auto_ptr<SomeObject>. If there's an exception, the
auto_ptr will have it's destructor called, which in turn will call the delete on the pointer it was given. You can use operator -> on the
auto_ptr to get at the members of the object just like a normal pointer, and the auto_ptr has member functions of its own like "code">reset(), which deletes the object held by the auto_ptr. std::auto_ptr<> and classes like it are called smart pointers; they act
like pointers, but have a little more intelligence built in.


However, as smart pointers go, std::auto_ptr<> isn't very smart because all it can do is call delete. For example, you can't use it to hold dynamic arrays allocated
with operator new[], because you should use operator delete[] instead of operator delete with dynamic arrays. Instead, of
trying to use std::auto_ptr<> with dynamic arrays, you should use a std::vector<> (which I cover in the next article). You also can't
use std::auto_ptr<> with something like the FILE * returned by C file I/O function fopen(), since you need to call
fclose() and not delete. In this case, the C++ standard library has the classes, std::fstream, std::ofstream and
std::ifstream. I'll cover all these classes in more detail later, but the general concept embodied by all these classes are the same: an object acquires a resource when it
is created, and handles releasing the resource when it is destroyed. This technique is referred to resource acquisition is initialization or RAII. RAII is a very useful technique in C++ and not just
for exception safety reasons.


You can also specify a function will not throw an exception. [13]



<span class="codecomment">// will not throw any exception</span>

<span class="codekeyword">void</span> function(<span class="codekeyword">void</span>) <span class="codekeyword">throw</span>() {

  <span class="codecomment">// stuff</span>

}


Generally, however, you will only want to do this if you are trying to implement a function or interface that requires a no-throw function, such as some custom allocator functions.


Exceptions are the primary method the C++ standard library uses to signal error conditions and deal with error conditions from your code, and the C++ language itself will throw exceptions in
various situations. As such the standard library includes a set of standard exceptions. The <exception> header defines the exceptions "code">std::exception, which is the base class for all exceptions in the standard library, and std::bad_exception, which is an exception class used with exception
specifications. The <typeinfo> header defines std::bad_cast, which is thrown if a dynamic_cast on reference types
fails, and std::bad_typeid which is thrown if a typeid operation fails (such as when passed a null pointer). The "code"><new> header contains std::bad_alloc which is thrown if operator new or operator new[] fails.


Finally, <stdexcept> defines a number of exception classes, some of which are thrown by standard library classes or functions.



  std::logic_error

    std::domain_error

    std::invalid_argument

    std::length_error

    std::out_of_range

  std::runtime_error

    std::range_error

    std::overflow_error

    std::underflow_error


Generally, it's good practice to derive your own exception classes from the standard library exception classes, and in particular from one of the classes in "code"><stdexcept>. std::logic_error and its children std::domain_error, std::invalid_argument, "code">std::length_error and std::out_of_range are used for errors on the part of the programmer. For example, supplying an index that is out of the range of valid
indices. Often these situations are instead handled by assertions. However, they can be useful, for example, when interfacing with scripting languages. std::runtime_error
and its children, std::range_error, std::overflow_error and std::underflow_error are useful when dealing with potential
problems that are not necessarily the result of programmer error.



Closing and References

Templates and exceptions are both topics that deserve much more room than I've allocated in this article. For more details on templates, you may wish to consult "http://www.gamedev.net/columns/books/bookdetails.asp?productid=17">The C++ Programming Language, 3rd Edition by Bjarne Stroustrup or "http://www.gamedev.net/columns/books/bookdetails.asp?productid=367">C++ Templates - The Complete Guide by David Vandevoorde and Nicolai Josuttis. Also, the "http://www.parashift.com/c++-faq-lite/templates.html">C++ FAQ Lite contains many useful insights into specific issues in template programming.


For more details on exceptions, you may want to consult again The C++ Programming Language, 3rd Edition by Bjarne
Stroustrup, and especially the hard cover version of the book which has an additional section on exception handling in the end. Other good books for learning about exception handling include "http://www.gamedev.net/columns/books/bookdetails.asp?productid=249">Exceptional C++ and More Exceptional C+ by
Herb Sutter, and C++ Gotchas by Steven Dewhurst. Again, the "http://www.parashift.com/c++-faq-lite/exceptions.html">C++ FAQ Lite covers many common issues about exception handling.


There are a few details missing from my coverage about namespaces, which again can be found in The C++ Programming
Language, 3rd Edition
by Bjarne Stroustrup.


General references for the standard library as a whole include yet again, The C++ Programming Language, 3rd Edition
by Bjarne Stroustrup and also The C++ Standard Library by Nicolai Josuttis and of course the actual text of the C++
Standard: ISO/IEC 14882:2003, which can be found either as hardcover as The C++ Standard: Incorporating Technical Corrigendum No. 1 from Wiley or from your national standards body. For
example, for the United States, it can be found both printed and for electronic download (for a fee) from ANSI. [14] You can visit the C++ Standard
Committee's website here. In particular you can download draft copies
of the C++ Standard
there, which, while they are not up to date, are free. This includes the TR1 paper. Generally
speaking the differences between the draft and final versions of the papers are minor.


Also, I will also be referring to the Boost project quite a bit as well.


If you are interested in the pre-standards history of C++ (including much of what makes up the modern standard library) consider reading "http://www.gamedev.net/columns/books/bookdetails.asp?productid=496">The Design and Evolution of C++ by Bjarne Stroustrup, or The Annotated C++ Reference Manual by Margaret Ellis and
Bjarne Stroustrup.


A different approach to introducing the standard library, and the C++ language as a whole, is taken by the book "http://www.gamedev.net/columns/books/bookdetails.asp?productid=193">Accelerated C++ by Andrew Koenig and Barbara Moo. If the approach taken in this article series doesn't work for you, you may
want to try reading that book.


In the next article I'll cover one of the more useful of the standard library classes: std::vector.




1) If you aren't that comfortable with header files you may wish to read this
article
.


2) To be pedantic, Technical Report 1 is non-normative, so compiler vendors are not under any obligation to provide the library features detailed in
Technical Report 1.


3) This is called Koenig lookup.


4) However, you can use using directives and declarations in a class member function's implementation.


5) Unless, for some bizarre reason, your compiler's <iostream> header directly or indirectly includes "code"><vector>.


6) Many people use the convention of using typename when the template argument can be any type including primitives, and using
class when the template argument must be a class. An exception is that template-template parameters require the class keyword. However,
template-template parameters are outside the scope of this article as the C++ Standard Library does not use them.


7) This is something that will probably change in the next version of the C++ Standard.


8) Not compilers will. However, the ones that don't tend to be older compilers that look up all names at the point on instantiation.


9) It also generates the same headaches for the linker that inline functions do.


10) Also, the export keyword doesn't work like you might expect it would as it doesn't allow for true seperate compilation of
templates. For more details see these articles: "Export" Restrictions, Part 1 and "http://www.gotw.ca/publications/mill24.htm">"Export" Restrictions, Part 2.


11) And you can't get away from them. The language itself will throw exceptions in many cases. For example, if memory allocation fails in a "code">new expression, an exception will be thrown. If a dynamic_cast to a reference type fails an exception will be thrown.


12) Catching by value can lead to problems such as slicing, where you lose information about the exception being caught. Another issue is that sometimes
catching by value may invoke a copy constructor that itself may throw an exception. Throwing an exception while doing exception handling is a bad thing.


13) Actually, you can also specify that a function will only throw certain exceptions.



<span class="codecomment">// will only throw SomeException and SomeOtherException</span>

<span class="codekeyword">void</span> function1(<span class="codekeyword">void</span>) <span class="codekeyword">throw</span>(SomeException, SomeOtherException) {

  <span class="codecomment">// stuff</span>

}


Exception specifications were introduced with the hope that it would allow certain optimizations. However, the way that exception specifications were defined in the standard generally makes them
per






Comments

Note: Please offer only positive, constructive comments - we are looking to promote a positive atmosphere where collaboration is valued above all else.




PARTNERS