aboutsummaryrefslogtreecommitdiffhomepage
path: root/doc
diff options
context:
space:
mode:
authorGravatar Jitse Niesen <jitse@maths.leeds.ac.uk>2011-09-10 09:18:18 +0100
committerGravatar Jitse Niesen <jitse@maths.leeds.ac.uk>2011-09-10 09:18:18 +0100
commit59b83c14fd2bec0b8c8afa7a2fa0357af7f0f827 (patch)
tree122dbf8cc5fe742070911a11bdc108db17510bbb /doc
parent3e7aaadb1dcd0500a4a874f4036bd3489b3b8dd0 (diff)
Write page on template and typename keywords in C++.
After yet another question on the forum, I decided to write something on this common issue. Now we just need to link to this and get people to read it. Thanks to mattb on the forum for some links. Caveat: IANALL (I am not a language lawyer).
Diffstat (limited to 'doc')
-rw-r--r--doc/C09_TutorialSparse.dox5
-rw-r--r--doc/I16_TemplateKeyword.dox136
-rw-r--r--doc/Overview.dox1
-rw-r--r--doc/QuickReference.dox6
-rw-r--r--doc/examples/TemplateKeyword_flexible.cpp22
-rw-r--r--doc/examples/TemplateKeyword_simple.cpp20
6 files changed, 189 insertions, 1 deletions
diff --git a/doc/C09_TutorialSparse.dox b/doc/C09_TutorialSparse.dox
index 5d9050a85..37ec79ed6 100644
--- a/doc/C09_TutorialSparse.dox
+++ b/doc/C09_TutorialSparse.dox
@@ -110,7 +110,7 @@ Iterating over the coefficients of a sparse matrix can be done only in the same
<tr><td>
\code
SparseMatrixType mat(rows,cols);
-for (int k=0; k<m1.outerSize(); ++k)
+for (int k=0; k<mat.outerSize(); ++k)
for (SparseMatrixType::InnerIterator it(mat,k); it; ++it)
{
it.value();
@@ -131,6 +131,9 @@ for (SparseVector<double>::InnerIterator it(vec); it; ++it)
</td></tr>
</table>
+If the type of the sparse matrix or vector depends on a template parameter, then the \c typename keyword is
+required to indicate that \c InnerIterator denotes a type; see \ref TopicTemplateKeyword for details.
+
\section TutorialSparseFilling Filling a sparse matrix
diff --git a/doc/I16_TemplateKeyword.dox b/doc/I16_TemplateKeyword.dox
new file mode 100644
index 000000000..324532310
--- /dev/null
+++ b/doc/I16_TemplateKeyword.dox
@@ -0,0 +1,136 @@
+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
+
+*/
+}
diff --git a/doc/Overview.dox b/doc/Overview.dox
index 04bc075f0..f1eb77956 100644
--- a/doc/Overview.dox
+++ b/doc/Overview.dox
@@ -39,6 +39,7 @@ For a first contact with Eigen, the best place is to have a look at the \ref Get
- \ref TopicWritingEfficientProductExpression
- \ref TopicClassHierarchy
- \ref TopicFunctionTakingEigenTypes
+ - \ref TopicTemplateKeyword
- <b>Topics related to alignment issues</b>
- \ref TopicUnalignedArrayAssert
- \ref TopicFixedSizeVectorizable
diff --git a/doc/QuickReference.dox b/doc/QuickReference.dox
index a578d15a6..68845772d 100644
--- a/doc/QuickReference.dox
+++ b/doc/QuickReference.dox
@@ -586,6 +586,9 @@ mat3 = mat1 * diag1.inverse()
TriangularView gives a view on a triangular part of a dense matrix and allows to perform optimized operations on it. The opposite triangular part is never referenced and can be used to store other information.
+\note The .triangularView() template member function requires the \c template keyword if it is used on an
+object of a type that depends on a template parameter; see \ref TopicTemplateKeyword for details.
+
<table class="example">
<tr><th>Operation</th><th>Code</th></tr>
<tr><td>
@@ -630,6 +633,9 @@ Just as for triangular matrix, you can reference any triangular part of a square
matrix and perform special and optimized operations. Again the opposite triangular part is never referenced and can be
used to store other information.
+\note The .selfadjointView() template member function requires the \c template keyword if it is used on an
+object of a type that depends on a template parameter; see \ref TopicTemplateKeyword for details.
+
<table class="example">
<tr><th>Operation</th><th>Code</th></tr>
<tr><td>
diff --git a/doc/examples/TemplateKeyword_flexible.cpp b/doc/examples/TemplateKeyword_flexible.cpp
new file mode 100644
index 000000000..9d85292dd
--- /dev/null
+++ b/doc/examples/TemplateKeyword_flexible.cpp
@@ -0,0 +1,22 @@
+#include <Eigen/Dense>
+#include <iostream>
+
+using namespace Eigen;
+
+template <typename Derived1, typename Derived2>
+void copyUpperTriangularPart(MatrixBase<Derived1>& dst, const MatrixBase<Derived2>& src)
+{
+ /* Note the 'template' keywords in the following line! */
+ dst.template triangularView<Upper>() = src.template triangularView<Upper>();
+}
+
+int main()
+{
+ MatrixXi m1 = MatrixXi::Ones(5,5);
+ MatrixXi m2 = MatrixXi::Random(4,4);
+ std::cout << "m2 before copy:" << std::endl;
+ std::cout << m2 << std::endl << std::endl;
+ copyUpperTriangularPart(m2, m1.topLeftCorner(4,4));
+ std::cout << "m2 after copy:" << std::endl;
+ std::cout << m2 << std::endl << std::endl;
+}
diff --git a/doc/examples/TemplateKeyword_simple.cpp b/doc/examples/TemplateKeyword_simple.cpp
new file mode 100644
index 000000000..6998c1769
--- /dev/null
+++ b/doc/examples/TemplateKeyword_simple.cpp
@@ -0,0 +1,20 @@
+#include <Eigen/Dense>
+#include <iostream>
+
+using namespace Eigen;
+
+void copyUpperTriangularPart(MatrixXf& dst, const MatrixXf& src)
+{
+ dst.triangularView<Upper>() = src.triangularView<Upper>();
+}
+
+int main()
+{
+ MatrixXf m1 = MatrixXf::Ones(4,4);
+ MatrixXf m2 = MatrixXf::Random(4,4);
+ std::cout << "m2 before copy:" << std::endl;
+ std::cout << m2 << std::endl << std::endl;
+ copyUpperTriangularPart(m2, m1);
+ std::cout << "m2 after copy:" << std::endl;
+ std::cout << m2 << std::endl << std::endl;
+}