namespace Eigen {

/** \page TopicTemplateKeyword The template and typename keywords in C++

There are two uses for the \c template and \c typename keywords in C++. One of them is fairly well known
amongst programmers: to define templates. The other use is more obscure: to specify that an expression refers
to a template function or a type. This regularly trips up programmers that use the %Eigen library, often
leading to error messages from the compiler that are difficult to understand.

<b>Table of contents</b>
  - \ref TopicTemplateKeywordToDefineTemplates
  - \ref TopicTemplateKeywordExample
  - \ref TopicTemplateKeywordExplanation
  - \ref TopicTemplateKeywordResources


\section TopicTemplateKeywordToDefineTemplates Using the template and typename keywords to define templates

The \c template and \c typename keywords are routinely used to define templates. This is not the topic of this
page as we assume that the reader is aware of this (otherwise consult a C++ book). The following example
should illustrate this use of the \c template keyword.

\code
template <typename T>
bool isPositive(T x)
{
    return x > 0;
}
\endcode

We could just as well have written <tt>template &lt;class T&gt;</tt>; the keywords \c typename and \c class have the
same meaning in this context.


\section TopicTemplateKeywordExample An example showing the second use of the template keyword

Let us illustrate the second use of the \c template keyword with an example. Suppose we want to write a
function which copies all entries in the upper triangular part of a matrix into another matrix, while keeping
the lower triangular part unchanged. A straightforward implementation would be as follows:

<table class="example">
<tr><th>Example:</th><th>Output:</th></tr>
<tr><td>
\include TemplateKeyword_simple.cpp
</td>
<td>
\verbinclude TemplateKeyword_simple.out
</td></tr></table>

That works fine, but it is not very flexible. First, it only works with dynamic-size matrices of
single-precision floats; the function \c copyUpperTriangularPart() does not accept static-size matrices or
matrices with double-precision numbers. Second, if you use an expression such as
<tt>mat.topLeftCorner(3,3)</tt> as the parameter \c src, then this is copied into a temporary variable of type
MatrixXf; this copy can be avoided.

As explained in \ref TopicFunctionTakingEigenTypes, both issues can be resolved by making 
\c copyUpperTriangularPart() accept any object of type MatrixBase. This leads to the following code:

<table class="example">
<tr><th>Example:</th><th>Output:</th></tr>
<tr><td>
\include TemplateKeyword_flexible.cpp
</td>
<td>
\verbinclude TemplateKeyword_flexible.out
</td></tr></table>

The one line in the body of the function \c copyUpperTriangularPart() shows the second, more obscure use of
the \c template keyword in C++.  Even though it may look strange, the \c template keywords are necessary
according to the standard. Without it, the compiler may reject the code with an error message like "no match
for operator<".


\section TopicTemplateKeywordExplanation Explanation

The reason that the \c template keyword is necessary in the last example has to do with the rules for how
templates are supposed to be compiled in C++. The compiler has to check the code for correct syntax at the
point where the template is defined, without knowing the actual value of the template arguments (\c Derived1
and \c Derived2 in the example). That means that the compiler cannot know that <tt>dst.triangularPart</tt> is
a member template and that the following &lt; symbol is part of the delimiter for the template
parameter. Another possibility would be that <tt>dst.triangularPart</tt> is a member variable with the &lt;
symbol refering to the <tt>operator&lt;()</tt> function. In fact, the compiler should choose the second
possibility, according to the standard. If <tt>dst.triangularPart</tt> is a member template (as in our case),
the programmer should specify this explicitly with the \c template keyword and write <tt>dst.template
triangularPart</tt>.

The precise rules are rather complicated, but ignoring some subtleties we can summarize them as follows:
- A <em>dependent name</em> is name that depends (directly or indirectly) on a template parameter. In the
  example, \c dst is a dependent name because it is of type <tt>MatrixBase&lt;Derived1&gt;</tt> which depends
  on the template parameter \c Derived1.
- If the code contains either one of the contructions <tt>xxx.yyy</tt> or <tt>xxx-&gt;yyy</tt> and \c xxx is a
  dependent name and \c yyy refers to a member template, then the \c template keyword must be used before 
  \c yyy, leading to <tt>xxx.template yyy</tt> or <tt>xxx-&gt;template yyy</tt>.
- If the code contains the contruction <tt>xxx::yyy</tt> and \c xxx is a dependent name and \c yyy refers to a
  member typedef, then the \c typename keyword must be used before the whole construction, leading to
  <tt>typename xxx::yyy</tt>.

As an example where the \c typename keyword is required, consider the following code in \ref TutorialSparse
for iterating over the non-zero entries of a sparse matrix type:

\code
SparseMatrixType mat(rows,cols);
for (int k=0; k<mat.outerSize(); ++k)
  for (SparseMatrixType::InnerIterator it(mat,k); it; ++it)
  {
    /* ... */
  }
\endcode

If \c SparseMatrixType depends on a template parameter, then the \c typename keyword is required:

\code
template <typename T>
void iterateOverSparseMatrix(const SparseMatrix<T>& mat;
{
  for (int k=0; k<m1.outerSize(); ++k)
    for (typename SparseMatrix<T>::InnerIterator it(mat,k); it; ++it)
    {
      /* ... */
    }
}
\endcode


\section TopicTemplateKeywordResources Resources for further reading

For more information and a fuller explanation of this topic, the reader may consult the following sources:
- The book "C++ Template Metaprogramming" by David Abrahams and Aleksey Gurtovoy contains a very good
  explanation in Appendix B ("The typename and template Keywords") which formed the basis for this page.
- http://pages.cs.wisc.edu/~driscoll/typename.html
- http://www.parashift.com/c++-faq-lite/templates.html#faq-35.18
- http://www.comeaucomputing.com/techtalk/templates/#templateprefix
- http://www.comeaucomputing.com/techtalk/templates/#typename

*/
}
