forked from boostorg/preprocessor
lib cleanup
[SVN r15700]
This commit is contained in:
@ -1,43 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<link rel="stylesheet" type="text/css" href="../../../boost.css">
|
||||
<title>Boost.Preprocessor - Acknowledgements</title>
|
||||
</head>
|
||||
<body link="#0000ff" vlink="#800080">
|
||||
<table border="0" cellpadding="7" cellspacing="0" width="100%" summary=
|
||||
"header">
|
||||
<tr>
|
||||
<td valign="top" width="300">
|
||||
<h3><a href="../../../index.htm"><img height="86" width="277" alt="C++ Boost" src="../../../c++boost.gif" border="0"></a></h3>
|
||||
</td>
|
||||
<td valign="top">
|
||||
<h1 align="center">Boost.Preprocessor</h1>
|
||||
<h2 align="center">Acknowledgements</h2>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr>
|
||||
<p>The original idea of passing two extra parameters to REPEAT, which makes it
|
||||
possible to create preprocessor code on top of it, was due to Aleksey Gurtovoy.
|
||||
The invokeable IDENTITY macro was also invented by him. He also suggested the
|
||||
name for the library. Many thanks to Aleksey for his insights!</p>
|
||||
<p>Thanks to everyone who participated in the review: David Abrahams, Beman Dawes,
|
||||
Ronald Garcia, Douglas Gregor, Aleksey Gurtovoy, Jeremy Siek, and Daryle Walker.</p>
|
||||
<p>Thanks to Chris Little and Mat Marcus for providing help with MWCW.</p>
|
||||
<p>The original automatic recursion technique, which makes many of the library
|
||||
primitives easier to use, was invented by Paul Mensonides.</p>
|
||||
<p>The PREPROCESSOR library has been developed by Vesa Karvonen. </p>
|
||||
<hr>
|
||||
<p>Revised
|
||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
|
||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
||||
</p>
|
||||
<p><i>© Copyright <a href="http://www.housemarque.com">Housemarque Oy</a> 2002</i></p>
|
||||
|
||||
<p>Permission to copy, use, modify, sell and distribute this document is granted
|
||||
provided this copyright notice appears in all copies. This document is provided
|
||||
"as is" without express or implied warranty, and with no claim as to its suitability
|
||||
for any purpose.</p>
|
||||
</body>
|
||||
</html>
|
@ -1,48 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<link rel="stylesheet" type="text/css" href="../../../boost.css">
|
||||
<title>Boost.Preprocessor - Bibliography</title>
|
||||
</head>
|
||||
<body link="#0000ff" vlink="#800080">
|
||||
<table border="0" cellpadding="7" cellspacing="0" width="100%" summary=
|
||||
"header">
|
||||
<tr>
|
||||
<td valign="top" width="300">
|
||||
<h3><a href="../../../index.htm"><img height="86" width="277" alt="C++ Boost" src="../../../c++boost.gif" border="0"></a></h3>
|
||||
</td>
|
||||
<td valign="top">
|
||||
<h1 align="center">Boost.Preprocessor</h1>
|
||||
<h2 align="center">Bibliography</h2>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<hr>
|
||||
|
||||
<table>
|
||||
<tr><td><b>[Stroustrup]</b></td><td><a name="[Stroustrup]">Stroustrup: <i>The Design and Evolution of C++</i>, ISBN 0201543303</a></td></tr>
|
||||
<tr><td><b>[Czarnecki]</b></td><td><a name="[Czarnecki]">Czarnecki, Eisenecker: <i>Generative Programming</i>, ISBN 0201309777</a></td></tr>
|
||||
<tr><td><b>[Barton]</b></td><td><a name="[Barton]">Barton, Nackman: <i>Scientific and Engineering C++</i>, ISBN 0201533936</a></td></tr>
|
||||
<tr><td><b>[McConnell]</b></td><td><a name="[McConnell]">McConnell: <i>Code Complete</i>, ISBN 1556154844</a></td></tr>
|
||||
<tr><td><b>[Std]</b></td><td><a name="[Std]">ISO/IEC 14882:1998 <i>Programming languages - C++</i></a></td></tr>
|
||||
<tr><td><b>[Thompson]</b></td><td><a name="[Thompson]">Thompson: <i>Haskell: The Craft of Functional Programming</i>, ISBN 0201342758</a></td></tr>
|
||||
<tr><td><b>[Okasaki]</b></td><td><a name="[Okasaki]">Okasaki: <i>Purely Functional Data Structures</i>, ISBN 0521663504</a></td></tr>
|
||||
<tr><td><b>[Cousineau]</b></td><td><a name="[Cousineau]">Cousineau, Mauny: <i>The Functional Approach to Programming</i>, ISBN 0521576814</a></td></tr>
|
||||
<tr><td><b>[Abelson]</b></td><td><a name="[Abelson]">Abelson, Sussman, Sussman: <i>Structure and Interpretation of Computer Programs</i>, ISBN 0262011530</a></td></tr>
|
||||
</table>
|
||||
|
||||
<hr>
|
||||
|
||||
<p>Revised
|
||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
|
||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
||||
</p>
|
||||
<p><i>© Copyright <a href="http://www.housemarque.com">Housemarque Oy</a> 2002</i></p>
|
||||
|
||||
<p>Permission to copy, use, modify, sell and distribute this document is granted
|
||||
provided this copyright notice appears in all copies. This document is provided
|
||||
"as is" without express or implied warranty, and with no claim as to its suitability
|
||||
for any purpose.</p>
|
||||
</body>
|
||||
</html>
|
@ -1,91 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<link rel="stylesheet" type="text/css" href="../../../boost.css">
|
||||
<title>Boost.Preprocessor - Bibliography</title>
|
||||
</head>
|
||||
<body link="#0000ff" vlink="#800080">
|
||||
<table border="0" cellpadding="7" cellspacing="0" width="100%" summary=
|
||||
"header">
|
||||
<tr>
|
||||
<td valign="top" width="300">
|
||||
<h3><a href="../../../index.htm"><img height="86" width="277" alt="C++ Boost" src="../../../c++boost.gif" border="0"></a></h3>
|
||||
</td>
|
||||
<td valign="top">
|
||||
<h1 align="center">Boost.Preprocessor</h1>
|
||||
<h2 align="center">Examples</h2>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<hr>
|
||||
|
||||
<table>
|
||||
<tr><td><a href="../example/array_arithmetic.c">array_arithmetic.c</a></td><td>Implements over 2200 functions for 1-dimensional arithmetic
|
||||
array manipulation in C. The idea is to use preprocessor data structures,
|
||||
lists and tuples, for storing metainformation to be used for generating
|
||||
the actual C code.</td></tr>
|
||||
<tr>
|
||||
<td><a href="../example/catch_builtin.cpp">catch_builtin.cpp</a></td>
|
||||
<td>Demonstrates the usage of lists and BOOST_PP_LIST_FOR_EACH().</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="../example/count_down.c">count_down.c</a></td>
|
||||
<td> Trivial example of using BOOST_PP_WHILE() that simply counts
|
||||
down from N to 0 ultimately expanding to a 0.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="../example/delay.c">delay.c</a></td>
|
||||
<td>Implements a macro whose expansion takes exponential amount
|
||||
of time.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="../example/duffs_device.c">duffs_device.c</a></td>
|
||||
<td>Uses the preprocessor library to implement a generalized
|
||||
macro for implementing a Duff's Device.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="../example/is_integral.cpp">is_integral.cpp</a></td>
|
||||
<td>Demonstrates the usage of preprocessor lists for generating
|
||||
C++ code.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="../example/linear_fib.c">linear_fib.c</a></td>
|
||||
<td>Shows how BOOST_PP_WHILE() can be used for implementing macros.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="../example/note.c">note.c</a></td>
|
||||
<td>Shows how BOOST_PP_STRINGIZE() can be used to allow macro
|
||||
expansion before stringization.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="../example/repeat_2d.c">repeat_2d.c</a></td>
|
||||
<td>Implements a generalized macro for 2D repetition using the
|
||||
simple repetition primitives of the preprocessor library.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="../example/static_assert.c">static_assert.c</a></td>
|
||||
<td>Shows how BOOST_PP_CAT() can be used to allow macro expansion
|
||||
before token concatenation.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="../example/subscript_layer.cpp">subscript_layer.cpp</a></td>
|
||||
<td>Shows how BOOST_PP_EMPTY can be used as an unused or empty
|
||||
parameter.</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<hr>
|
||||
|
||||
<p>Revised
|
||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
|
||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
||||
</p>
|
||||
<p><i>© Copyright <a href="http://www.housemarque.com">Housemarque Oy</a> 2002</i></p>
|
||||
|
||||
<p>Permission to copy, use, modify, sell and distribute this document is granted
|
||||
provided this copyright notice appears in all copies. This document is provided
|
||||
"as is" without express or implied warranty, and with no claim as to its suitability
|
||||
for any purpose.</p>
|
||||
</body>
|
||||
</html>
|
@ -1,326 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<link rel="stylesheet" type="text/css" href="../../../boost.css">
|
||||
<title>Boost.Preprocessor - Tutorial examples preprocessed</title>
|
||||
</head>
|
||||
<body link="#0000ff" vlink="#800080">
|
||||
<table border="0" cellpadding="7" cellspacing="0" width="100%" summary=
|
||||
"header">
|
||||
<tr>
|
||||
<td valign="top" width="300">
|
||||
<h3><a href="../../../index.htm"><img height="86" width="277" alt="C++ Boost" src="../../../c++boost.gif" border="0"></a></h3>
|
||||
</td>
|
||||
<td valign="top">
|
||||
<h1 align="center">Boost.Preprocessor</h1>
|
||||
<h2 align="center">Tutorial examples preprocessed</h2>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr>
|
||||
|
||||
<p>The following code snippets were produced by actually preprocessing the code
|
||||
snippets of the tutorial. After preprocessing the code was reformatted manually.</p>
|
||||
|
||||
<hr>
|
||||
<p><strong><a name="Local Macro"></a><a href="tutorial.htm#Local Macro">EXAMPLE</a>:</strong>
|
||||
Use a Local Macro to avoid small scale repetition</p>
|
||||
|
||||
<pre>template<class T, int n>
|
||||
vec<T,n>&
|
||||
operator +=
|
||||
( vec<T,n>&
|
||||
lhs
|
||||
, const vec<T,n>&
|
||||
rhs
|
||||
)
|
||||
{ for (int i=0; i<n; ++i)
|
||||
lhs(i) += rhs(i);
|
||||
return lhs;
|
||||
}
|
||||
|
||||
template<class T, int n>
|
||||
vec<T,n>&
|
||||
operator -=
|
||||
( vec<T,n>&
|
||||
lhs
|
||||
, const vec<T,n>&
|
||||
rhs
|
||||
)
|
||||
{ for (int i=0; i<n; ++i)
|
||||
lhs(i) -= rhs(i);
|
||||
return lhs;
|
||||
}
|
||||
|
||||
template<class T, int n>
|
||||
vec<T,n>&
|
||||
operator *=
|
||||
( vec<T,n>&
|
||||
lhs
|
||||
, const vec<T,n>&
|
||||
rhs
|
||||
)
|
||||
{ for (int i=0; i<n; ++i)
|
||||
lhs(i) *= rhs(i);
|
||||
return lhs;
|
||||
}
|
||||
|
||||
template<class T, int n>
|
||||
vec<T,n>&
|
||||
operator /=
|
||||
( vec<T,n>&
|
||||
lhs
|
||||
, const vec<T,n>&
|
||||
rhs
|
||||
)
|
||||
{ for (int i=0; i<n; ++i)
|
||||
lhs(i) /= rhs(i);
|
||||
return lhs;
|
||||
}
|
||||
</pre>
|
||||
|
||||
<hr>
|
||||
<p><strong><a name="UNUSED"></a><a href="tutorial.htm#UNUSED">EXAMPLE</a>:</strong>
|
||||
Use BOOST_PP_EMPTY() as an unused parameter in Local Macro instantiations</p>
|
||||
|
||||
<pre>template<class base>
|
||||
typename implement_subscript_using_begin_subscript<base>::value_type&
|
||||
implement_subscript_using_begin_subscript<base>::operator[]
|
||||
( index_type
|
||||
i
|
||||
)
|
||||
{ return base::begin()[i];
|
||||
}
|
||||
|
||||
template<class base>
|
||||
const typename implement_subscript_using_begin_subscript<base>::value_type&
|
||||
implement_subscript_using_begin_subscript<base>::operator[]
|
||||
( index_type
|
||||
i
|
||||
) const
|
||||
{ return base::begin()[i];
|
||||
}
|
||||
</pre>
|
||||
|
||||
<hr>
|
||||
<p><b><a name="CAT"></a><a href="tutorial.htm#CAT">EXAMPLE:</a></b> Use BOOST_PP_CAT instead of ## when necessary</p>
|
||||
|
||||
<pre>enum
|
||||
{ static_check_152 = (sizeof(int) <= sizeof(long)) ? 1 : -1
|
||||
};
|
||||
typedef char
|
||||
static_assert_152
|
||||
[ static_check_152
|
||||
];
|
||||
</pre>
|
||||
<hr>
|
||||
<p><b><a name="STRINGIZE"></a><a href="tutorial.htm#STRINGIZE">EXAMPLE:</a></b> Use BOOST_PP_STRINGIZE instead of # whenever necessary</p>
|
||||
<pre>#pragma message("examples.cpp" "(" "20" ") : " "TBD!")</pre>
|
||||
<hr>
|
||||
<p><strong><a name="ENUM_PARAMS"></a><a href="tutorial.htm#ENUM_PARAMS">EXAMPLE</a>:</strong>
|
||||
Use:</p>
|
||||
<ul>
|
||||
<li> BOOST_PP_ENUM_PARAMS,</li>
|
||||
<li> BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT,</li>
|
||||
<li> BOOST_PP_ENUM_PARAMS_WITH_DEFAULTS,</li>
|
||||
<li> BOOST_PP_ENUM_SHIFTED_PARAMS, or</li>
|
||||
<li>BOOST_PP_REPEAT, and</li>
|
||||
<li> BOOST_PP_COMMA_IF</li>
|
||||
</ul>
|
||||
<p>to avoid O(N) repetition on lists in general</p>
|
||||
<pre>struct make_type_list_end;
|
||||
|
||||
template
|
||||
< class T0=make_type_list_end
|
||||
, class T1=make_type_list_end
|
||||
, class T2=make_type_list_end
|
||||
, class T3=make_type_list_end
|
||||
, class T4=make_type_list_end
|
||||
, class T5=make_type_list_end
|
||||
, class T6=make_type_list_end
|
||||
, class T7=make_type_list_end
|
||||
>
|
||||
struct make_type_list
|
||||
{
|
||||
private:
|
||||
enum
|
||||
{ end = is_same<T0,make_type_list_end>::value
|
||||
};
|
||||
public:
|
||||
typedef typename
|
||||
type_if
|
||||
< end
|
||||
, type_cons_empty
|
||||
, type_cons
|
||||
< T0
|
||||
, typename
|
||||
type_inner_if
|
||||
< end
|
||||
, type_identity<end>
|
||||
, make_type_list
|
||||
< T1
|
||||
, T2
|
||||
, T3
|
||||
, T4
|
||||
, T5
|
||||
, T6
|
||||
, T7
|
||||
>
|
||||
>::type
|
||||
>
|
||||
>::type type;
|
||||
};
|
||||
</pre>
|
||||
|
||||
<hr>
|
||||
<p><strong><a name="Token Look-Up"></a><a href="tutorial.htm#Token Look-Up">EXAMPLE</a>:</strong>
|
||||
Use BOOST_PP_REPEAT and a Token Look-Up Function to eliminate categorical
|
||||
repetition</p>
|
||||
|
||||
<pre>catch (bool t)
|
||||
{ report_typeid(t);
|
||||
report_value(t);
|
||||
}
|
||||
catch (char t)
|
||||
{ report_typeid(t);
|
||||
report_value(t);
|
||||
}
|
||||
catch (signed char t)
|
||||
{ report_typeid(t);
|
||||
report_value(t);
|
||||
}
|
||||
catch (unsigned char t)
|
||||
{ report_typeid(t);
|
||||
report_value(t);
|
||||
}
|
||||
catch (short t)
|
||||
{ report_typeid(t);
|
||||
report_value(t);
|
||||
}
|
||||
catch (unsigned short t)
|
||||
{ report_typeid(t);
|
||||
report_value(t);
|
||||
}
|
||||
catch (int t)
|
||||
{ report_typeid(t);
|
||||
report_value(t);
|
||||
}
|
||||
catch (unsigned int t)
|
||||
{ report_typeid(t);
|
||||
report_value(t);
|
||||
}
|
||||
catch (long t)
|
||||
{ report_typeid(t);
|
||||
report_value(t);
|
||||
}
|
||||
catch (unsigned long t)
|
||||
{ report_typeid(t);
|
||||
report_value(t);
|
||||
}
|
||||
catch (float t)
|
||||
{ report_typeid(t);
|
||||
report_value(t);
|
||||
}
|
||||
catch (double t)
|
||||
{ report_typeid(t);
|
||||
report_value(t);
|
||||
}
|
||||
catch (long double t)
|
||||
{ report_typeid(t);
|
||||
report_value(t);
|
||||
}
|
||||
</pre>
|
||||
|
||||
<hr>
|
||||
<p><strong><a name="2ND_REPEAT"></a><a href="tutorial.htm#2ND_REPEAT">EXAMPLE</a>:</strong>
|
||||
Use BOOST_PP_REPEAT_2ND to avoid O(N*N) repetition</p>
|
||||
|
||||
<pre>vec()
|
||||
{
|
||||
}
|
||||
vec(T a0)
|
||||
{ (*this)[0] = a0;
|
||||
}
|
||||
vec(T a0, T a1)
|
||||
{ (*this)[0] = a0;
|
||||
(*this)[1] = a1;
|
||||
}
|
||||
vec(T a0, T a1, T a2)
|
||||
{ (*this)[0] = a0;
|
||||
(*this)[1] = a1;
|
||||
(*this)[2] = a2;
|
||||
}
|
||||
vec(T a0, T a1, T a2, T a3)
|
||||
{ (*this)[0] = a0;
|
||||
(*this)[1] = a1;
|
||||
(*this)[2] = a2;
|
||||
(*this)[3] = a3;
|
||||
}
|
||||
vec(T a0, T a1, T a2, T a3, T a4)
|
||||
{ (*this)[0] = a0;
|
||||
(*this)[1] = a1;
|
||||
(*this)[2] = a2;
|
||||
(*this)[3] = a3;
|
||||
(*this)[4] = a4;
|
||||
}
|
||||
vec(T a0, T a1, T a2, T a3, T a4, T a5)
|
||||
{ (*this)[0] = a0;
|
||||
(*this)[1] = a1;
|
||||
(*this)[2] = a2;
|
||||
(*this)[3] = a3;
|
||||
(*this)[4] = a4;
|
||||
(*this)[5] = a5;
|
||||
}
|
||||
vec(T a0, T a1, T a2, T a3, T a4, T a5, T a6)
|
||||
{ (*this)[0] = a0;
|
||||
(*this)[1] = a1;
|
||||
(*this)[2] = a2;
|
||||
(*this)[3] = a3;
|
||||
(*this)[4] = a4;
|
||||
(*this)[5] = a5;
|
||||
(*this)[6] = a6;
|
||||
}
|
||||
vec(T a0, T a1, T a2, T a3, T a4, T a5, T a6, T a7)
|
||||
{ (*this)[0] = a0;
|
||||
(*this)[1] = a1;
|
||||
(*this)[2] = a2;
|
||||
(*this)[3] = a3;
|
||||
(*this)[4] = a4;
|
||||
(*this)[5] = a5;
|
||||
(*this)[6] = a6;
|
||||
(*this)[7] = a7;
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
<hr>
|
||||
<p><a name="IF"></a><a href="tutorial.htm#IF"><b>EXAMPLE:</b></a>
|
||||
Use BOOST_PP_IF to implement special case for the first element</p>
|
||||
|
||||
<pre>false == false;
|
||||
true == true;
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
<hr>
|
||||
|
||||
<p><a name="Arithmetic"></a><a href="tutorial.htm#Arithmetic"><B>EXAMPLE:</B></a> Use arithmetic, logical and comparison operations when necessary</p>
|
||||
|
||||
<pre>S, E0, E1
|
||||
E0, S, E1
|
||||
E0, E1, S
|
||||
BAD PARAMS FOR SPECIAL_NUMBERED_LIST! E0, E1, E2, S</pre>
|
||||
|
||||
<hr>
|
||||
<p>Revised
|
||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
|
||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
||||
</p>
|
||||
<p><i>© Copyright <a href="http://www.housemarque.com">Housemarque Oy</a> 2002</i></p>
|
||||
|
||||
<p>Permission to copy, use, modify, sell and distribute this document is granted
|
||||
provided this copyright notice appears in all copies. This document is provided
|
||||
"as is" without express or implied warranty, and with no claim as to its suitability
|
||||
for any purpose.</p>
|
||||
</body>
|
||||
</html>
|
@ -1,48 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<link rel="stylesheet" type="text/css" href="../../../boost.css">
|
||||
<title>Boost.Preprocessor - Index</title>
|
||||
</head>
|
||||
<body link="#0000ff" vlink="#800080">
|
||||
<table border="0" cellpadding="7" cellspacing="0" width="100%" summary=
|
||||
"header">
|
||||
<tr>
|
||||
<td valign="top" width="300">
|
||||
<h3><a href="../../../index.htm"><img height="86" width="277" alt="C++ Boost" src="../../../c++boost.gif" border="0"></a></h3>
|
||||
</td>
|
||||
<td valign="top">
|
||||
<h1 align="center">Boost.Preprocessor</h1>
|
||||
<h2 align="center">Index</h2>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<hr>
|
||||
|
||||
<h2>Contents</h2>
|
||||
<dl class="index">
|
||||
<dt><a href="tutorial.htm">Tutorial</a></dt>
|
||||
<dt><a href="examples.htm">Examples</a></dt>
|
||||
<dt><a href="reference/index.htm">Reference</a></dt>
|
||||
<dt><a href="known_problems_with_cpp.htm">Widely known problems with the C preprocessor</a></dt>
|
||||
<dt><a href="keywords.txt">Keywords for syntax highlighting</a></dt>
|
||||
<dt><a href="problems_with_compilers.htm">Known problems with specific compilers</a></dt>
|
||||
<dt><a href="bibliography.htm">Bibliography</a></dt>
|
||||
<dt><a href="acknowledgements.htm">Acknowledgements</a></dt>
|
||||
</dl>
|
||||
|
||||
<hr>
|
||||
|
||||
<p>Revised
|
||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan --><!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
||||
</p>
|
||||
|
||||
<p><i>© Copyright <a href="http://www.housemarque.com">Housemarque Oy</a> 2002</i></p>
|
||||
|
||||
<p>Permission to copy, use, modify, sell and distribute this document is granted
|
||||
provided this copyright notice appears in all copies. This document is provided
|
||||
"as is" without express or implied warranty, and with no claim as to its suitability
|
||||
for any purpose.</p>
|
||||
</body>
|
||||
</html>
|
@ -1,99 +0,0 @@
|
||||
BOOST_PP_ADD
|
||||
BOOST_PP_ADD_D
|
||||
BOOST_PP_AND
|
||||
BOOST_PP_ASSERT_MSG
|
||||
BOOST_PP_BOOL
|
||||
BOOST_PP_CAT
|
||||
BOOST_PP_COMMA
|
||||
BOOST_PP_COMMA_IF
|
||||
BOOST_PP_DEC
|
||||
BOOST_PP_DIV
|
||||
BOOST_PP_DIV_D
|
||||
BOOST_PP_EMPTY
|
||||
BOOST_PP_ENUM
|
||||
BOOST_PP_ENUM_PARAMS
|
||||
BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT
|
||||
BOOST_PP_ENUM_PARAMS_WITH_DEFAULTS
|
||||
BOOST_PP_ENUM_SHIFTED
|
||||
BOOST_PP_ENUM_SHIFTED_PARAMS
|
||||
BOOST_PP_EQUAL
|
||||
BOOST_PP_EQUAL_D
|
||||
BOOST_PP_EXPAND
|
||||
BOOST_PP_EXPR_IF
|
||||
BOOST_PP_FOR
|
||||
BOOST_PP_GREATER
|
||||
BOOST_PP_GREATER_D
|
||||
BOOST_PP_GREATER_EQUAL
|
||||
BOOST_PP_GREATER_EQUAL_D
|
||||
BOOST_PP_IDENTITY
|
||||
BOOST_PP_IF
|
||||
BOOST_PP_INC
|
||||
BOOST_PP_LESS
|
||||
BOOST_PP_LESS_D
|
||||
BOOST_PP_LESS_EQUAL
|
||||
BOOST_PP_LESS_EQUAL_D
|
||||
BOOST_PP_LIMIT_DIM
|
||||
BOOST_PP_LIMIT_MAG
|
||||
BOOST_PP_LIMIT_TUPLE
|
||||
BOOST_PP_LIST_APPEND
|
||||
BOOST_PP_LIST_APPEND_D
|
||||
BOOST_PP_LIST_AT
|
||||
BOOST_PP_LIST_AT_D
|
||||
BOOST_PP_LIST_CAT
|
||||
BOOST_PP_LIST_CAT_D
|
||||
BOOST_PP_LIST_CONS
|
||||
BOOST_PP_LIST_ENUM
|
||||
BOOST_PP_LIST_ENUM_R
|
||||
BOOST_PP_LIST_FILTER
|
||||
BOOST_PP_LIST_FILTER_D
|
||||
BOOST_PP_LIST_FIRST
|
||||
BOOST_PP_LIST_FIRST_N
|
||||
BOOST_PP_LIST_FIRST_N_D
|
||||
BOOST_PP_LIST_FOLD_LEFT
|
||||
BOOST_PP_LIST_FOLD_LEFT_D
|
||||
BOOST_PP_LIST_FOLD_RIGHT
|
||||
BOOST_PP_LIST_FOLD_RIGHT_D
|
||||
BOOST_PP_LIST_FOR_EACH
|
||||
BOOST_PP_LIST_FOR_EACH_I
|
||||
BOOST_PP_LIST_FOR_EACH_I_R
|
||||
BOOST_PP_LIST_FOR_EACH_R
|
||||
BOOST_PP_LIST_FOR_EACH_PRODUCT
|
||||
BOOST_PP_LIST_FOR_EACH_PRODUCT_R
|
||||
BOOST_PP_LIST_IS_CONS
|
||||
BOOST_PP_LIST_IS_NIL
|
||||
BOOST_PP_LIST_NIL
|
||||
BOOST_PP_LIST_REST
|
||||
BOOST_PP_LIST_REST_N
|
||||
BOOST_PP_LIST_REST_N_D
|
||||
BOOST_PP_LIST_REVERSE
|
||||
BOOST_PP_LIST_REVERSE_D
|
||||
BOOST_PP_LIST_SIZE
|
||||
BOOST_PP_LIST_SIZE_D
|
||||
BOOST_PP_LIST_TO_TUPLE
|
||||
BOOST_PP_LIST_TO_TUPLE_R
|
||||
BOOST_PP_LIST_TRANSFORM
|
||||
BOOST_PP_LIST_TRANSFORM_D
|
||||
BOOST_PP_MAX
|
||||
BOOST_PP_MAX_D
|
||||
BOOST_PP_MIN
|
||||
BOOST_PP_MIN_D
|
||||
BOOST_PP_MOD
|
||||
BOOST_PP_MOD_D
|
||||
BOOST_PP_MUL
|
||||
BOOST_PP_MUL_D
|
||||
BOOST_PP_NOR
|
||||
BOOST_PP_NOT
|
||||
BOOST_PP_NOT_EQUAL
|
||||
BOOST_PP_NOT_EQUAL_D
|
||||
BOOST_PP_OR
|
||||
BOOST_PP_REPEAT
|
||||
BOOST_PP_REPEAT_FROM_TO
|
||||
BOOST_PP_STRINGIZE
|
||||
BOOST_PP_SUB
|
||||
BOOST_PP_SUB_D
|
||||
BOOST_PP_TUPLE_EAT
|
||||
BOOST_PP_TUPLE_ELEM
|
||||
BOOST_PP_TUPLE_REVERSE
|
||||
BOOST_PP_TUPLE_TO_LIST
|
||||
BOOST_PP_WHILE
|
||||
BOOST_PP_XOR
|
@ -1,125 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<link rel="stylesheet" type="text/css" href="../../../boost.css">
|
||||
<title>Boost.Preprocessor - Widely known problems with the C preprocessor</title>
|
||||
</head>
|
||||
<body link="#0000ff" vlink="#800080">
|
||||
<table border="0" cellpadding="7" cellspacing="0" width="100%" summary=
|
||||
"header">
|
||||
<tr>
|
||||
<td valign="top" width="300">
|
||||
<h3><a href="../../../index.htm"><img height="86" width="277" alt="C++ Boost" src="../../../c++boost.gif" border="0"></a></h3>
|
||||
</td>
|
||||
<td valign="top">
|
||||
<h1 align="center">Boost.Preprocessor</h1>
|
||||
<h2 align="center">Widely known problems with the C preprocessor</h2>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<hr>
|
||||
|
||||
<p>Preprocessor metaprogramming is subject to heated discussions. Part of this is caused by
|
||||
bad experiences with dangerous techniques, such as defining inline functions using macros. As a rule
|
||||
of thumb, if you can find a clean and
|
||||
manageable way to do something without using the preprocessor, then
|
||||
you should do it that way.</p>
|
||||
|
||||
<p>Let's survey some of the widely known problems with the preprocessor in a problem/solution
|
||||
format.</p>
|
||||
<HR>
|
||||
|
||||
<p><B>PROBLEM:</B> Preprocessor does not
|
||||
respect scope, therefore macros can accidentally and sometimes silently replace
|
||||
code.</p>
|
||||
|
||||
<p><B>SOLUTION A:</B> Use all caps identifiers
|
||||
for macros and only macros. This practically eliminates the possibility that a
|
||||
macro might replace other kind of code accidentally.</p>
|
||||
|
||||
<p><B>SOLUTION B:</B> Use the Local Macro
|
||||
idiom:</p>
|
||||
|
||||
<pre>#define MACRO ...
|
||||
// Use MACRO
|
||||
#undef MACRO
|
||||
</pre>
|
||||
|
||||
<p>This makes sure that a macro can not accidentally
|
||||
replace code outside of the scope of the local macro.</p>
|
||||
<P>A problem with this solution is that the #undef can not be automated and may be
|
||||
forgotten. Experienced programmers generally write the #undef either immediately
|
||||
before (in time) or immediately after writing the macro definition.</P>
|
||||
<P><B>SOLUTION C:</B> Use the Unique Macro Prefix idiom:</P>
|
||||
|
||||
<pre>#define UMP_MACRO
|
||||
// Use UMP_MACRO
|
||||
</pre>
|
||||
|
||||
|
||||
<P>This makes accidental substitution and collisions highly
|
||||
unlikely. Problems with this solution:</P>
|
||||
<UL>
|
||||
<LI>
|
||||
There can still be naming collisions inside a large project.
|
||||
<LI>
|
||||
Macros still pollute the global namespace. </LI></UL>
|
||||
<P><EM><B>By combining all solutions, whenever
|
||||
possible, the scope problem can be largely avoided.</B></EM></P>
|
||||
<HR>
|
||||
|
||||
<P><B>PROBLEM:</B> Preprocessor code is difficult to read.
|
||||
It requires understanding the basic process of how
|
||||
the preprocessor recursively expands macros, finding the macro definition and mentally
|
||||
substituting the parameters of the macro. </P>
|
||||
<P><B>SOLUTION:</B> Any kind of programming requires basic understanding
|
||||
of how the code is executed. Any parameterization technique, including simple
|
||||
functions and templates requires finding the definition and mentally substituting
|
||||
parameters. </P>
|
||||
<P>However, it is good to know a few techniques:</P>
|
||||
<UL>
|
||||
<LI>
|
||||
By using as many Local Macros as reasonable, the bulk of the searching
|
||||
process can be eliminated.
|
||||
<LI>
|
||||
Code browsers and text search tools make it easier to find the
|
||||
definitions.
|
||||
<LI>
|
||||
The compiler can be used for generating the preprocessed source code in
|
||||
order to look for bugs.
|
||||
<LI>
|
||||
Before turning something into a preprocessor metaprogram, first
|
||||
implement a small scale version of it without preprocessor. Then work
|
||||
bottom->up replacing hand written constructs by using preprocessor. This
|
||||
way you can test the code incrementally. Experienced programmers often skip
|
||||
many stages, but if something proves too complex to write directly, it is
|
||||
always possible to fall back to incremental methods.
|
||||
<LI>
|
||||
If you insert a special symbol into the preprocessor code in places where
|
||||
there should be a line break, you can make code readable after preprocessing
|
||||
simply by using a search and replace tool. </LI></UL>
|
||||
<P><B><EM> An especially important thing to remember is to limit the use of preprocessor
|
||||
to the structured, well understood and safe methods. Structure helps to understand
|
||||
complex systems <A href="bibliography.htm#[McConnell]">[McConnell]</A>.</EM></B></P>
|
||||
<HR>
|
||||
|
||||
<P><B>PROBLEM:</B> "I'd
|
||||
like to see Cpp abolished." - Bjarne Stroustrup in <A href="bibliography.htm#[Stroustrup]">[Stroustrup]</A></P>
|
||||
<P><B>SOLUTION:</B> The C preprocessor will be here for a
|
||||
long time.</P>
|
||||
<P><EM><B>In practice, preprocessor metaprogramming is far simpler and more portable
|
||||
than template metaprogramming <A href="bibliography.htm#[Czarnecki]">[Czarnecki]</A>.</B></EM></P>
|
||||
<hr>
|
||||
<p>Revised
|
||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
|
||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
||||
</p>
|
||||
<p><i>© Copyright <a href="http://www.housemarque.com">Housemarque Oy</a> 2002</i></p>
|
||||
|
||||
<p>Permission to copy, use, modify, sell and distribute this document is granted
|
||||
provided this copyright notice appears in all copies. This document is provided
|
||||
"as is" without express or implied warranty, and with no claim as to its suitability
|
||||
for any purpose.</p>
|
||||
</body>
|
||||
</html>
|
@ -1,138 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<link rel="stylesheet" type="text/css" href="../../../boost.css">
|
||||
<title>Boost.Preprocessor - Known problems with specific compilers</title>
|
||||
</head>
|
||||
<body link="#0000ff" vlink="#800080">
|
||||
<table border="0" cellpadding="7" cellspacing="0" width="100%" summary=
|
||||
"header">
|
||||
<tr>
|
||||
<td valign="top" width="300">
|
||||
<h3><a href="../../../index.htm"><img height="86" width="277" alt="C++ Boost" src="../../../c++boost.gif" border="0"></a></h3>
|
||||
</td>
|
||||
<td valign="top">
|
||||
<h1 align="center">Boost.Preprocessor</h1>
|
||||
<h2 align="center">Known problems with specific compilers</h2>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<hr>
|
||||
|
||||
<p> Some compilers have buggy or limited preprocessors. This page explains known
|
||||
problems with specific compilers.</p>
|
||||
<hr>
|
||||
<h2>Contents</h2>
|
||||
<ul>
|
||||
<li><a href="#Metrowerks Codewarrior 7.0">Metrowerks Codewarrior 7.0</a></li>
|
||||
<li><a href="#Comeau C/C++ 4.2.45.2">Comeau C/C++ 4.2.45.2 for Windows</a></li>
|
||||
</ul>
|
||||
<HR>
|
||||
|
||||
<h3><a name="Metrowerks Codewarrior 7.0">Metrowerks Codewarrior 7.0</a></h3>
|
||||
<p>Metrowerks Codewarrior 7.0 has a bug in preprocessor (to be more
|
||||
concrete, in function-like macro replacement mechanism) that restricts usage
|
||||
of the library to only very simple cases, at least if you don't write code that
|
||||
specifically address this issue; for example, the above NUMBERED_EXPRESSION
|
||||
example doesn't compile on CW 7.0. Below is a simple test case that reproduces
|
||||
the bug:</p>
|
||||
|
||||
<pre>#define IDENTITY_MACRO(x) IDENTITY_MACRO_BODY(x)
|
||||
#define IDENTITY_MACRO_BODY(x) x
|
||||
#define COMMA_TOKEN() ,
|
||||
int a IDENTITY_MACRO(COMMA_TOKEN)() b; // this works
|
||||
int c IDENTITY_MACRO(IDENTITY_MACRO(COMMA_TOKEN))() d; // this doesn't
|
||||
</pre>
|
||||
|
||||
<p>Basically, what's happening here is that function-like COMMA_TOKEN macro gets
|
||||
expanded _inside_ of the nested IDENTITY_MACRO call - even although it's NOT
|
||||
followed by a '(' as the next preprocessing token - which is a clearly an incorrect
|
||||
behavior (see 16.3 [cpp.replace] para 9 for the detailed description of the
|
||||
function-like macro replacement process). I've submitted a bug report, but they
|
||||
haven't confirmed it yet.</p>
|
||||
<p>So, this is not a problem of the library, but probably something that needs
|
||||
to be mentioned in the documentation, may be with some examples of how to workaround
|
||||
the issue. Just to show one possible way around the problem, here is a NUMBERED_EXPRESSION
|
||||
macro that does work on MWCW:</p>
|
||||
<pre>#define NUMBERED_EXPRESSION(n, x) \
|
||||
BOOST_PP_CAT(BOOST_, \
|
||||
BOOST_PP_IF( \
|
||||
n \
|
||||
, PREPROCESSOR_IDENTITY(x##n) \
|
||||
, PREPROCESSOR_EMPTY \
|
||||
))() \
|
||||
/**/
|
||||
</pre>
|
||||
<p align="right"><i>Reported by Aleksey Gurtovoy</i></p>
|
||||
|
||||
<h3><a name="Comeau C/C++ 4.2.45.2">Comeau C/C++ 4.2.45.2 for Windows</a></h3>
|
||||
<p>It appears that their algorithm of macro call invocation is quite far
|
||||
from ideal, because for the following code fragment (which is a part of
|
||||
<a href="../test/preprocessor_test.cpp">preprocessor_test.cpp</a>), the
|
||||
linear increasing of IS_FUNCTION_HELPER_TEST_MAX value leads to not even
|
||||
quadratic, but something like exponential increasing of compilation time!
|
||||
(see the timing data below). This behavior may or may not be problematic
|
||||
for you, depending on how intense is your usage of the library.
|
||||
|
||||
<pre>#ifndef IS_FUNCTION_HELPER_TEST_MAX
|
||||
#define IS_FUNCTION_HELPER_TEST_MAX 40
|
||||
#endif
|
||||
|
||||
typedef char yes_type;
|
||||
|
||||
#define IS_FUNCTION_HELPER(I,A)\
|
||||
template\
|
||||
<BOOST_PP_ENUM_PARAMS(BOOST_PP_INC(I),class P)>\
|
||||
yes_type is_function_helper(\
|
||||
P0 (*)(BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_PP_INC(I),P)));
|
||||
|
||||
BOOST_PP_REPEAT_2ND(BOOST_PP_INC(IS_FUNCTION_HELPER_TEST_MAX),IS_FUNCTION_HELPER,A)
|
||||
|
||||
#undef IS_FUNCTION_HELPER
|
||||
</pre>
|
||||
|
||||
<h4>Timing data:</h4>
|
||||
<table border="1">
|
||||
<tr align="center">
|
||||
<th> </th>
|
||||
<th>Comeau C/C++ 4.2.45.2</th>
|
||||
<th>Microsoft Visual C++ 6.0 SP5</th>
|
||||
</tr>
|
||||
<tr align="center">
|
||||
<td>10 parameters</td>
|
||||
<td><font color="red">< 1 sec</font></td>
|
||||
<td>< 1 sec</td>
|
||||
</tr>
|
||||
<tr align="center">
|
||||
<td>20 parameters</td>
|
||||
<td><font color="red">~ 2 sec</font></td>
|
||||
<td>< 1 sec</td>
|
||||
</tr>
|
||||
<tr align="center">
|
||||
<td>30 parameters</td>
|
||||
<td><font color="red">~ 15 sec</font></td>
|
||||
<td>< 1 sec</td>
|
||||
</tr>
|
||||
<tr align="center">
|
||||
<td>40 parameters</td>
|
||||
<td><font color="red">~ 50 sec</font></td>
|
||||
<td>< 1 sec</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<p align="right"><i>Reported by Aleksey Gurtovoy</i></p>
|
||||
|
||||
<hr>
|
||||
<p>Revised
|
||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
|
||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
||||
</p>
|
||||
<p><i>© Copyright <a href="http://www.housemarque.com">Housemarque Oy</a> 2002</i></p>
|
||||
|
||||
<p>Permission to copy, use, modify, sell and distribute this document is granted
|
||||
provided this copyright notice appears in all copies. This document is provided
|
||||
"as is" without express or implied warranty, and with no claim as to its suitability
|
||||
for any purpose.</p>
|
||||
</body>
|
||||
</html>
|
478
doc/tutorial.htm
478
doc/tutorial.htm
@ -1,478 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<link rel="stylesheet" type="text/css" href="../../../boost.css">
|
||||
<title>Boost.Preprocessor - Tutorial</title>
|
||||
</head>
|
||||
<body link="#0000ff" vlink="#800080">
|
||||
<table border="0" cellpadding="7" cellspacing="0" width="100%" summary=
|
||||
"header">
|
||||
<tr>
|
||||
<td valign="top" width="300">
|
||||
<h3><a href="../../../index.htm"><img height="86" width="277" alt="C++ Boost" src="../../../c++boost.gif" border="0"></a></h3>
|
||||
</td>
|
||||
<td valign="top">
|
||||
<h1 align="center">Boost.Preprocessor</h1>
|
||||
<h2 align="center">Tutorial</h2>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr>
|
||||
|
||||
<h2>Contents</h2>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#Motivation">Motivation</a></dt>
|
||||
<dt><a href="#Techniques">Preprocessor Metaprogramming Techniques</a>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#Local Macro">Use a Local Macro to avoid small scale repetition</a></dt>
|
||||
<dt><a href="#UNUSED">Use BOOST_PP_EMPTY as an unused parameter in Local
|
||||
Macro instantiations</a></dt>
|
||||
<dt><a href="#CAT">Use BOOST_PP_CAT instead of ## when necessary</a></dt>
|
||||
<dt><a href="#STRINGIZE">Use BOOST_PP_STRINGIZE instead of # whenever necessary</a></dt>
|
||||
<dt><a href="#ENUM_PARAMS">Avoid O(N) repetition on lists in general</a></dt>
|
||||
<dt><a href="#Conditional Define">Use a Conditional Define to enable user configuration of code repetition</a></dt>
|
||||
<dt><a href="#Token Look-Up">Use Token Look-Up Function to eliminate categorical repetition</a></dt>
|
||||
<dt><a href="#2ND_REPEAT">Use BOOST_PP_REPEAT to avoid O(N*N) repetition</a></dt>
|
||||
<dt><a href="#IF">Use BOOST_PP_IF to implement special case for the first element</a></dt>
|
||||
<dt><a href="#Arithmetic">Use arithmetic, logical and comparison operations when necessary</a></dt>
|
||||
</dl>
|
||||
</dt>
|
||||
</dl>
|
||||
|
||||
<hr>
|
||||
|
||||
<h2><a name="Motivation">Motivation</a></h2>
|
||||
|
||||
<p>The C++ function and template parameter lists are special syntactic constructs
|
||||
and it is impossible to directly manipulate or generate them using C++ constructs.
|
||||
This leads to unnecessary code repetition.</p>
|
||||
<p> Consider the implementation of the is_function<> metafunction in Boost. The
|
||||
implementation uses an overloaded is_function_tester() function that is used
|
||||
for testing if a type is convertible to pointer to a function. Because of the
|
||||
special treatment of parameter lists, it is not possible to directly match a
|
||||
function with an arbitrary parameter list. Instead, the is_function_tester()
|
||||
must be overloaded for every distinct number of parameters that is to be supported.
|
||||
Example:</p>
|
||||
|
||||
<pre>template <class R>
|
||||
yes_type is_function_tester(R (*)());
|
||||
template <class R, class A0>
|
||||
yes_type is_function_tester(R (*)(A0));
|
||||
template <class R, class A0, A1>
|
||||
yes_type is_function_tester(R (*)(A0, A1));
|
||||
template <class R, class A0, A1, A2>
|
||||
yes_type is_function_tester(R (*)(A0, A1, A2));
|
||||
|
||||
// ...
|
||||
</pre>
|
||||
|
||||
<P>The need for this kind of repetition occurs particularly frequently while implementing
|
||||
generic components or metaprogramming facilities, but the need also manifests
|
||||
itself in many far simpler situations. </P>
|
||||
|
||||
<h3>Typical solutions</h3>
|
||||
|
||||
<p>Typically the repetition is done manually. Manual code repetition is highly
|
||||
unproductive, but sometimes more readable to the untrained eye.</p>
|
||||
<p>Another solution is to write an external program for generating the repeated
|
||||
code or use some other extra linquistic means such as a smart editor. Unfortunately,
|
||||
using external code generators has many disadvantages:</p>
|
||||
<ul>
|
||||
<li>writing the generator takes time (this could be helped by using a standard
|
||||
generator)</li>
|
||||
<li>it is no longer productive to manipulate C++ code directly</li>
|
||||
<li>invoking the generator may be difficult</li>
|
||||
<li>automating the invocation of the generator can be difficult in certain environments
|
||||
(automatic invocation is desirable for active libraries)</li>
|
||||
<li>porting and distributing the generator may be difficult or simply takes
|
||||
precious time</li>
|
||||
</ul>
|
||||
<h3>What about the preprocessor?</h3>
|
||||
<p>Because C++ comes with a preprocessor, one would assume that it would support
|
||||
these kind of needs directly. Using the preprocessor in this case is highly
|
||||
desirable because:</p>
|
||||
<ul>
|
||||
<li>preprocessor is highly portable</li>
|
||||
<li>preprocessor is automatically invoked as part of the compiling process</li>
|
||||
<li>preprocessor metacode can be directly embedded into the C++ source code</li>
|
||||
<li>Compilers generally allow to view or output the preprocessed code, which
|
||||
can be used for debugging or to copy-paste the generated code.</li>
|
||||
</ul>
|
||||
<p>Most unfortunately, the preprocessor is a very low level preprocessor that
|
||||
specifically does not support repetition or recursive macros. Library support
|
||||
is needed!</p>
|
||||
<p><i>For detailed information on the capabilities and limitations of the preprocessor,
|
||||
please refer to the C++ standard <A href="bibliography.htm#[Std]">[Std]</A>.</i></p>
|
||||
<h3>The motivation example revisited</h3>
|
||||
<p>Using the primitives of the PREPROCESSOR library, the is_function_tester()s
|
||||
could be implemented like this:</p>
|
||||
|
||||
<pre>#define IS_FUNCTION_TESTER(N,_)\
|
||||
template<class R BOOST_PP_COMMA_IF(N) BOOST_PP_ENUM_PARAMS(N, class A)>\
|
||||
yes_type is_function_tester(R (*)(BOOST_PP_ENUM_PARAMS(N,A)));
|
||||
|
||||
BOOST_PP_REPEAT(BOOST_PP_INC(MAX_IS_FUNCTION_TESTER_PARAMS),IS_FUNCTION_TESTER,_)
|
||||
#undef IS_FUNCTION_TESTER
|
||||
</pre>
|
||||
|
||||
<p>In order to change the maximum number of function parameters supported, you
|
||||
now simply change the MAX_IS_FUNCTION_TESTER_PARAMS definition and recompile.</p>
|
||||
<HR>
|
||||
|
||||
<H2><a name="Techniques">Preprocessor Metaprogramming Techniques</a></H2>
|
||||
<P>The preprocessor metaprogramming techniques are presented in example format.
|
||||
</P>
|
||||
<HR>
|
||||
<P><B><a name="Local Macro"></a><a href="examples_preprocessed.htm#Local Macro">EXAMPLE</a>:</B>
|
||||
Use a Local Macro to avoid small scale repetition</P>
|
||||
|
||||
<pre>#define BOOST_PP_DEF(OP) \
|
||||
template<class T, int n> \
|
||||
vec<T,n>& \
|
||||
operator OP##= \
|
||||
( vec<T,n>& \
|
||||
lhs \
|
||||
, const vec<T,n>& \
|
||||
rhs \
|
||||
) \
|
||||
{ for (int i=0; i<n; ++i)\
|
||||
lhs(i) OP##= rhs(i); \
|
||||
return lhs; \
|
||||
}
|
||||
|
||||
BOOST_PP_DEF(+)
|
||||
BOOST_PP_DEF(-)
|
||||
BOOST_PP_DEF(*)
|
||||
BOOST_PP_DEF(/)
|
||||
#undef BOOST_PP_DEF
|
||||
</pre>
|
||||
|
||||
<P><B>TIP:</B> It is usually okay to use a standard macro name like BOOST_PP_DEF
|
||||
for this kind of code, because the macro is both defined and undefined in the
|
||||
immediate site of its use.</P>
|
||||
<P><B>TIP:</B> It is easier to verify proper use of
|
||||
the line continuation operator when they are aligned.</P>
|
||||
<P><B>NOTES:</B> You can extend this example by defining more and different kinds
|
||||
of operators. Before doing so, consider using the Algebraic Categories technique
|
||||
introduced in <A href="bibliography.htm#[Barton]">[Barton]</A> or a Layered Architecture (see for instance
|
||||
<A href="bibliography.htm#[Czarnecki]">[Czarnecki]</A>). However, at some point you must type the operator tokens
|
||||
*, /, +, -, ..., because it is impossible to generate them using templates.
|
||||
The resulting Categorical Repetition of tokens can be eliminated by using preprocessor
|
||||
metaprogramming.</P>
|
||||
<HR>
|
||||
<P><B><a name="UNUSED"></a><a href="examples_preprocessed.htm#UNUSED">EXAMPLE</a>:</B>
|
||||
Use BOOST_PP_EMPTY as an unused parameter in Local Macro instantiations</P>
|
||||
|
||||
<pre>#define BOOST_PP_DEF(CV) \
|
||||
template<class base> \
|
||||
CV() typename implement_subscript_using_begin_subscript<base>::value_type&\
|
||||
implement_subscript_using_begin_subscript<base>::operator[]\
|
||||
( index_type \
|
||||
i \
|
||||
) CV() \
|
||||
{ return base::begin()[i];\
|
||||
}
|
||||
|
||||
BOOST_PP_DEF(BOOST_PP_EMPTY)
|
||||
BOOST_PP_DEF(const BOOST_PP_EMPTY)
|
||||
#undef BOOST_PP_DEF
|
||||
</pre>
|
||||
|
||||
<P><B>HOW:</B> BOOST_PP_EMPTY() expands to nothing and can be used as
|
||||
an unused parameter.</P>
|
||||
<P><b>NOTE:</b> BOOST_PP_EMPTY without the () never gets expanded. The
|
||||
() is necessary to invoke a function-like macro.</P>
|
||||
<B>CAVEAT:</B> You can not safely use concatenation while using BOOST_PP_EMPTY().
|
||||
<P><B>TIP:</B> Occasionally one or two lines are
|
||||
considerably longer than the rest. It can often save some work to not align all
|
||||
of the line continuation operators without making the code too unreadable.</P>
|
||||
<P><B>TIP:</B> Use syntax highlighting on preprocessor metaprogramming macro and
|
||||
parameter identifiers such as</P>
|
||||
<ul>
|
||||
<li>BOOST_PP_DEF,</li>
|
||||
<li>BOOST_PP_EMPTY,</li>
|
||||
<li>BOOST_PP_REPEAT,</li>
|
||||
<li>OP,</li>
|
||||
<li>CV,</li>
|
||||
<li>...</li>
|
||||
</ul>
|
||||
<p>It can greatly improve readability.</p>
|
||||
<HR>
|
||||
<P><a name="CAT"></a><a href="examples_preprocessed.htm#CAT"><B>EXAMPLE:</B></a> Use BOOST_PP_CAT instead of ## when necessary</P>
|
||||
|
||||
<pre>#define STATIC_ASSERT(EXPR)\
|
||||
enum\
|
||||
{ BOOST_PP_CAT(static_check_,__LINE__) = (EXPR) ? 1 : -1\
|
||||
};\
|
||||
typedef char\
|
||||
BOOST_PP_CAT(static_assert_,__LINE__)\
|
||||
[ BOOST_PP_CAT(static_check_,__LINE__)\
|
||||
]
|
||||
|
||||
// ...
|
||||
|
||||
STATIC_ASSERT(sizeof(int) <= sizeof(long));
|
||||
</pre>
|
||||
|
||||
<P><B>WHY:</B> Macro expansion proceeds recursively in "layers". Token pasting
|
||||
prevents the preprocessor from performing macro expansion, therefore it
|
||||
is often necessary to delay token concatenation.</P>
|
||||
<hr>
|
||||
<p><a name="STRINGIZE"></a><a href="examples_preprocessed.htm#STRINGIZE"><B>EXAMPLE:</B></a> Use BOOST_PP_STRINGIZE instead of # whenever necessary</p>
|
||||
|
||||
<pre>#define NOTE(STR)\
|
||||
message(__FILE__ "(" BOOST_PP_STRINGIZE(__LINE__) ") : " STR)
|
||||
|
||||
// ...
|
||||
|
||||
#pragma NOTE("TBD!")
|
||||
</pre>
|
||||
|
||||
<p><b>WHY:</b> Macro expansion proceeds recursively in "layers". Stringization
|
||||
prevents the preprocessor from performing macro expansion, therefore it is often
|
||||
necessary to delay stringization.</p>
|
||||
<HR>
|
||||
<P><B><a name="ENUM_PARAMS"></a><a href="examples_preprocessed.htm#ENUM_PARAMS">EXAMPLE</a>:</B>
|
||||
Use:</P>
|
||||
<ul>
|
||||
<li>BOOST_PP_ENUM_PARAMS,</li>
|
||||
<li>BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT,</li>
|
||||
<li>BOOST_PP_ENUM_PARAMS_WITH_DEFAULTS,</li>
|
||||
<li>BOOST_PP_ENUM_SHIFTED_PARAMS, or</li>
|
||||
<li>BOOST_PP_REPEAT, and</li>
|
||||
<li>BOOST_PP_COMMA_IF</li>
|
||||
</ul>
|
||||
<p>to avoid O(N) repetition on lists in general</p>
|
||||
|
||||
<pre>struct make_type_list_end;
|
||||
|
||||
template
|
||||
< BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT
|
||||
( MAKE_TYPE_LIST_MAX_LENGTH
|
||||
, class T
|
||||
, make_type_list_end
|
||||
)
|
||||
>
|
||||
struct make_type_list
|
||||
{
|
||||
private:
|
||||
enum
|
||||
{ end = is_same<T0,make_type_list_end>::value
|
||||
};
|
||||
|
||||
public:
|
||||
typedef typename
|
||||
type_if
|
||||
< end
|
||||
, type_cons_empty
|
||||
, type_cons
|
||||
< T0
|
||||
, typename
|
||||
type_inner_if
|
||||
< end
|
||||
, type_identity<end>
|
||||
, make_type_list
|
||||
< BOOST_PP_ENUM_SHIFTED_PARAMS
|
||||
( MAKE_TYPE_LIST_MAX_LENGTH
|
||||
, T
|
||||
)
|
||||
>
|
||||
>::type
|
||||
>
|
||||
>::type type;
|
||||
};
|
||||
</pre>
|
||||
|
||||
<P><B>HOW:</B> BOOST_PP_REPEAT uses simulated recursion (pseudo code):</P>
|
||||
|
||||
<pre>#define BOOST_PP_REPEAT(N,M,P) BOOST_PP_REPEAT##N(M,P)
|
||||
#define BOOST_PP_REPEAT0(M,P)
|
||||
#define BOOST_PP_REPEAT1(M,P) M(0,P)
|
||||
#define BOOST_PP_REPEAT2(M,P) M(0,P) M(1,P)
|
||||
#define BOOST_PP_REPEAT3(M,P) BOOST_PP_REPEAT2(M,P) M(2,P)
|
||||
#define BOOST_PP_REPEAT4(M,P) BOOST_PP_REPEAT3(M,P) M(3,P)
|
||||
// ...
|
||||
</pre>
|
||||
|
||||
<P>BOOST_PP_ENUM_PARAMS variations use BOOST_PP_REPEAT</P>
|
||||
|
||||
<P>BOOST_PP_COMMA_IF(I) expands to a comma if I != 0.</P>
|
||||
|
||||
<P>BOOST_PP_INC(I) expands essentially to "I+1" and BOOST_PP_DEC(I)
|
||||
expands essentially to "I-1".</P>
|
||||
|
||||
<HR>
|
||||
|
||||
<P><a name="Conditional Define"><B>EXAMPLE:</B></a> Use a Conditional Define to
|
||||
enable user configuration of code repetition based on need rather than some
|
||||
"reasonable" upper limit</P>
|
||||
|
||||
<pre>#ifndef MAKE_TYPE_LIST_MAX_LENGTH
|
||||
#define MAKE_TYPE_LIST_MAX_LENGTH 8
|
||||
#endif
|
||||
</pre>
|
||||
|
||||
<P>Now the user can configure the make_type_list primitive without modifying library
|
||||
code.</P>
|
||||
<HR>
|
||||
<P><B><a name="Token Look-Up"></a><a href="examples_preprocessed.htm#Token Look-Up">EXAMPLE</a>:</B>
|
||||
Use BOOST_PP_REPEAT and a Token Look-Up Function to eliminate categorical
|
||||
repetition</P>
|
||||
|
||||
<pre>// CAVEAT: My compiler is not standard on arithmetic types.
|
||||
#define ARITHMETIC_TYPE(I) ARITHMETIC_TYPE##I
|
||||
#define ARITHMETIC_TYPE0 bool
|
||||
#define ARITHMETIC_TYPE1 char
|
||||
#define ARITHMETIC_TYPE2 signed char
|
||||
#define ARITHMETIC_TYPE3 unsigned char
|
||||
#define ARITHMETIC_TYPE4 short
|
||||
#define ARITHMETIC_TYPE5 unsigned short
|
||||
#define ARITHMETIC_TYPE6 int
|
||||
#define ARITHMETIC_TYPE7 unsigned int
|
||||
#define ARITHMETIC_TYPE8 long
|
||||
#define ARITHMETIC_TYPE9 unsigned long
|
||||
#define ARITHMETIC_TYPE10 float
|
||||
#define ARITHMETIC_TYPE11 double
|
||||
#define ARITHMETIC_TYPE12 long double
|
||||
#define ARITHMETIC_TYPE_CNT 13
|
||||
|
||||
// ...
|
||||
|
||||
#define BOOST_PP_DEF(I,_)\
|
||||
catch (ARITHMETIC_TYPE(I) t)\
|
||||
{ report_typeid(t);\
|
||||
report_value(t);\
|
||||
}
|
||||
BOOST_PP_REPEAT
|
||||
( ARITHMETIC_TYPE_CNT
|
||||
, BOOST_PP_DEF
|
||||
, _
|
||||
)
|
||||
#undef BOOST_PP_DEF
|
||||
|
||||
// ...
|
||||
</pre>
|
||||
|
||||
<P><B>NOTE:</B> The repetition of the above
|
||||
example can be eliminated using template metaprogramming <A href="bibliography.htm#[Czarnecki]">[Czarnecki]</A> as well. However
|
||||
categorical repetition of operator tokens can not be completely eliminated by
|
||||
using template metaprogramming.</P>
|
||||
<HR>
|
||||
<P><B><a name="2ND_REPEAT"></a><a href="examples_preprocessed.htm#2ND_REPEAT">EXAMPLE</a>:</B>
|
||||
Use BOOST_PP_REPEAT to avoid O(N*N) repetition</P>
|
||||
|
||||
<pre>#ifndef MAX_VEC_ARG_CNT
|
||||
#define MAX_VEC_ARG_CNT 8
|
||||
#endif
|
||||
|
||||
// ...
|
||||
|
||||
#define ARG_FUN(I,_) BOOST_PP_COMMA_IF(I) T a##I
|
||||
#define ASSIGN_FUN(I,_) (*this)[I] = a##I;
|
||||
|
||||
#define DEF_VEC_CTOR_FUN(I,_)\
|
||||
vec( BOOST_PP_REPEAT(I,ARG_FUN,_) )\
|
||||
{ BOOST_PP_REPEAT(I,ASSIGN_FUN,_)\
|
||||
}
|
||||
|
||||
BOOST_PP_REPEAT
|
||||
( BOOST_PP_INC(MAX_VEC_ARG_CNT)
|
||||
, DEF_VEC_CTOR_FUN
|
||||
, _
|
||||
)
|
||||
|
||||
#undef ARG_FUN
|
||||
#undef ASSIGN_FUN
|
||||
#undef DEF_VEC_CTOR_FUN
|
||||
|
||||
// ...
|
||||
</pre>
|
||||
|
||||
<P><B>HOW:</B> BOOST_PP_REPEAT is implemented in a special way to enable
|
||||
automatic recursion.</P>
|
||||
|
||||
<HR>
|
||||
|
||||
<P><a name="IF"></a><a href="examples_preprocessed.htm#IF"><B>EXAMPLE:</B></a> Use BOOST_PP_IF to implement special case for the first element</P>
|
||||
|
||||
<pre>#define BOOST_PP_COMMA_IF(C)\
|
||||
BOOST_PP_IF(C,BOOST_PP_COMMA,BOOST_PP_EMPTY)()
|
||||
|
||||
BOOST_PP_IF(0,true,false) == false;
|
||||
BOOST_PP_IF(1,true,false) == true;
|
||||
</pre>
|
||||
|
||||
<P>BOOST_PP_IF enables convenient generation of lists using BOOST_PP_REPEAT.</P>
|
||||
|
||||
<P><B>NOTE:</B> THEN and ELSE don't have to be macros. However, if at least one
|
||||
of them is a function-like macro and you want it to be expanded conditionally,
|
||||
you have to make the other parameter a function-like macro, too. This can often
|
||||
be done using BOOST_PP_IDENTITY. Consider the following example (by
|
||||
Aleksey Gurtovoy):</P>
|
||||
|
||||
<pre>#define NUMBERED_EXPRESSION(I,X)\
|
||||
BOOST_PP_IF \
|
||||
( I \
|
||||
, BOOST_PP_IDENTITY(X##I) \
|
||||
, BOOST_PP_EMPTY \
|
||||
)()</pre>
|
||||
|
||||
<P><b>NOTE:</b> Like in the above implementation of COMMA_IF, the result of IF
|
||||
is often invoked and not the THEN and ELSE parameters. If the parameters were
|
||||
invoked, the code would not expand correctly, because the EMPTY parameter would
|
||||
get expanded to nothing before the IF would be properly expanded.</P>
|
||||
<P><b>HOW:</b> BOOST_PP_IF is defined for the entire repeat range (pseudo
|
||||
code):</P>
|
||||
|
||||
<pre>#define BOOST_PP_IF(C,THEN,ELSE) BOOST_PP_IF##C(THEN,ELSE)
|
||||
#define BOOST_PP_IF0(THEN,ELSE) ELSE
|
||||
#define BOOST_PP_IF1(THEN,ELSE) THEN
|
||||
#define BOOST_PP_IF2(THEN,ELSE) THEN
|
||||
// ...
|
||||
</pre>
|
||||
|
||||
<hr>
|
||||
|
||||
<p><a name="Arithmetic"></a><a href="examples_preprocessed.htm#Arithmetic"><B>EXAMPLE:</B></a> Use arithmetic, logical and comparison operations when necessary</p>
|
||||
|
||||
<P>The PREPROCESSOR library supports saturated arithmetic, logical and
|
||||
comparison operations on decimal integer literals in the range [0,BOOST_PP_LIMIT_MAG].</p>
|
||||
|
||||
<p>Suppose that you want to generate a numbered lists with a special element inserted
|
||||
at a desired position. For example: E0, E1, S, E2. Consider the following example:</p>
|
||||
|
||||
<pre>#define SPECIAL_NUMBERED_LIST(N,I,ELEM,SPECIAL)\
|
||||
BOOST_PP_ASSERT_MSG(BOOST_PP_LESS(I,N),BAD PARAMS FOR SPECIAL_NUMBERED_LIST!)\
|
||||
BOOST_PP_ENUM_PARAMS(I,ELEM)\
|
||||
BOOST_PP_COMMA_IF(I) SPECIAL\
|
||||
BOOST_PP_REPEAT(BOOST_PP_SUB(\
|
||||
BOOST_PP_DEC(N),I),SPECIAL_NUMBERED_LIST_HELPER,(ELEM,I))
|
||||
#define SPECIAL_NUMBERED_LIST_HELPER(I,ELEM_BASE)\
|
||||
,\
|
||||
BOOST_PP_CAT\
|
||||
( BOOST_PP_TUPLE_ELEM(2,0,ELEM_BASE)\
|
||||
, BOOST_PP_ADD\
|
||||
( I\
|
||||
, BOOST_PP_TUPLE_ELEM(2,1,ELEM_BASE)\
|
||||
)\
|
||||
)
|
||||
|
||||
SPECIAL_NUMBERED_LIST(3,0,E,S)
|
||||
SPECIAL_NUMBERED_LIST(3,1,E,S)
|
||||
SPECIAL_NUMBERED_LIST(3,2,E,S)
|
||||
SPECIAL_NUMBERED_LIST(3,3,E,S)
|
||||
</pre>
|
||||
|
||||
<hr>
|
||||
<p>Revised
|
||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
|
||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
||||
</p>
|
||||
<p><i>© Copyright <a href="http://www.housemarque.com">Housemarque Oy</a> 2002</i></p>
|
||||
|
||||
<p>Permission to copy, use, modify, sell and distribute this document is granted
|
||||
provided this copyright notice appears in all copies. This document is provided
|
||||
"as is" without express or implied warranty, and with no claim as to its suitability
|
||||
for any purpose.</p>
|
||||
</body>
|
||||
</html>
|
@ -1,69 +0,0 @@
|
||||
/* Copyright (C) 2001
|
||||
* Housemarque Oy
|
||||
* http://www.housemarque.com
|
||||
*
|
||||
* Permission to copy, use, modify, sell and distribute this software is
|
||||
* granted provided this copyright notice appears in all copies. This
|
||||
* software is provided "as is" without express or implied warranty, and
|
||||
* with no claim as to its suitability for any purpose.
|
||||
*
|
||||
* See http://www.boost.org for most recent version.
|
||||
*/
|
||||
|
||||
#include <boost/preprocessor/arithmetic.hpp>
|
||||
#include <boost/preprocessor/comparison.hpp>
|
||||
#include <boost/preprocessor/limits.hpp>
|
||||
#include <boost/preprocessor/min.hpp>
|
||||
#include <boost/preprocessor/max.hpp>
|
||||
|
||||
#include <libs/preprocessor/test/test.hpp>
|
||||
|
||||
/* *** */
|
||||
|
||||
TEST_B BOOST_PP_ADD(2,3) == 5 TEST_E
|
||||
TEST_B BOOST_PP_ADD(21,BOOST_PP_SUB(BOOST_PP_LIMIT_MAG,20)) == BOOST_PP_LIMIT_MAG TEST_E
|
||||
|
||||
TEST_B BOOST_PP_SUB(11,0) == 11 TEST_E
|
||||
TEST_B BOOST_PP_SUB(12,1) == 11 TEST_E
|
||||
TEST_B BOOST_PP_SUB(3,4) == 0 TEST_E
|
||||
|
||||
TEST_B BOOST_PP_MUL(0,1) == 0 TEST_E
|
||||
TEST_B BOOST_PP_MUL(1,0) == 0 TEST_E
|
||||
TEST_B BOOST_PP_MUL(1,1) == 1 TEST_E
|
||||
TEST_B BOOST_PP_MUL(4,3) == 12 TEST_E
|
||||
|
||||
TEST_B BOOST_PP_DIV(2,1) == 2 TEST_E
|
||||
TEST_B BOOST_PP_DIV(0,5) == 0 TEST_E
|
||||
TEST_B BOOST_PP_DIV(7,3) == 2 TEST_E
|
||||
|
||||
TEST_B BOOST_PP_EQUAL(1,0) == 0 TEST_E
|
||||
TEST_B BOOST_PP_EQUAL(10,10) == 1 TEST_E
|
||||
|
||||
TEST_B BOOST_PP_NOT_EQUAL(3,4) == 1 TEST_E
|
||||
TEST_B BOOST_PP_NOT_EQUAL(7,7) == 0 TEST_E
|
||||
|
||||
TEST_B BOOST_PP_LESS_EQUAL(6,7) == 1 TEST_E
|
||||
TEST_B BOOST_PP_LESS_EQUAL(8,1) == 0 TEST_E
|
||||
TEST_B BOOST_PP_LESS_EQUAL(5,5) == 1 TEST_E
|
||||
|
||||
TEST_B BOOST_PP_GREATER_EQUAL(6,7) == 0 TEST_E
|
||||
TEST_B BOOST_PP_GREATER_EQUAL(10,10) == 1 TEST_E
|
||||
TEST_B BOOST_PP_GREATER_EQUAL(8,1) == 1 TEST_E
|
||||
|
||||
TEST_B BOOST_PP_LESS(2,1) == 0 TEST_E
|
||||
TEST_B BOOST_PP_LESS(1,1) == 0 TEST_E
|
||||
TEST_B BOOST_PP_LESS(1,2) == 1 TEST_E
|
||||
|
||||
TEST_B BOOST_PP_GREATER(2,1) == 1 TEST_E
|
||||
TEST_B BOOST_PP_GREATER(1,1) == 0 TEST_E
|
||||
TEST_B BOOST_PP_GREATER(1,2) == 0 TEST_E
|
||||
|
||||
TEST_B BOOST_PP_MIN(1,0) == 0 TEST_E
|
||||
TEST_B BOOST_PP_MIN(1,2) == 1 TEST_E
|
||||
|
||||
TEST_B BOOST_PP_MAX(3,2) == 3 TEST_E
|
||||
TEST_B BOOST_PP_MAX(4,5) == 5 TEST_E
|
||||
|
||||
TEST_B BOOST_PP_MOD(5,5) == 0 TEST_E
|
||||
TEST_B BOOST_PP_MOD(9,5) == 4 TEST_E
|
||||
TEST_B BOOST_PP_MOD(7,4) == 3 TEST_E
|
@ -1,28 +0,0 @@
|
||||
/* Copyright (C) 2001
|
||||
* Housemarque Oy
|
||||
* http://www.housemarque.com
|
||||
*
|
||||
* Permission to copy, use, modify, sell and distribute this software is
|
||||
* granted provided this copyright notice appears in all copies. This
|
||||
* software is provided "as is" without express or implied warranty, and
|
||||
* with no claim as to its suitability for any purpose.
|
||||
*
|
||||
* See http://www.boost.org for most recent version.
|
||||
*/
|
||||
|
||||
#include <boost/preprocessor/for.hpp>
|
||||
#include <boost/preprocessor/dec.hpp>
|
||||
|
||||
#include <libs/preprocessor/test/test.hpp>
|
||||
|
||||
/* *** */
|
||||
|
||||
#ifndef FOR_TEST_MAX
|
||||
#define FOR_TEST_MAX 50
|
||||
#endif
|
||||
|
||||
#define C(D,X) X
|
||||
#define F(D,X) BOOST_PP_DEC(X)
|
||||
#define I(D,X) -X
|
||||
|
||||
TEST_B (FOR_TEST_MAX*(FOR_TEST_MAX+1)/2)+1 BOOST_PP_FOR(FOR_TEST_MAX,C,F,I) TEST_E
|
@ -1,57 +0,0 @@
|
||||
/* Copyright (C) 2001
|
||||
* Housemarque Oy
|
||||
* http://www.housemarque.com
|
||||
*
|
||||
* Permission to copy, use, modify, sell and distribute this software is
|
||||
* granted provided this copyright notice appears in all copies. This
|
||||
* software is provided "as is" without express or implied warranty, and
|
||||
* with no claim as to its suitability for any purpose.
|
||||
*
|
||||
* See http://www.boost.org for most recent version.
|
||||
*/
|
||||
|
||||
#include <boost/preprocessor/list.hpp>
|
||||
#include <boost/preprocessor/tuple/to_list.hpp>
|
||||
#include <boost/preprocessor/arithmetic/add.hpp>
|
||||
#include <boost/preprocessor/arithmetic/sub.hpp>
|
||||
#include <boost/preprocessor/comparison/less.hpp>
|
||||
|
||||
#include <libs/preprocessor/test/test.hpp>
|
||||
|
||||
/* *** */
|
||||
|
||||
#define TEST_LIST BOOST_PP_TUPLE_TO_LIST(4,(4,1,5,2))
|
||||
|
||||
TEST_B BOOST_PP_LIST_FOLD_LEFT(BOOST_PP_SUB_D,22,TEST_LIST) == 10 TEST_E
|
||||
TEST_B BOOST_PP_LIST_CAT(BOOST_PP_LIST_REVERSE(TEST_LIST)) == 2514 TEST_E
|
||||
TEST_B BOOST_PP_LIST_FOLD_RIGHT(BOOST_PP_SUB_D,TEST_LIST,0) == 4 TEST_E
|
||||
|
||||
TEST_B BOOST_PP_LIST_CAT(BOOST_PP_LIST_REST_N(2,TEST_LIST)) == 52 TEST_E
|
||||
TEST_B BOOST_PP_LIST_CAT(BOOST_PP_LIST_FIRST_N(2,TEST_LIST)) == 41 TEST_E
|
||||
|
||||
TEST_B BOOST_PP_LIST_AT(TEST_LIST,2) == 5 TEST_E
|
||||
|
||||
TEST_B BOOST_PP_LIST_SIZE(TEST_LIST) == 4 TEST_E
|
||||
|
||||
TEST_B BOOST_PP_LIST_CAT(BOOST_PP_LIST_TRANSFORM(BOOST_PP_ADD_D,2,TEST_LIST)) == 6374 TEST_E
|
||||
|
||||
TEST_B BOOST_PP_LIST_CAT(BOOST_PP_LIST_APPEND(BOOST_PP_LIST_REST(TEST_LIST),TEST_LIST)) == 1524152 TEST_E
|
||||
|
||||
#define F(I,P,X) +X+P
|
||||
TEST_B BOOST_PP_LIST_FOR_EACH(F,1,TEST_LIST) == 16 TEST_E
|
||||
#undef F
|
||||
|
||||
TEST_B BOOST_PP_TUPLE_ELEM(4,3,BOOST_PP_LIST_TO_TUPLE(TEST_LIST)) == 2 TEST_E
|
||||
|
||||
TEST_B BOOST_PP_LIST_CAT(BOOST_PP_LIST_FILTER(BOOST_PP_LESS_D,3,TEST_LIST)) == 45 TEST_E
|
||||
|
||||
#define F(R,X) +BOOST_PP_TUPLE_ELEM(2,0,X)+2-BOOST_PP_TUPLE_ELEM(2,1,X)
|
||||
TEST_B BOOST_PP_LIST_FOR_EACH_PRODUCT(F,2,(BOOST_PP_TUPLE_TO_LIST(2,(1,0)),BOOST_PP_TUPLE_TO_LIST(2,(2,3)))) == 0 TEST_E
|
||||
#undef F
|
||||
|
||||
TEST_B BOOST_PP_LIST_CAT(BOOST_PP_LIST_FOLD_RIGHT(BOOST_PP_LIST_APPEND_D,
|
||||
BOOST_PP_TUPLE_TO_LIST(3,
|
||||
(BOOST_PP_TUPLE_TO_LIST(2,(0,x)),
|
||||
BOOST_PP_TUPLE_TO_LIST(4,(A,1,B,2)),
|
||||
BOOST_PP_TUPLE_TO_LIST(3,(C,3,D)))),
|
||||
BOOST_PP_LIST_NIL)) == 0xA1B2C3D TEST_E
|
@ -1,40 +0,0 @@
|
||||
/* Copyright (C) 2001
|
||||
* Housemarque Oy
|
||||
* http://www.housemarque.com
|
||||
*
|
||||
* Permission to copy, use, modify, sell and distribute this software is
|
||||
* granted provided this copyright notice appears in all copies. This
|
||||
* software is provided "as is" without express or implied warranty, and
|
||||
* with no claim as to its suitability for any purpose.
|
||||
*
|
||||
* See http://www.boost.org for most recent version.
|
||||
*/
|
||||
|
||||
#include <boost/preprocessor/logical.hpp>
|
||||
|
||||
#include <libs/preprocessor/test/test.hpp>
|
||||
|
||||
/* *** */
|
||||
|
||||
TEST_B BOOST_PP_NOT(0) == 1 TEST_E
|
||||
TEST_B BOOST_PP_NOT(2) == 0 TEST_E
|
||||
|
||||
TEST_B BOOST_PP_AND(0,0) == 0 TEST_E
|
||||
TEST_B BOOST_PP_AND(0,3) == 0 TEST_E
|
||||
TEST_B BOOST_PP_AND(4,0) == 0 TEST_E
|
||||
TEST_B BOOST_PP_AND(5,6) == 1 TEST_E
|
||||
|
||||
TEST_B BOOST_PP_OR(0,0) == 0 TEST_E
|
||||
TEST_B BOOST_PP_OR(0,7) == 1 TEST_E
|
||||
TEST_B BOOST_PP_OR(8,0) == 1 TEST_E
|
||||
TEST_B BOOST_PP_OR(9,1) == 1 TEST_E
|
||||
|
||||
TEST_B BOOST_PP_XOR(0,0) == 0 TEST_E
|
||||
TEST_B BOOST_PP_XOR(0,2) == 1 TEST_E
|
||||
TEST_B BOOST_PP_XOR(3,0) == 1 TEST_E
|
||||
TEST_B BOOST_PP_XOR(4,5) == 0 TEST_E
|
||||
|
||||
TEST_B BOOST_PP_NOR(0,0) == 1 TEST_E
|
||||
TEST_B BOOST_PP_NOR(0,6) == 0 TEST_E
|
||||
TEST_B BOOST_PP_NOR(7,0) == 0 TEST_E
|
||||
TEST_B BOOST_PP_NOR(8,9) == 0 TEST_E
|
@ -1,57 +0,0 @@
|
||||
/* Copyright (C) 2001
|
||||
* Housemarque Oy
|
||||
* http://www.housemarque.com
|
||||
*
|
||||
* Permission to copy, use, modify, sell and distribute this software is
|
||||
* granted provided this copyright notice appears in all copies. This
|
||||
* software is provided "as is" without express or implied warranty, and
|
||||
* with no claim as to its suitability for any purpose.
|
||||
*
|
||||
* See http://www.boost.org for most recent version.
|
||||
*/
|
||||
|
||||
#include <boost/preprocessor/empty.hpp>
|
||||
#include <boost/preprocessor/identity.hpp>
|
||||
#include <boost/preprocessor/if.hpp>
|
||||
#include <boost/preprocessor/expr_if.hpp>
|
||||
#include <boost/preprocessor/cat.hpp>
|
||||
#include <boost/preprocessor/stringize.hpp>
|
||||
#include <boost/preprocessor/tuple/elem.hpp>
|
||||
|
||||
#include <libs/preprocessor/test/test.hpp>
|
||||
|
||||
/* *** */
|
||||
|
||||
struct Container
|
||||
{
|
||||
#define BOOST_PP_DEF(CV)\
|
||||
CV() int& operator[](int i) CV();
|
||||
|
||||
BOOST_PP_DEF(BOOST_PP_EMPTY)
|
||||
BOOST_PP_DEF(BOOST_PP_IDENTITY(const))
|
||||
BOOST_PP_DEF(BOOST_PP_IDENTITY(volatile))
|
||||
BOOST_PP_DEF(BOOST_PP_IDENTITY(const volatile))
|
||||
|
||||
#undef BOOST_PP_DEF
|
||||
};
|
||||
|
||||
/* *** */
|
||||
|
||||
TEST_B BOOST_PP_IF(BOOST_PP_IF(1,1,1),true,false) &&
|
||||
BOOST_PP_IF(BOOST_PP_IF(0,0,0),false,true) TEST_E
|
||||
|
||||
/* *** */
|
||||
|
||||
TEST_B BOOST_PP_EXPR_IF(1,1) TEST_E
|
||||
|
||||
/* *** */
|
||||
|
||||
TEST_B BOOST_PP_CAT(BOOST_PP_IF(1,tru,fals), e) TEST_E
|
||||
|
||||
/* *** */
|
||||
|
||||
char stringize_test[3] = BOOST_PP_STRINGIZE(__LINE__);
|
||||
|
||||
/* *** */
|
||||
|
||||
TEST_B BOOST_PP_TUPLE_ELEM(2,0,(1,0)) TEST_E
|
@ -1,62 +0,0 @@
|
||||
/* Copyright (C) 2001
|
||||
* Housemarque Oy
|
||||
* http://www.housemarque.com
|
||||
*
|
||||
* Permission to copy, use, modify, sell and distribute this software is
|
||||
* granted provided this copyright notice appears in all copies. This
|
||||
* software is provided "as is" without express or implied warranty, and
|
||||
* with no claim as to its suitability for any purpose.
|
||||
*
|
||||
* See http://www.boost.org for most recent version.
|
||||
*/
|
||||
|
||||
#include <boost/preprocessor/enum_params.hpp>
|
||||
#include <boost/preprocessor/enum_shifted_params.hpp>
|
||||
#include <boost/preprocessor/inc.hpp>
|
||||
#include <boost/preprocessor/repeat_from_to.hpp>
|
||||
#include <libs/preprocessor/test/test.hpp>
|
||||
|
||||
/* *** */
|
||||
|
||||
/* RATIONALE:
|
||||
* - BOOST_PP_REPEAT, BOOST_PP_ENUM, BOOST_PP_REPEAT_FROM_TO and must work
|
||||
* recursively together.
|
||||
* - BOOST_PP_REPEAT is already tested with
|
||||
* BOOST_PP_ENUM_PARAMS.
|
||||
* - The tested repeat count should exceed imaginable usage.
|
||||
* - Testing the generation of is_function_helper()s upto 40 arguments should
|
||||
* be sufficient in this case. Many compilers may fail the repetition tests
|
||||
* (at least with higher counts). However, the primary purpose of the
|
||||
* repetition primitives is to enable configurability with reasonable
|
||||
* defaults, and not necessarily "the most impressive repetition".
|
||||
* - ENUM_SHIFTED_PARAMS must be tested so that the shifted range is shown to
|
||||
* be correct.
|
||||
*/
|
||||
|
||||
#ifndef IS_FUNCTION_HELPER_TEST_MAX
|
||||
#define IS_FUNCTION_HELPER_TEST_MAX 40
|
||||
#endif
|
||||
|
||||
typedef char yes_type;
|
||||
|
||||
#define IS_FUNCTION_HELPER(I,A)\
|
||||
template\
|
||||
<BOOST_PP_ENUM_PARAMS(BOOST_PP_INC(I),class P)>\
|
||||
yes_type is_function_helper(\
|
||||
P0 (*)(BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_PP_INC(I),P)));
|
||||
|
||||
BOOST_PP_REPEAT(BOOST_PP_INC(IS_FUNCTION_HELPER_TEST_MAX),IS_FUNCTION_HELPER,A)
|
||||
|
||||
#undef IS_FUNCTION_HELPER
|
||||
|
||||
/* *** */
|
||||
|
||||
#define ELEM(_,X) X
|
||||
#define COL(I,_) - BOOST_PP_TUPLE_ELEM(2,0,(BOOST_PP_ENUM(2,ELEM,I)))
|
||||
#define ROW(I,_) BOOST_PP_REPEAT(I,COL,_)
|
||||
|
||||
TEST_B 0 == (1 +1+2 +1+2+3) BOOST_PP_REPEAT_FROM_TO(2,5,ROW,_) TEST_E
|
||||
|
||||
#undef ROW
|
||||
#undef COL
|
||||
#undef ELEM
|
@ -1,56 +0,0 @@
|
||||
/* Copyright (C) 2001
|
||||
* Housemarque Oy
|
||||
* http://www.housemarque.com
|
||||
*
|
||||
* Permission to copy, use, modify, sell and distribute this software is
|
||||
* granted provided this copyright notice appears in all copies. This
|
||||
* software is provided "as is" without express or implied warranty, and
|
||||
* with no claim as to its suitability for any purpose.
|
||||
*
|
||||
* See http://www.boost.org for most recent version.
|
||||
*/
|
||||
|
||||
#include <boost/preprocessor/cat.hpp>
|
||||
#include <boost/preprocessor/enum_params.hpp>
|
||||
#include <boost/preprocessor/enum_params_with_a_default.hpp>
|
||||
#include <boost/preprocessor/enum_params_with_defaults.hpp>
|
||||
#include <boost/preprocessor/repeat_from_to.hpp>
|
||||
#include <libs/preprocessor/test/test.hpp>
|
||||
|
||||
/* *** */
|
||||
|
||||
/* RATIONALE:
|
||||
* - All forms of ENUM_PARAMS must be tested with 0 and n, where n is
|
||||
* sufficiently large to exceed imaginable usage like. 50 should be
|
||||
* suffient in this case.
|
||||
*/
|
||||
|
||||
#ifndef ENUM_PARAMS_TEST_MAX
|
||||
#define ENUM_PARAMS_TEST_MAX 50
|
||||
#endif
|
||||
|
||||
#define CONSTANT(I,A) BOOST_PP_CAT(A,I) = I
|
||||
const int BOOST_PP_ENUM(ENUM_PARAMS_TEST_MAX, CONSTANT, default_param_);
|
||||
#undef CONSTANT
|
||||
|
||||
#define TEST_ENUM_PARAMS(N)\
|
||||
void BOOST_PP_CAT(test_enum_params,N)(\
|
||||
BOOST_PP_ENUM_PARAMS(N, int x));\
|
||||
void BOOST_PP_CAT(test_enum_params_with_a_default,N)(\
|
||||
BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(N, int x, 0));\
|
||||
void BOOST_PP_CAT(test_enum_params_with_defaults,N)(\
|
||||
BOOST_PP_ENUM_PARAMS_WITH_DEFAULTS(N, int x, default_param_));
|
||||
|
||||
TEST_ENUM_PARAMS(0)
|
||||
TEST_ENUM_PARAMS(ENUM_PARAMS_TEST_MAX)
|
||||
|
||||
#undef TEST_ENUM_PARAMS
|
||||
|
||||
template<BOOST_PP_ENUM_PARAMS(ENUM_PARAMS_TEST_MAX,class T)>
|
||||
struct no_rescan;
|
||||
|
||||
/* *** */
|
||||
|
||||
#define F(I,P) P I
|
||||
TEST_B 1 + (4+5+6) BOOST_PP_REPEAT_FROM_TO(4,7,F,-) TEST_E
|
||||
#undef F
|
@ -1,28 +0,0 @@
|
||||
#ifndef BOOST_LIBS_PREPROCESSOR_TEST_TEST_HPP
|
||||
#define BOOST_LIBS_PREPROCESSOR_TEST_TEST_HPP
|
||||
|
||||
/* Copyright (C) 2001
|
||||
* Housemarque Oy
|
||||
* http://www.housemarque.com
|
||||
*
|
||||
* Permission to copy, use, modify, sell and distribute this software is
|
||||
* granted provided this copyright notice appears in all copies. This
|
||||
* software is provided "as is" without express or implied warranty, and
|
||||
* with no claim as to its suitability for any purpose.
|
||||
*
|
||||
* See http://www.boost.org for most recent version.
|
||||
*/
|
||||
|
||||
#include <boost/preprocessor/cat.hpp>
|
||||
|
||||
/* The TEST macro has been broken into two pieces to avoid
|
||||
* double expansion:
|
||||
* 1. as a macro argument
|
||||
* 2. rescan
|
||||
*/
|
||||
#define TEST_B typedef int BOOST_PP_CAT(test_,__LINE__)[((
|
||||
#define TEST_E )==1) ? 1 : -1];
|
||||
|
||||
#define MACRO(X) X
|
||||
#define MACRO_ARGS(X) (X)
|
||||
#endif
|
@ -1,12 +0,0 @@
|
||||
/* Copyright (C) 2002 Vesa Karvonen
|
||||
*
|
||||
* Permission to copy, use, modify, sell and distribute this software is
|
||||
* granted provided this copyright notice appears in all copies. This
|
||||
* software is provided "as is" without express or implied warranty, and
|
||||
* with no claim as to its suitability for any purpose.
|
||||
*
|
||||
* See http://www.boost.org for most recent version.
|
||||
*/
|
||||
|
||||
/* This simply attempts to include all preprocessor library headers. */
|
||||
#include <boost/preprocessor.hpp>
|
Reference in New Issue
Block a user