mirror of
https://github.com/boostorg/wave.git
synced 2026-01-26 07:02:23 +00:00
318 lines
18 KiB
HTML
318 lines
18 KiB
HTML
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
|
<html>
|
|
<head>
|
|
<title>Preliminary C++0x support</title>
|
|
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
|
<link href="theme/style.css" rel="stylesheet" type="text/css">
|
|
</head>
|
|
|
|
<body>
|
|
<table width="100%" border="0" cellspacing="2" background="theme/bkd2.gif">
|
|
<tr>
|
|
<td width="21"> <h1></h1></td>
|
|
<td width="885"> <font face="Verdana, Arial, Helvetica, sans-serif"><b><font size="6">Preliminary
|
|
C++0x support</font></b></font></td>
|
|
<td width="96"><a href="http://spirit.sf.net"><img src="theme/wave.gif" width="93" height="68" align="right" border="0"></a></td>
|
|
</tr>
|
|
</table>
|
|
<br>
|
|
<table border="0">
|
|
<tr>
|
|
<td width="10"></td>
|
|
<td width="30"><a href="index.html"><img src="theme/u_arr.gif" border="0"></a></td>
|
|
<td width="30"><a href="class_reference_inputpolicy.html"><img src="theme/l_arr.gif" width="20" height="19" border="0"></a></td>
|
|
<td width="30"><a href="wave_driver.html"><img src="theme/r_arr.gif" border="0"></a></td>
|
|
</tr>
|
|
</table>
|
|
<p>In order to prepare a proposal for the C++ Standards committee, which should
|
|
describe certain new and enhanced preprocessor features, the Wave preprocessor
|
|
library has implemented experimental support for the following features:</p>
|
|
<p><a href="preliminary_cpp0x_support.html#variadic_macros">Variadic macros</a><br>
|
|
<a href="preliminary_cpp0x_support.html#placemarker_tokens">Placemarker tokens</a><br>
|
|
<a href="preliminary_cpp0x_support.html#token_pasting">Well defined token-pasting</a><br>
|
|
<a href="preliminary_cpp0x_support.html#macro_scoping">Macro scoping mechanism</a><br>
|
|
<a href="preliminary_cpp0x_support.html#new_alternative_tokens">New alternative tokens</a></p>
|
|
<p>The described features are enabled by the <tt>--c++0x</tt> command line option
|
|
of the <tt>Wave</tt> driver. Alternatively you can enable these features by
|
|
calling the <tt>wave::context<>::set_language()</tt> function with the
|
|
<tt>wave::support_cpp0x</tt> value. </p>
|
|
<h2><a name="variadic_macros"></a>Variadic macros</h2>
|
|
<p>Both variadic macros and placemarker tokens have already been added to C99
|
|
<a href="references.html#iso_c">[2]</a>. This represents an unnecessary incompatibility
|
|
between C and C++. Adding these facilities to the C++ preprocessor would cause
|
|
no code to break that is currently well-defined and would closing the gap between
|
|
C and C++ in this field.</p>
|
|
<p>Variadic macros were added to the C preprocessor as of C99 <a href="references.html#iso_c">[2]</a>.
|
|
They are, effectively, a way to pass a variable number of arguments to a macro.
|
|
The specific syntax is as follows:</p>
|
|
<pre> <span class="preprocessor">#define</span> A(...) <span class="preprocessor">__VA_ARGS__</span>
|
|
<span class="preprocessor">#define</span> B(a, ...) <span class="preprocessor">__VA_ARGS__</span>
|
|
|
|
A(1, 2, 3) <span class="comment">// expands to: 1, 2, 3</span>
|
|
B(1, 2, 3) <span class="comment">// expands to: 2, 3</span>
|
|
</pre>
|
|
<p>The ellipsis is used to denote that the macro can accept any number of trailing
|
|
arguments. It must always occur as the last formal parameter of the macro. The
|
|
variadic arguments passed to the macro are identified by the special symbol
|
|
<tt>__VA_ARGS__</tt> in the replacement list of a variadic macro. The use of
|
|
this symbol is prohibited in any other context.</p>
|
|
<h2><a name="placemarker_tokens"></a>Placemarker tokens</h2>
|
|
<p>Placemarker tokens (technically, preprocessing tokens) are simply a well-defined
|
|
way of passing "nothing" as a macro argument. This facility was also
|
|
added to the C preprocessor as of C99 <a href="references.html#iso_c">[2]</a>.</p>
|
|
<pre> <span class="preprocessor">#define</span> X(p) f(p)
|
|
X("abc") <span class="comment">// expands to: f("abc")</span>
|
|
X() <span class="comment">// expands to: f()</span>
|
|
|
|
<span class="preprocessor">#define</span> Y(a, b) <span class="keyword">int</span>[a][b]
|
|
Y(2, 2) <span class="comment">// expands to: int[2][2]</span>
|
|
Y(, 2) <span class="comment">// expands to: int[][2]</span>
|
|
</pre>
|
|
<p>Placemarker tokens are a natural counterpart to variadic macros. They formalize the optional nature of a variadic argument (or arguments) so that variadic macros appear similar to the variadic functions, but have been generalized to include named parameters as well.
|
|
</p>
|
|
<h2><a name="token_pasting"></a>Well defined token-pasting</h2>
|
|
<p>Currently, as of both C++98 and C99, if token-pasting results in multiple preprocessing
|
|
tokens, the behavior is undefined. For example,</p>
|
|
<pre> <span class="preprocessor">#define</span> PASTE(a, b) a <span class="preprocessor">##</span> b
|
|
PASTE(1, 2) <span class="comment">// okay</span>
|
|
PASTE(+, -) <span class="comment">// undefined behavior</span></pre>
|
|
<p>Token-pasting of unrelated tokens (i.e. token-pasting resulting in multiple
|
|
preprocessing tokens) is currently undefined for no substantial reason. It is
|
|
not dependent on architecture nor is it difficult for an implementation to diagnose.
|
|
Furthermore, retokenization is what most, if not all, preprocessors already
|
|
do and what most programmers already expect the preprocessor to do. Well-defined
|
|
behavior is simply standardizing existing practice and removing an arbitrary
|
|
and unnecessary undefined behavior from the standard.</p>
|
|
<p>To achieve well-defined behavior in this context <tt>Wave</tt> retokenizes
|
|
the result of the token-pasting and inserts the newly created token sequence
|
|
as the macro replacement text.</p>
|
|
<pre> PASTE(+, ==) <span class="comment">// expands to: += =</span></pre>
|
|
<h2><a name="macro_scoping"></a>Macro scoping mechanism</h2>
|
|
<p>One of the major problems of the preprocessor is that macro definitions do
|
|
not respect any of the scoping mechanisms of the core language. As history has
|
|
shown, this is a major inconvenience and drastically increases the likelihood
|
|
of name clashes within a translation unit. The solution is to add both a named
|
|
and unnamed scoping mechanism to the C++ preprocessor. This limits the scope
|
|
of macro definitions without limiting its accessibility. Here are the details.
|
|
</p>
|
|
<p>The scoping mechanism is implemented with the help of three new preprocessor
|
|
directives: <span class="preprocessor">#region</span>, <span class="preprocessor">#endregion</span>
|
|
and <span class="preprocessor">#import</span>. Additionally it changes minor
|
|
details of some of the existing preprocessor directives: <span class="preprocessor">#ifdef</span>,
|
|
<span class="preprocessor">#ifndef</span> and the <span class="preprocessor">operator
|
|
defined()</span>.</p>
|
|
<h3>The #region directive</h3>
|
|
<p>The <span class="preprocessor">#region</span> directive starts a new named
|
|
or unnamed macro scope.</p>
|
|
<h4>Syntax</h4>
|
|
<blockquote>
|
|
<p><tt>#region <qualified-identifier></tt></p>
|
|
<p> Where <tt><qualified-identifier></tt> is an optionally qualified name
|
|
defining the name of the region to open.<br>
|
|
This name is optional. If the name is omitted a nameless region is opened.
|
|
</p>
|
|
</blockquote>
|
|
<p>If the qualified identifier starts with an <tt>'::'</tt> the name is looked
|
|
up relative to the global scope (the <tt><qualified-identifier></tt> is
|
|
called <em>absolute</em>), if it starts with an identifier, the region is looked
|
|
up relative to the current open region (the <tt><qualified-identifier></tt>
|
|
is called <em>relative</em>). If the specified region is not defined, it is
|
|
created. </p>
|
|
<p>The <span class="preprocessor">#region</span> directive is opaque for all macro
|
|
definitions made outside this region, i.e. no macros defined inside of other
|
|
regions or at the global scope are directly accessible from inside the opened
|
|
region. To access such macros these must be imported (see the <span class="preprocessor">#import</span>
|
|
directive) or must be referred to through it's qualified name. </p>
|
|
<p>Regions may be nested. </p>
|
|
<p>A region may be re-opened (i.e. a <span class="preprocessor">#region</span>
|
|
directive with the same name is found at the same scope), and macros defined
|
|
inside the previous occurences of this region will be visible. </p>
|
|
<p>Region names and macro names of the same scope are stored into the same symbol
|
|
table. This implies, that at one scope there shall not be defined a region and
|
|
a macro with the same name.</p>
|
|
<p>Macros defined inside a nameless region may not be accessed from outside this
|
|
region. Further, from inside a nameless region it is not allowed to open an
|
|
enclosed region through an <em>absolute</em> name.</p>
|
|
<p>The argument of the <span class="preprocessor">#region</span> directive is
|
|
<strong>not</strong> subject to macro expansion before it is evaluated.</p>
|
|
<p>The following is a small code sample, which shows possible usages of preprocessor
|
|
regions.</p>
|
|
<pre> <span class="preprocessor">#define</span> A() 1
|
|
|
|
<span class="comment">/////////////////////////////////////</span>
|
|
<span class="preprocessor">#region</span> region_A
|
|
<span class="preprocessor"># define</span> B() 2
|
|
|
|
<span class="comment">/////////////////////////////////////</span>
|
|
<span class="preprocessor"># region</span> region_B
|
|
<span class="preprocessor"># define</span> C() 3
|
|
A() <span class="comment">// expands to: A()</span>
|
|
B() <span class="comment">// expands to: B()</span>
|
|
C() <span class="comment">// expands to: 3</span>
|
|
<span class="preprocessor"># endregion</span> <span class="comment">// region_B</span>
|
|
<span class="comment">/////////////////////////////////////</span>
|
|
|
|
A() <span class="comment">// expands to: A()</span>
|
|
B() <span class="comment">// expands to: 2</span>
|
|
C() <span class="comment">// expands to: C()</span>
|
|
region_B::C() <span class="comment">// expands to: 3</span>
|
|
::region_A::region_B::C() <span class="comment">// expands to: 3</span>
|
|
<span class="preprocessor">#endregion</span> <span class="comment">// region_A</span>
|
|
<span class="comment">/////////////////////////////////////</span>
|
|
|
|
A() <span class="comment">// expands to: 1</span>
|
|
B() <span class="comment">// expands to: B()</span>
|
|
region_A::B() <span class="comment">// expands to: 2</span>
|
|
::region_A::B() <span class="comment">// expands to: 2</span>
|
|
region_A::region_B::C() <span class="comment">// expands to: 3</span>
|
|
::region_A::region_B::C() <span class="comment">// expands to: 3</span>
|
|
|
|
<span class="preprocessor">#define</span> region_A ... <span class="comment">// error, name clash with region_A</span>
|
|
<span class="preprocessor">#region</span> A <span class="comment">// error, name clash with macro A</span>
|
|
<span class="preprocessor">#endregion</span>
|
|
</pre>
|
|
<h3>The #endregion directive</h3>
|
|
<p>The <span class="preprocessor">#endregion</span> directive closes the last
|
|
macro scope opened with a <span class="preprocessor">#region</span> directive
|
|
.</p>
|
|
<h4>Syntax</h4>
|
|
<blockquote>
|
|
<p><tt>#endregion</tt></p>
|
|
</blockquote>
|
|
<p>The <span class="preprocessor">#endregion</span> directive is opaque for all
|
|
macros defined inside the closed region. Macros defined inside this region may
|
|
be accessed from outside of this region only if imported (see the <span class="preprocessor">
|
|
#import</span> directive) or if referenced through qualified names specifying
|
|
the region and the macro name and if the region isn't unnamed.</p>
|
|
<p>The <span class="preprocessor">#region</span> and <span class="preprocessor">#endregion</span>
|
|
directives shall be balanced over the whole translation unit. Otherwise an error
|
|
is raised.</p>
|
|
<h3>The #import directive</h3>
|
|
<p>The <span class="preprocessor">#import</span> directive allows to import macros
|
|
or whole macro scopes into the current macro scope.</p>
|
|
<h4>Syntax</h4>
|
|
<blockquote>
|
|
<p><tt>#import <qualified-identifier> [, <qualified-identifier>
|
|
...]</tt></p>
|
|
</blockquote>
|
|
<blockquote>
|
|
<p>Where <tt><qualified-identifier></tt> is an optionally qualified name
|
|
defining the name of the macro or region to import. The <span class="preprocessor">#import</span>
|
|
directive may specify one or more comma separated qualified names.</p>
|
|
</blockquote>
|
|
<p>If the qualified identifier starts with an <tt>'::'</tt> the name is looked
|
|
up relative to the global scope (the <tt><qualified-identifier></tt> is
|
|
called <em>absolute</em>), if it starts with an identifier, the region is looked
|
|
up relative to the current open region (the <tt><qualified-identifier></tt>
|
|
is called <em>relative</em>). </p>
|
|
<p>If <tt><qualified-identifier></tt> refers to a macro, then the referenced
|
|
macro definition is made available in the current region, just if it were defined
|
|
here. Both macro definitions (the original macro definition and the imported
|
|
one) refer to the same macro. This is significant for disabling of a certain
|
|
macro during the rescanning of a replacement list. If one of the different instances
|
|
of the macro definition is marked as disabled for expansion, the others are
|
|
marked as disabled for expansion too.</p>
|
|
<p>If <tt><qualified-identifier></tt> refers to a region, then</p>
|
|
<ul>
|
|
<li>all macro definitions of the referenced region are made available in the
|
|
current region, just if these were defined here.</li>
|
|
<li> all sub-regions of the referenced region are made available from the current
|
|
region, just if these were defined as direct sub-regions of the current region.</li>
|
|
</ul>
|
|
<p> Imported macros may be undefined with the <span class="preprocessor">#undef</span>
|
|
directive as usual. This removes the referenced macro from the current region,
|
|
but leaves it unchanged in the original region, where it was defined initially.<br>
|
|
<br>
|
|
The argument of the <span class="preprocessor">#import</span> directive is <strong>not</strong>
|
|
subject to macro expansion before it is evaluated. </p>
|
|
<h3>Changes to the #ifdef, #ifndef directives and the operator defined()</h3>
|
|
<p>To fully support macro regions, the <span class="preprocessor">#ifdef</span>
|
|
and <span class="preprocessor">#ifndef</span> directives and the <span class="preprocessor">operator
|
|
defined()</span> may be used with qualified identifiers as its arguments too.
|
|
Therefor the following sample is completely wellformed (courtesy to Paul Mensonides):</p>
|
|
<pre> <span class="preprocessor"># ifndef</span> ::CHAOS_PREPROCESSOR::chaos::WSTRINGIZE_HPP
|
|
<span class="preprocessor"># region</span> ::CHAOS_PREPROCESSOR::chaos
|
|
<span class="preprocessor">#</span>
|
|
<span class="preprocessor"># define</span> WSTRINGIZE_HPP
|
|
<span class="preprocessor">#</span>
|
|
<span class="preprocessor"># include</span> <span class="copyright"><chaos/experimental/cat.hpp></span>
|
|
<span class="preprocessor">#</span>
|
|
<span class="preprocessor">#</span> <span class="comment">// wstringize</span>
|
|
<span class="preprocessor">#</span>
|
|
<span class="preprocessor"># define</span> wstringize(...) \
|
|
chaos::primitive_wstringize(__VA_ARGS__) \
|
|
<span class="comment">/**/</span>
|
|
<span class="preprocessor">#</span>
|
|
<span class="preprocessor">#</span> <span class="comment">// primitive_wstringize</span>
|
|
<span class="preprocessor">#</span>
|
|
<span class="preprocessor"># define</span> primitive_wstringize(...) \
|
|
chaos::primitive_cat(L, #__VA_ARGS__) \
|
|
<span class="comment">/**/</span>
|
|
<span class="preprocessor">#</span>
|
|
<span class="preprocessor"># endregion</span>
|
|
<span class="preprocessor"># endif</span>
|
|
|
|
<span class="preprocessor"># import</span> ::CHAOS_PREPROCESSOR
|
|
|
|
chaos::wstringize(a,b,c) <span class="comment">// L"a,b,c"</span>
|
|
</pre>
|
|
<p>In the context of the <span class="preprocessor">#ifdef</span> and <span class="preprocessor">#ifndef</span>
|
|
directives and the <span class="preprocessor">operator defined()</span> a qualified
|
|
macro name is considered to be defined if:</p>
|
|
<ul>
|
|
<li>all regions referenced by the qualified name exist (opened at least once)
|
|
and</li>
|
|
<li>the referenced macro scope contains the definition of a macro with the given
|
|
name.</li>
|
|
</ul>
|
|
<h2><a name="new_alternative_tokens"></a>New alternative tokens</h2>
|
|
<p>Vesa Karvonen recently suggested on the <a href="http://aspn.activestate.com/ASPN/Mail/Message/boost/1618972">Boost
|
|
mailing list</a> the following addition to the preprocessor, which is implemented
|
|
by <tt>Wave</tt> in C++0x mode.</p>
|
|
<p>Consider the following example:</p>
|
|
<pre> <span class="preprocessor">#define</span> ID(x) x
|
|
ID( ( )
|
|
ID( a , b )
|
|
ID( ) )</pre>
|
|
<p>The macro expansion of the above preprocessor code does not produce the intended
|
|
result: </p>
|
|
<pre> ( a , b )</pre>
|
|
<p>The basic idea is that the keywords <tt>__lparen__</tt>, <tt>__rparen__</tt>
|
|
and <tt>__comma__</tt> could be used in place of <span class="literal">'('</span>,
|
|
<span class="literal">')'</span> and <span class="literal">','</span>, respectively.
|
|
The <br>
|
|
above example would now become:</p>
|
|
<pre> <span class="preprocessor">#define</span> ID(x) x
|
|
ID( __lparen__ )
|
|
ID( a __comma__ b )
|
|
ID( __rparen__ )</pre>
|
|
<p>and it would expand into:</p>
|
|
<pre> __lparen__ a __comma__ b __rparen__</pre>
|
|
<p>which would be recognized in translation phases after macro replacement as
|
|
equivalent to the token sequence:</p>
|
|
<pre> ( a , b )</pre>
|
|
<p>This trivial extension makes it an order of magnitude easier to generate C++
|
|
code using the C++ preprocessor.</p>
|
|
<table border="0">
|
|
<tr>
|
|
<td width="10"></td>
|
|
<td width="30"><a href="index.html"><img src="theme/u_arr.gif" border="0"></a></td>
|
|
<td width="30"><a href="class_reference_inputpolicy.html"><img src="theme/l_arr.gif" width="20" height="19" border="0"></a></td>
|
|
<td width="30"><a href="wave_driver.html"><img src="theme/r_arr.gif" border="0"></a></td>
|
|
</tr>
|
|
</table>
|
|
<hr size="1">
|
|
<p class="copyright">Copyright © 2003-2004 Hartmut Kaiser<br>
|
|
Copyright © 2003 Paul Mensonides<br>
|
|
Copyright © 2003 Vesa Karvonen<br>
|
|
<br>
|
|
<font size="2">Use, modification and distribution is subject to the Boost Software
|
|
License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
</font> </p>
|
|
<span class="updated">Last updated:
|
|
<!-- #BeginDate format:fcAm1m -->Monday, January 5, 2004 14:57<!-- #EndDate -->
|
|
</span>
|
|
<p> </p>
|
|
</body>
|
|
</html>
|