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, such as "expected expression" or
"no match for operator<".

\eigenAutoToc


\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.triangularView</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.triangularView</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.triangularView</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
triangularView</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 constructs <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 construct <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 construct, 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

*/
}
