<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
lang="en-us" xml:lang="en-us">
<head>
  <title>Integrating feature-test macros into the C++ WD</title>
  <meta charset="us-ascii" />
  <style type="text/css">
    tr {
      page-break-inside: avoid;
    }

    .editornote {
      /* display: none; */
      font-family: Cursive;
      background-color: Yellow;
    }

    .note {
      font-style: italic;
    }

    ins, .ins {
      text-decoration: underline;
      background-color: #CFC;
    }

    del {
      text-decoration: line-through;
      background-color: #FCC;
    }

    h2, h3, h4, p, pre, dl, table {
      background-color: inherit;
    }

      h2:before {
        content: "[" counter(h2) "]";
        padding-right: 0.25in;
      }

      h3:before {
        content: "[" counter(h2) "." counter(h3) "]";
        padding-right: 0.25in;
      }

      h4:before {
        content: "[" counter(h2) "." counter(h3) "." counter(h4) "]";
        padding-right: 0.25in;
      }

      h2.annex:before, h2.annex ~ h2:before {
        content: "[" counter(h2, upper-alpha) "]";
        padding-right: 0.25in;
      }

      h2.annex ~ h3:before, h2.annex ~ ins h3:before {
        content: "[" counter(h2, upper-alpha) "." counter(h3) "]";
        padding-right: 0.25in;
      }

      h2.annex ~ h4:before, h2.annex ~ ins h4:before {
        content: "[" counter(h2, upper-alpha) "." counter(h3) "." counter(h4) "]";
        padding-right: 0.25in;
      }

    h1 {
      counter-reset: h2 -2;
    }

    h2.annex {
      counter-reset: h2;
    }

    h2 {
      page-break-after: avoid;
      counter-increment: h2;
      counter-reset: h3 h4 p;
    }

    h3 {
      page-break-after: avoid;
      counter-increment: h3;
      counter-reset: h4 p;
    }

    h4 {
      page-break-after: avoid;
      counter-increment: h4;
      counter-reset: p;
    }

  </style>
</head>
<body>
  <table border="1">
    <tbody>
      <tr>
	<th>Doc. No.:</th>
	<td>P0941R0</td>
      </tr>
      <tr>
	<th>Date:</th>
	<td>2018-05-04</td>
      </tr>
      <tr>
	<th>Reply to:</th>
	<td><a href="mailto:ville.voutilainen@gmail.com">Ville Voutilainen</a><br/></td>
      </tr>
      <tr>
	<th>Audience:</th>
	<td>EWG, LEWG</td>
      </tr>
    </tbody>
  </table>

  <h1>Integrating feature-test macros into the C++ WD</h1>

  <h2>Preface</h2>
  <p>
    This revision of this paper proposes incorporating feature-testing macros
    into the working draft of the C++ standard.
  </p>

  <h2>Contents</h2>
  <ol>
    <li><a href="#intro">Introduction</a></li>
    <li><a href="#recs">Wording</a>
      <ol>
	<li><a href="#recs.hasattr">Testing for the presence of an attribute: <code>__has_cpp_attribute</code></a></li>
	<li><a href="#recs.cpp11">Feature-testing macros</a></li>
      </ol>
    </li>
    <li><a href="#recs.cpp98">Feedback question on RTTI and exceptions</a></li>
    <li><a href="#hist">Revision history</a></li>
  </ol>

  <h2 id="intro">Introduction</h2>
  <p>
    At the November 2017 (Albuquerque) meeting of WG21, there was a five-way poll of
		all of the C++ experts in attendance concerning
		their support for "Feature macros should be standardized in the IS, and we want to invite a proposal to be reviewed by EWG to discss the rationale and granularity." The
		results of the poll:
  </p>
  <table border="1">
    <thead>
      <tr>
	<th>Strongly favor</th>
	<th>Favor</th>
	<th>Neutral</th>
	<th>Oppose</th>
	<th>Strongly oppose</th>
      </tr>
    </thead>
    <tbody>
      <tr>
	<td>27</td>
	<td>21</td>
	<td>9</td>
	<td>4</td>
	<td>1</td>
      </tr>
    </tbody>
  </table>

  <p>
    The approach taken here is as follows:
    <ul>
      <li>For the macros incorporated, use the latest value from SD-6, and
	do not bump the numbers. This is done in order to avoid pointless breakage of existing code that uses the SD-6 macros.</li>
      <li>Library macros are defined both in the corresponding header for
	the library facility and in &lt;version&gt;.</li>
    </ul>
  </p>
  <h2>Wording</h2>
  <h3 id="recs.hasattr">Testing for the presence of an attribute: <code>__has_cpp_attribute</code></h3>
  <p>
    After [lex.literal], insert a new subsection of section [lex]
    with the following content:
  </p>

  <blockquote>
  <p>
  <dl class="grammar">
    <dt><dfn>has-attribute-expression</dfn>:</dt>
    <dd><code>__has_cpp_attribute (</code>
      <var>attribute-token</var>
      <code>)</code></dd>
  </dl>
  </p>
  
  <p>
    A
    <var>has-attribute-expression</var>
    shall appear only in the controlling constant
		expression of a <code>#if</code> or <code>#elif</code> directive ([cpp.cond] 16.1).
		The
    <var>has-attribute-expression</var>
    is replaced by a non-zero pp-number if the
		implementation supports an attribute with the specified name, and by the pp-number
		0 otherwise.
  </p>
  <p>
    For a standard attribute, the value of the <code>__has_cpp_attribute</code>
    macro is based on the year and month in which the attribute was voted into the working
		draft. In the case where the attribute is vendor-specific, the value is implementation-defined.
		However, in most cases it is expected that the availability of an attribute can
		be detected by any non-zero result.
  </p>
  <p>
    The <code>#ifdef</code> and <code>#ifndef</code> directives, and the <code>defined</code>
    conditional inclusion operator, shall treat <code>__has_cpp_attribute</code> as
		if it were the name of a defined macro. The identifier <code>__has_cpp_attribute</code>
    shall not appear in any context not mentioned in this section.
  </p>

  <p>
    This demonstrates a way to use the attribute <code>[[deprecated]]</code> only
		if it is available.
  </p>
  <pre>#ifndef __has_cpp_attribute
# define __has_cpp_attribute(x) 0
#endif
#if __has_cpp_attribute(deprecated)
# define ATTR_DEPRECATED(msg) [[deprecated(msg)]]
#else
# define ATTR_DEPRECATED(msg)
#endif
  </pre>
  </blockquote>

  <h3 id="recs.cpp11">Feature-testing macros</h3>

  <p>Drafting note: these are intended to match the latest
  values in SD-6. Wording review should check that that is indeed so.</p>
  <p>
    After [support.runtime], insert a new subsection of
    section [language.support] with the following content:
  </p>
  <blockquote>
  <p>
    The macros that are not predefined are defined in the header &lt;version&gt; in addition to the header specified in the table.
  </p>
  <table border="1">
    <thead>
      <tr>
	<th>Macro name</th>
	<th>Value</th>
	<th>Header</th>
      </tr>
    </thead>
    <tbody>
      <tr>
	<td><a id="__cpp_unicode_characters"><code>__cpp_unicode_characters</code></td>
	<td>200704</td>
	<td><em>predefined</em></td>
      </tr>
      <tr>
	<td><a id="__cpp_raw_strings"><code>__cpp_raw_strings</code></td>
	<td>200710</td>
	<td><em>predefined</em></td>
      </tr>
      <tr>
	<td><a id="__cpp_unicode_literals"><code>__cpp_unicode_literals</code></td>
	<td>200710</td>
	<td><em>predefined</em></td>
      </tr>
      <tr>
	<td><a id="__cpp_user_defined_literals"><code>__cpp_user_defined_literals</code></td>
	<td>200809</td>
	<td><em>predefined</em></td>
      </tr>
      <tr>
	<td><a><code>__cpp_threadsafe_static_init</code></td>
	<td>200806</td>
	<td><em>predefined</em></td>
      </tr>
      <tr>
	<td><a id="__cpp_lambdas"><code>__cpp_lambdas</code></td>
	<td>200907</td>
	<td><em>predefined</em></td>
      </tr>
      <tr>
	<td><a id="__cpp_range_based_for_200907"><code>__cpp_range_based_for</code></td>
	<td>200907</td>
	<td><em>predefined</em></td>
      </tr>
      <tr>
	<td><a id="__cpp_static_assert_200410"><code>__cpp_static_assert</code></td>
	<td>200410</td>
	<td><em>predefined</em></td>
      </tr>
      <tr>
	<td><a id="__cpp_decltype"><code>__cpp_decltype</code></td>
	<td>200707</td>
	<td><em>predefined</em></td>
      </tr>
      <tr>
	<td><a id="__cpp_attributes"><code>__cpp_attributes</code></td>
	<td>200809</td>
	<td><em>predefined</em></td>
      </tr>
      <tr>
	<td><a><code>__has_cpp_attribute(noreturn)</code></td>
	<td>200809</td>
	<td><em>predefined</em></td>
      </tr>
      <tr>
	<td><a><code>__has_cpp_attribute(carries_dependency)</code></td>
	<td>200809</td>
	<td><em>predefined</em></td>
      </tr>
      <tr>
	<td><a id="__cpp_rvalue_references"><code>__cpp_rvalue_references</code></td>
	<td>200610</td>
	<td><em>predefined</em></td>
      </tr>
      <tr>
	<td><a id="__cpp_variadic_templates"><code>__cpp_variadic_templates</code></td>
	<td>200704</td>
	<td><em>predefined</em></td>
      </tr>
      <tr>
	<td><a id="__cpp_initializer_lists"><code>__cpp_initializer_lists</code></td>
	<td>200806</td>
	<td><em>predefined</em></td>
      </tr>
      <tr>
	<td><a id="__cpp_delegating_constructors"><code>__cpp_delegating_constructors</code></td>
	<td>200604</td>
	<td><em>predefined</em></td>
      </tr>
      <tr>
	<td><a id="__cpp_nsdmi"><code>__cpp_nsdmi</code></td>
	<td>200809</td>
	<td><em>predefined</em></td>
      </tr>
      <tr>
	<td><a id="__cpp_ref_qualifiers"><code>__cpp_ref_qualifiers</code></td>
	<td>200710</td>
	<td><em>predefined</em></td>
      </tr>
      <tr>
	<td><a id="__cpp_alias_templates"><code>__cpp_alias_templates</code></td>
	<td>200704</td>
	<td><em>predefined</em></td>
      </tr>

      <tr>
	<td><code>__cpp_binary_literals</code></td>
	<td>201304</td>
	<td><em>predefined</em></td>
      </tr>
      <tr>
	<td><code>__cpp_init_captures</code></td>
	<td>201304</td>
	<td><em>predefined</em></td>
      </tr>
      <tr>
	<td><code>__cpp_generic_lambdas</code></td>
	<td>201304</td>
	<td><em>predefined</em></td>
      </tr>
      <tr>
	<td><code>__cpp_sized_deallocation</code></td>
	<td>201309</td>
	<td><em>predefined</em></td>
      </tr>
      <tr>
	<td><code>__cpp_decltype_auto</code></td>
	<td>201304</td>
	<td><em>predefined</em></td>
      </tr>
      <tr>
	<td><code>__cpp_return_type_deduction</code></td>
	<td>201304</td>
	<td><em>predefined</em></td>
      </tr>
      <tr>
	<td><code>__has_cpp_attribute(deprecated)</code></td>
	<td>201309</td>
	<td><em>predefined</em></td>
      </tr>
      <tr>
	<td><code>__cpp_aggregate_nsdmi</code></td>
	<td>201304</td>
	<td><em>predefined</em></td>
      </tr>
      <tr>
	<td><code>__cpp_variable_templates</code></td>
	<td>201304</td>
	<td><em>predefined</em></td>
      </tr>
      <tr>
	<td><code>__cpp_lib_integer_sequence</code></td>
	<td>201304</td>
	<td><code>&lt;utility&gt;</code></td>
      </tr>
      <tr>
	<td><code>__cpp_lib_exchange_function</code></td>
	<td>201304</td>
	<td><code>&lt;utility&gt;</code></td>
      </tr>
      <tr>
	<td><code>__cpp_lib_tuples_by_type</code></td>
	<td>201304</td>
	<td><code>&lt;utility&gt;</code></td>
      </tr>
      <tr>
	<td><code>__cpp_lib_tuple_element_t</code></td>
	<td>201402</td>
	<td><code>&lt;utility&gt;</code></td>
      </tr>
      <tr>
	<td><code>__cpp_lib_make_unique</code></td>
	<td>201304</td>
	<td><code>&lt;memory&gt;</code></td>
      </tr>
      <tr>
	<td><code>__cpp_lib_transparent_operators</code>
	</td>
	<td>201210</td>
	<td><code>&lt;functional&gt;</code></td>
      </tr>
      <tr>
	<td><code>__cpp_lib_integral_constant_callable</code>
	</td>
	<td>201304</td>
	<td><code>&lt;type_traits&gt;</code></td>
      </tr>
      <tr>
	<td><code>__cpp_lib_transformation_trait_aliases</code>
	</td>
	<td>201304</td>
	<td><code>&lt;type_traits&gt;</code></td>
      </tr>
      <tr>
	<td><code>__cpp_lib_result_of_sfinae</code></td>
	<td>201210</td>
	<td><code>&lt;functional&gt;</code><br />
	  <code>&lt;type_traits&gt;</code></td>
      </tr>
      <tr>
	<td><code>__cpp_lib_is_final</code></td>
	<td>201402</td>
	<td><code>&lt;type_traits&gt;</code></td>
      </tr>
      <tr>
	<td><code>__cpp_lib_is_null_pointer</code></td>
	<td>201309</td>
	<td><code>&lt;type_traits&gt;</code></td>
      </tr>
      <tr>
	<td><code>__cpp_lib_string_udls</code></td>
	<td>201304</td>
	<td><code>&lt;string&gt;</code></td>
      </tr>
      <tr>
	<td><code>__cpp_lib_generic_associative_lookup</code>
	</td>
	<td>201304</td>
	<td><code>&lt;map&gt;</code><br />
	  <code>&lt;set&gt;</code></td>
      </tr>
      <tr>
	<td><code>__cpp_lib_null_iterators</code></td>
	<td>201304</td>
	<td><code>&lt;iterator&gt;</code></td>
      </tr>
      <tr>
	<td><code>__cpp_lib_make_reverse_iterator</code>
	</td>
	<td>201402</td>
	<td><code>&lt;iterator&gt;</code></td>
      </tr>
      <tr>
	<td><code>__cpp_lib_robust_nonmodifying_seq_ops</code>
	</td>
	<td>201304</td>
	<td><code>&lt;algorithm&gt;</code></td>
      </tr>
      <tr>
	<td><code>__cpp_lib_complex_udls</code></td>
	<td>201309</td>
	<td><code>&lt;complex&gt;</code></td>
      </tr>
      <tr>
	<td><code>__cpp_lib_quoted_string_io</code></td>
	<td>201304</td>
	<td><code>&lt;iomanip&gt;</code></td>
      </tr>
      <tr>
	<td><code>__has_include(&lt;shared_mutex&gt;)</code>
	</td>
	<td>1</td>
	<td><em>predefined</em></td>
      </tr>
      <tr>
	<td><code>__cpp_lib_shared_timed_mutex</code></td>
	<td>201402</td>
	<td><code>&lt;shared_mutex&gt;</code></td>
      </tr>
      <tr>
	<td><code>__cpp_hex_float</code>
	  </td>
	<td>201603</td>
	<td><em>predefined</em></td>
      </tr>
      <tr>
	<td><code>__cpp_inline_variables</code></td>
	<td>201606</td>
	<td><em>predefined</em></td>
      </tr>
      <tr>
	<td><code>__cpp_aligned_new</code>
	  </td>
	<td>201606</td>
	<td><em>predefined</em></td>
      </tr>
      <tr>
	<td><code>__cpp_guaranteed_copy_elision</code></td>
	<td>201606</td>
	<td><em>predefined</em></td>
      </tr>
      <tr>
	<td><code>__cpp_noexcept_function_type</code>
	  </td>
	<td>201510</td>
	<td><em>predefined</em></td>
      </tr>
      <tr>
	<td><code>__cpp_fold_expressions</code></td>
	<td>201411</td>
	<td><em>predefined</em></td>
      </tr>
      <tr>
	<td><code>__cpp_capture_star_this</code>
	  </td>
	<td>201603</td>
	<td><em>predefined</em></td>
      </tr>
      <tr>
	<td><code>__cpp_constexpr</code></td>
	<td>201603</td>
	<td><em>predefined</em></td>
      </tr>
      <tr>
	<td><code>__cpp_if_constexpr</code>
	  </td>
	<td>201606</td>
	<td><em>predefined</em></td>
      </tr>
      <tr>
	<td><code>__cpp_range_based_for</code></td>
	<td>201603</td>
	<td><em>predefined</em></td>
      </tr>
      <tr>
	<td><code>__cpp_static_assert</code></td>
	<td>201411</td>
	<td><em>predefined</em></td>
      </tr>
      <tr>
	<td><code>__cpp_deduction_guides</code>
	  </td>
	<td>201606</td>
	<td><em>predefined</em></td>
      </tr>
      <tr>
	<td><code>__cpp_deduction_guides</code>
	  </td>
	<td>201611</td>
	<td><em>predefined</em></td>
      </tr>
      <tr>
	<td>
	  <code>__cpp_nontype_template_parameter_auto</code>
	    </td>
	<td>201606</td>
	<td><em>predefined</em></td>
      </tr>
      <tr>
	<td><code>__cpp_namespace_attributes</code></td>
	<td>201411</td>
	<td><em>predefined</em></td>
      </tr>
      <tr>
	<td><code>__cpp_enumerator_attributes</code></td>
	<td>201411</td>
	<td><em>predefined</em></td>
      </tr>
      <tr>
	<td><code>__cpp_inheriting_constructors</code>
	</td>
	<td>201511</td>
	<td><em>predefined</em></td>
      </tr>
      <tr>
	<td><code>__cpp_variadic_using</code></td>
	<td>201611</td>
	<td><em>predefined</em></td>
      </tr>
      <tr>
	<td><code>__has_cpp_attribute(fallthrough)</code></td>
	<td>201603</td>
	<td><em>predefined</em></td>
      </tr>
      <tr>
	<td><code>__has_cpp_attribute(nodiscard)</code></td>
	<td>201603</td>
	<td><em>predefined</em></td>
      </tr>
      <tr>
	<td><code>__has_cpp_attribute(maybe_unused)</code></td>
	<td>201603</td>
	<td><em>predefined</em></td>
      </tr>
      <tr>
	<td><code>__cpp_structured_bindings</code>
	  </td>
	<td>201606</td>
	<td><em>predefined</em></td>
      </tr>
      <tr>
	<td><code>__cpp_aggregate_bases</code>
	  </td>
	<td>201603</td>
	<td><em>predefined</em></td>
      </tr>
      <tr>
	<td><code>__cpp_nontype_template_args</code></td>
	<td>201411</td>
	<td><em>predefined</em></td>
      </tr>
      <tr>
	<td><code>__cpp_template_template_args</code>
	  
	</td>
	<td>201611</td>
	<td><em>predefined</em></td>
      </tr>
      <tr>
	<td><code>__cpp_fold_expressions</code></td>
	<td>201603</td>
	<td><em>predefined</em></td>
      </tr>
      <tr>
	<td><code>__has_include</code></td>
	<td><em>defined</em></td>
	<td><em>predefined</em></td>
      </tr>
      <tr>
	<td><code>__cpp_lib_byte</code>
	  </td>
	<td>201603</td>
	<td><code>&lt;cstddef&gt;</code></td>
      </tr>
      <tr>
	<td><code>__cpp_lib_hardware_interference_size</code>
	  </td>
	<td>201703</td>
	<td><code>&lt;new&gt;</code></td>
      </tr>
      <tr>
	<td><code>__cpp_lib_launder</code>
	  </td>
	<td>201606</td>
	<td><code>&lt;new&gt;</code></td>
      </tr>
      <tr>
	<td><code>__cpp_lib_uncaught_exceptions</code></td>
	<td>201411</td>
	<td><code>&lt;exception&gt;</code></td>
      </tr>
      <tr>
	<td><code>__cpp_lib_as_const</code>
	  </td>
	<td>201510</td>
	<td><code>&lt;utility&gt;</code></td>
      </tr>
      <tr>
	<td><code>__cpp_lib_make_from_tuple</code>
	  </td>
	<td>201606</td>
	<td><code>&lt;tuple&gt;</code></td>
      </tr>
      <tr>
	<td><code>__cpp_lib_apply</code>
	  </td>
	<td>201603</td>
	<td><code>&lt;tuple&gt;</code></td>
      </tr>
      <tr>
	<td><code>__has_include(&lt;optional&gt;)</code></td>
	<td>1</td>
	<td><em>predefined</em></td>
      </tr>
      <tr>
	<td><code>__cpp_lib_optional</code></td>
	<td id="__cpp_lib_optional_201603">201603</td>
	<td><code>&lt;optional&gt;</code></td>
      </tr>
      <tr>
	<td><code>__has_include(&lt;any&gt;)</code></td>
	<td>1</td>
	<td><em>predefined</em></td>
      </tr>
      <tr>
	<td><code>__cpp_lib_any</code></td>
	<td>201603</td>
	<td><code>&lt;any&gt;</code></td>
      </tr>
      <tr>
	<td><code>__has_include(&lt;memory_resource&gt;)</code></td>
	<td>1</td>
	<td><em>predefined</em></td>
      </tr>
      <tr>
	<td><code>__cpp_lib_memory_resource</code></td>
	<td>201603</td>
	<td><code>&lt;memory_resource&gt;</code></td>
      </tr>
      <tr>
	<td><code>__cpp_lib_boyer_moore_searcher</code>
	  </td>
	<td>201603</td>
	<td><code>&lt;functional&gt;</code></td>
      </tr>
      <tr>
	<td><code>__has_include(&lt;string_view&gt;)</code></td>
	<td>1</td>
	<td><em>predefined</em></td>
      </tr>
      <tr>
	<td><code>__cpp_lib_string_view</code></td>
	<td>201603</td>
	<td><code>&lt;string_view&gt;</code></td>
      </tr>
      <tr>
	<td><code>__cpp_lib_sample</code>
	  </td>
	<td>201603</td>
	<td><code>&lt;algorithm&gt;</code></td>
      </tr>
      <tr>
	<td><code>__cpp_lib_any</code>
	  
	</td>
	<td>201606</td>
	<td><code>&lt;any&gt;</code></td>
      </tr>
      <tr>
	<td><code>__cpp_lib_optional</code>
	</td>
	<td>201606</td>
	<td><code>&lt;optional&gt;</code></td>
      </tr>
      <tr>
	<td><code>__cpp_lib_optional</code></td>
	<td>201606</td>
	<td><code>&lt;optional&gt;</code></td>
      </tr>
      <tr>
	<td><code>__has_include(&lt;variant&gt;)</code></td>
	<td>1</td>
	<td><em>predefined</em></td>
      </tr>
      <tr>
	<td><code>__cpp_lib_variant</code>
	</td>
	<td>201606</td>
	<td><code>&lt;variant&gt;</code></td>
      </tr>
      <tr>
	<td><code>__cpp_lib_addressof_constexpr</code></td>
	<td>201603</td>
	<td><code>&lt;memory&gt;</code></td>
      </tr>
      <tr>
	<td><code>__cpp_lib_raw_memory_algorithms</code></td>
	<td>201606</td>
	<td><code>&lt;memory&gt;</code></td>
      </tr>
      <tr>
	<td><code>__cpp_lib_transparent_operators</code></td>
	<td>201510</td>
	<td><code>&lt;memory&gt; &lt;functional&gt;</code>
	</td>
      </tr>
      <tr>
	<td><code>__cpp_lib_enable_shared_from_this</code></td>
	<td>201603</td>
	<td><code>&lt;memory&gt;</code></td>
      </tr>
      <tr>
	<td><code>__cpp_lib_shared_ptr_weak_type</code></td>
	<td>201606</td>
	<td><code>&lt;memory&gt;</code></td>
      </tr>
      <tr>
	<td><code>__cpp_lib_shared_ptr_arrays</code>
	  </td>
	<td>201611</td>
	<td><code>&lt;memory&gt;</code></td>
      </tr>
      <tr>
	<td><code>__cpp_lib_invoke</code></td>
	<td>201411</td>
	<td><code>&lt;functional&gt;</code></td>
      </tr>
      <tr>
	<td><code>__cpp_lib_not_fn</code>
	  </td>
	<td>201603</td>
	<td><code>&lt;functional&gt;</code></td>
      </tr>
      <tr>
	<td><code>__cpp_lib_void_t</code></td>
	<td>201411</td>
	<td><code>&lt;type_traits&gt;</code></td>
      </tr>
      <tr>
	<td><code>__cpp_lib_bool_constant</code></td>
	<td>201505</td>
	<td><code>&lt;type_traits&gt;</code></td>
      </tr>
      <tr>
	<td><code>__cpp_lib_type_trait_variable_templates</code>
	  </td>
	<td>201510</td>
	<td><code>&lt;type_traits&gt;</code></td>
      </tr>
      <tr>
	<td><code>__cpp_lib_logical_traits</code></td>
	<td>201510</td>
	<td><code>&lt;type_traits&gt;</code></td>
      </tr>
      <tr>
	<td><code>__cpp_lib_is_swappable</code>
	</td>
	<td>201603</td>
	<td><code>&lt;type_traits&gt;</code></td>
      </tr>
      <tr>
	<td><code>__cpp_lib_is_invocable</code>
	  </td>
	<td>201703</td>
	<td><code>&lt;type_traits&gt;</code></td>
      </tr>
      <tr>
	<td><code>__cpp_lib_has_unique_object_representations</code>
	  </td>
	<td>201606</td>
	<td><code>&lt;type_traits&gt;</code></td>
      </tr>
      <tr>
	<td><code>__cpp_lib_is_aggregate</code>
	  </td>
	<td>201703</td>
	<td><code>&lt;type_traits&gt;</code></td>
      </tr>
      <tr>
	<td><code>__cpp_lib_chrono</code>
	  </td>
	<td>201611</td>
	<td><code>&lt;chrono&gt;</code></td>
      </tr>
      <tr>
	<td><code>__has_include(&lt;execution&gt;)</code></td>
	<td>1</td>
	<td><em>predefined</em></td>
      </tr>
      <tr>
	<td>
	  <code>__cpp_lib_execution</code></td>
	<td>201603</td>
	<td><code>&lt;execution&gt;</code></td>
      </tr>
      <tr>
	<td><code>__cpp_lib_parallel_algorithm</code>
	  
	</td>
	<td>201603</td>
	<td><code>&lt;algorithm&gt;</code> <code>&lt;numeric&gt;</code></td>
      </tr>
      <tr>
	<td><code>__cpp_lib_to_chars</code>
	  </td>
	<td>201611</td>
	<td><code>&lt;utility&gt;</code></td>
      </tr>
      <tr>
	<td><code>__cpp_lib_string_view</code></td>
	<td>201606</td>
	<td><code>&lt;string&gt; &lt;string_view&gt;</code></td>
      </tr>
      <tr>
	<td><code>__cpp_lib_allocator_traits_is_always_equal</code></td>
	<td>201411</td>
	<td><code>&lt;memory&gt;</code> <code>&lt;scoped_allocator&gt;</code><br />
	  <code>&lt;string&gt;</code> <code>&lt;deque&gt;</code><br />
	  <code>&lt;forward_list&gt;</code> <code>&lt;list&gt;</code><br />
	  <code>&lt;vector&gt;</code> <code>&lt;map&gt;</code><br />
	  <code>&lt;set&gt;</code> <code>&lt;unordered_map&gt;</code><br />
	  <code>&lt;unordered_set&gt;</code>
	</td>
      </tr>
      <tr>
	<td><code>__cpp_lib_incomplete_container_elements</code>
	  </td>
	<td>201505</td>
	<td><code>&lt;forwardlist&gt<br />
	  &lt;list&gt; &lt;vector&gt;</code></td>
      </tr>
      <tr>
	<td><code>__cpp_lib_map_try_emplace</code></td>
	<td>201411</td>
	<td><code>&lt;map&gt;</code></td>
      </tr>
      <tr>
	<td>
	  <code>__cpp_lib_unordered_map_try_emplace</code></td>
	<td>201411</td>
	<td><code>&lt;unordered_map&gt;</code></td>
      </tr>
      <tr>
	<td><code>__cpp_lib_node_extract</code></td>
	<td>201606</td>
	<td><code>&lt;map&gt; &lt;set&gt; &lt;unordered_map&gt; &lt;unordered_set&gt;</code></td>
      </tr>
      <tr>
	<td><code>__cpp_lib_array_constexpr</code>
	  </td>
	<td>201603</td>
	<td><code>&lt;iterator&gt; &lt;array&gt;</code></td>
      </tr>
      <tr>
	<td><code>__cpp_lib_nonmember_container_access</code></td>
	<td>201411</td>
	<td><code>&lt;iterator&gt; &lt;array&gt; &lt;deque&gt; &lt;forward_list&gt;<br />
	  &lt;list&gt; &lt;map&gt; &lt;regex&gt; &lt;set&gt; &lt;string&gt;<br />
	  &lt;unordered_map&gt; &lt;unordered_set&gt; &lt;vector&gt;</code></td>
      </tr>
      <tr>
	<td><code>__cpp_lib_clamp</code>
	  </td>
	<td>201603</td>
	<td><code>&lt;algorithm&gt;</code></td>
      </tr>
      <tr>
	<td><code>__cpp_lib_gcd_lcm</code>
	  </td>
	<td>201606</td>
	<td><code>&lt;numeric&gt;</code></td>
      </tr>
      <tr>
	<td><code>__cpp_lib_hypot</code>
	  </td>
	<td>201603</td>
	<td><code>&lt;cmath&gt;</code></td>
      </tr>
      <tr>
	<td><code>__cpp_lib_math_special_functions</code>
	  </td>
	<td>201603</td>
	<td><code>&lt;cmath&gt;</code></td>
      </tr>
      <tr>
	<td><code>__has_include(&lt;filesystem&gt;)</code></td>
	<td>1</td>
	<td><em>predefined</em></td>
      </tr>
      <tr>
	<td><code>__cpp_lib_filesystem</code></td>
	<td>201703</td>
	<td><code>&lt;filesystem&gt;</code></td>
      </tr>
      <tr>
	<td><code>__cpp_lib_atomic_is_always_lock_free</code>
	  </td>
	<td>201603</td>
	<td><code>&lt;atomic&gt;</code></td>
      </tr>
      <tr>
	<td><code>__cpp_lib_shared_mutex</code>
	  </td>
	<td>201505</td>
	<td><code>&lt;shared_mutex&gt;</code></td>
      </tr>
      <tr>
	<td><code>__cpp_lib_scoped_lock</code>
	  </td>
	<td>201703</td>
	<td><code>&lt;mutex&gt;</code></td>
      </tr>
    </tbody>
  </table>
  </blockquote>
  <h2 id="recs.cpp98">Feedback question on RTTI and exceptions</h2>
  <p>
    With very few exceptions,
    the features of C++98 have all been implemented
    in virtually every C++ compiler.
    But in many compilers, some of them can be enabled/disabled.
    It is recommended that the macros in the following table
    should be used to indicate whether one of these features
    is enabled in the current compilation.
  </p>
  <table border="1">
    <thead>
      <tr>
	<th>Macro name</th>
	<th>Value</th>
	<th>Header</th>
      </tr>
    </thead>
    <tbody>
      <tr>
	<td><code><a id="__cpp_rtti">__cpp_rtti</code></td>
	<td>199711</td>
	<td><em>predefined</em></td>
      </tr>
      <tr>
	<td><code><a id="__cpp_exceptions">__cpp_exceptions</code></td>
	<td>199711</td>
	<td><em>predefined</em></td>
      </tr>
    </tbody>
  </table>

  <h2 id="hist">Revision history</h2>
  <table border="1">
    <thead>
      <tr>
	<th>Date</th>
	<th>Document</th>
	<th>Description</th>
      </tr>
    </thead>
    <tbody>
      <tr>
	<td></td>
	<td>P0941R0</td>
	<td>Initial draft</td>
      </tr>
      <tr>
	<td></td>
	<td>P0941R1</td>
	<td>Draft wording, with non-standard content removed
	and rtti/exception macros made a separate point looking for feedback.</td>
      </tr>
    </tbody>
  </table>
</body>
</html>
