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 \code SparseMatrixType mat(rows,cols); -for (int k=0; k::InnerIterator it(vec); it; ++it) +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. + +Table of contents + - \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 +bool isPositive(T x) +{ + return x > 0; +} +\endcode + +We could just as well have written template <class T>; 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: + + + + +
Example:Output:
+\include TemplateKeyword_simple.cpp + +\verbinclude TemplateKeyword_simple.out +
+ +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 +mat.topLeftCorner(3,3) 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: + + + + +
Example:Output:
+\include TemplateKeyword_flexible.cpp + +\verbinclude TemplateKeyword_flexible.out +
+ +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 dst.triangularPart is +a member template and that the following < symbol is part of the delimiter for the template +parameter. Another possibility would be that dst.triangularPart is a member variable with the < +symbol refering to the operator<() function. In fact, the compiler should choose the second +possibility, according to the standard. If dst.triangularPart is a member template (as in our case), +the programmer should specify this explicitly with the \c template keyword and write dst.template +triangularPart. + +The precise rules are rather complicated, but ignoring some subtleties we can summarize them as follows: +- A dependent name 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 MatrixBase<Derived1> which depends + on the template parameter \c Derived1. +- If the code contains either one of the contructions xxx.yyy or xxx->yyy 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 xxx.template yyy or xxx->template yyy. +- If the code contains the contruction xxx::yyy 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 + typename xxx::yyy. + +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 +void iterateOverSparseMatrix(const SparseMatrix& mat; +{ + for (int k=0; k::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 - Topics related to alignment issues - \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. +
OperationCode
@@ -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. +
OperationCode
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 +#include + +using namespace Eigen; + +template +void copyUpperTriangularPart(MatrixBase& dst, const MatrixBase& src) +{ + /* Note the 'template' keywords in the following line! */ + dst.template triangularView() = src.template triangularView(); +} + +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 +#include + +using namespace Eigen; + +void copyUpperTriangularPart(MatrixXf& dst, const MatrixXf& src) +{ + dst.triangularView() = src.triangularView(); +} + +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; +}