<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=us-ascii" />
	<title>Standardized feature-test macros</title>
	<style type="text/css">
		.right
		{
			float: right;
		}
	</style>
</head>
<body>
	<table border="1" class="right" summary="This table provides identifying information for this document.">
		<tr>
			<th>Doc. No.:</th>
			<td>WG21/N3435<br />
				PL22.16/12-0125</td>
		</tr>
		<tr>
			<th>Date:</th>
			<td>2012-09-18</td>
		</tr>
		<tr>
			<th>Reply to:</th>
			<td>Clark Nelson</td>
		</tr>
		<tr>
			<th>Phone:</th>
			<td>+1-503-712-8433</td>
		</tr>
		<tr>
			<th>Email:</th>
			<td><a href="mailto:clark.nelson@intel.com">clark.nelson@intel.com</a></td>
		</tr>
	</table>
	<h1>Standardized feature-test macros</h1>
	<h2>Introduction</h2>
	<p>In the transition from C++03 to C++11 &mdash; which of course is ongoing &mdash;
		much pain has been caused by different implementations adding new features in different
		orders.</p>
	<p>For example, variadic templates were added to the working paper for C++11 by N2242,
		adopted by the committee in 2007. They were implemented and released by GNU in 2008.
		EDG implemented them in 2011. Microsoft apparently has yet to implement them.</p>
	<p>On the other hand, <code>decltype</code> was added to the working paper by N2343,
		adopted in 2007. EDG implemented it in 2007, GNU in 2008, and Microsoft by 2010.</p>
	<p>Implementers of portable code, such as Boost, Dinkumware and Plum Hall, are for practical
		purposes obliged to know exactly which features are and are not usable in each implementation
		of interest.</p>
	<p>Today, the only way to do that is to test, in an implementation-specific manner (probably
		using a version-number macro), whether the implementation is new enough to support
		the feature in question &mdash; for each implementation of interest.</p>
	<h2>An example: simultaneously too simple and too complicated</h2>
	<p>Here is some code that attempts to determine whether rvalue references are available
		in the implementation in use:</p>
	<pre>#ifndef __USE_RVALUE_REFERENCES
  #if (__GNUC__ > 4 || __GNUC__ == 4 &amp;&amp; __GNUC_MINOR__ >= 3) || \
      _MSC_VER >= 1600
    #if __EDG_VERSION__ > 0
      #define __USE_RVALUE_REFERENCES (__EDG_VERSION__ >= 410)
    #else
      #define __USE_RVALUE_REFERENCES 1
    #endif
  #elif __clang__
    #define __USE_RVALUE_REFERENCES __has_feature(cxx_rvalue_references)
  #else
    #define __USE_RVALUE_REFERENCES 0
  #endif
#endif</pre>
	<p>First, the GNU and Microsoft version numbers are checked to see if they are high
		enough. But then a check is made of the EDG version number, since that front end
		also has compatibility modes for both those compilers, and defines macros indicating
		(claimed) compatibility with them. If the feature wasn't implemented in the indicated
		EDG version, it is assumed that the feature is not available &mdash; even though
		it is possible for a customer of EDG to implement a feature before EDG does.</p>
	<p>Fortunately Clang has ways to test specifically for the presence of specific features.
		But unfortunately, the function-call-like syntax used for such tests won't work
		with a standard preprocessor, so this fine new feature winds up adding its own flavor
		of complexity to the mix.</p>
	<p>Also note that this code effectively assumes that the IBM and Oracle compilers do
		not implement rvalue references at all. That should not be interpreted as a slight
		to those compilers; it's just that this code has already gotten pretty complicated
		even before taking them into account.</p>
	<p>Also note that this code doesn't check to see if any required command-line option
		has been thrown to enable support for the feature in question, so it will get the
		wrong answer in many cases.</p>
	<h2>Moving forward</h2>
	<p>Obviously the issues with C++11 are water under the bridge; nothing we can do now
		will help software that's already in the field. But we really should consider what
		can reasonably be done to mitigate this problem for future revisions of the language.</p>
	<p>My proposal going forward would be to add an appendix to the working paper that associates
		a specific macro name with each new separable feature.</p>
	<p>The problem that immediately arises is how to define &ldquo;separable feature&rdquo;?</p>
	<p>I submit that the process by which features are added to the working paper effectively
		defines it for us. By the time the committee reaches consensus to add something,
		it has already been considered whether the &ldquo;something&rdquo; has the right
		granularity; whether it should have been split into multiple parts, or combined
		with something else. The form in which it is accepted can generaly be assumed to
		be separable (since it is considered and decided separately).</p>
	<p>The next question is how to decide on the spelling of the macro name?</p>
	<p>One simple possibility, based on our working definition of &ldquo;separable&rdquo;,
		would be to include the number of the document specifying the working paper changes
		by which the feature is added. For example, if we had been following this discipline
		for C++11, the presence of rvalue references in an implementation might have been
		tested by checking a macro named something like <code>__WG21_N2118</code>.</p>
	<p>Obviously, this is not exactly self-documenting. Selecting a human-readable macro
		name would effective require that every new proposal, before being accepted, specify
		the name of the corresponding test macro.</p>
	<p>It should be noted that, besides solving real-world coding problems, this appendix
		would also effectively answer the very interesting question: What's new in this
		revision of the standard?</p>
</body>
</html>
