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 referring 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

*/
}
