C++ for Scientists - Technische Universität Dresden
C++ for Scientists - Technische Universität Dresden
C++ for Scientists - Technische Universität Dresden
You also want an ePaper? Increase the reach of your titles
YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.
146 CHAPTER 5. META-PROGRAMMING<br />
trans_const.cpp:96: Error: Invalid application of ≫sizeof≪ on incomplete type<br />
≫boost::STATIC_ASSERTION_FAILURE≪<br />
If you see an error message with “STATIC ASSERTION” in it, do not think about the message<br />
itself (it is meaningless) but look at the source code line that caused this error and hope that<br />
the author of the assertion will provide more in<strong>for</strong>mation in a comment.<br />
When we try to compile our test with the assertion we will see that trans(A) compiles but<br />
not trans(B). The reason is that ‘const dense2D’ is considered different from ‘dense2D’ in<br />
template specialization so that it is still considered non-matrix. The good new is that we do not<br />
need to double our specializations <strong>for</strong> mutable and constant types but we can write a partial<br />
specialization <strong>for</strong> all constant arguments:<br />
template <br />
struct is matrix<br />
: is matrix {};<br />
Note that BOOST STATIC ASSERT is a macro and does not understand C ++. This manifests in<br />
particular if the argument contains one or more commas. Than the preprocessor will interpret<br />
this as multiple arguments <strong>for</strong> the macro and get confused. This confusion can be avoided<br />
by enclosing the argument of BOOST STATIC ASSERT with two enclosing parentheses as we did<br />
in the example (although it was not necessary here). Despite the double parentheses and the<br />
rather arbitrary error message, static assertions are very useful to increase reliabily. The next<br />
C ++ standard will provide static assertions in the language like:<br />
template <br />
class transposed view<br />
{<br />
static assert(is matrix::value, ”transposed view requires a matrix as argument”);<br />
// ...<br />
};<br />
As the reader can see, the integration into the language overcomes the be<strong>for</strong>e-mentioned deficiencies<br />
of the macro implementation.<br />
Useful are meta-functions to remove something from a type if exists, e.g. remove const trans<strong>for</strong>ms<br />
const T into T and non-constant types remain unchanged. Note that this only removes the<br />
constancy of entire types not that of template arguments, e.g., in vector the constancy<br />
of the arguments is not removed.<br />
Dually, meta-functions can add something to a type:<br />
typedef typename boost::add reference::type ref type;<br />
It would be shorter to just add an & but this is easily overseen in longer type definitions. More<br />
importantly, if some trait returns already a reference then it is an error to add another one. The<br />
meta-function adds the reference only to types that are no references yet. To adding const to a<br />
type we find it more concise without the meta-function:<br />
typedef typename some trait::type const const type;<br />
If the type trait returns already a constant type, the second const will be ignored.<br />
The widest functionality in the area of meta-programming provides the Boost Meta-Programming<br />
Library (MPL) [GA04]. The library implements most of the STL algorithms (§ 4.9) and also