Date: 2013-05-28
Reply to: Clark Nelson
Title: Feature testing: Summary of significant changes to C++14

Feature testing: Summary of significant changes to C++14

Process questions

Do we eventually want a WG21 vote on a numbered paper? Do we (also) eventually want a living document on a wiki?

What about recommendations for C++11?

Do we want to use github?

How can we gauge consensus within SG10 outside of a teleconference?

Introduction

For the sake of improved portability between partial implementations of C++14, WG21 (the ISO technical committee for the C++ programming language) recommends that implementers and programmers follow the guidelines in this document concerning feature-test macros.

Implementers who provide a new feature should define a macro with the recommended name, in the same circumstances under which the feature is available (for example, taking into account relevant command-line options), to indicate the presence of support for that feature.

Programmers who wish to determine whether a feature is available in an implementation should base that determination on the state of the macro with the recommended name. (The absence of a tested feature may result in a program with decreased functionality, or the relevant functionality may be provided in a different way. A program that strictly depends on support for a feature can just try to use the feature unconditionally; on an implementation lacking necessary support, translation will presumably fail.)

The introductory sections of N3435 are presented here for reference.

Introduction

In the transition from C++03 to C++11 — which of course is ongoing — much pain has been caused by different implementations adding new features in different orders.

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.

On the other hand, decltype was added to the working paper by N2343, adopted in 2007. EDG implemented it in 2007, GNU in 2008, and Microsoft by 2010.

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.

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 — for each implementation of interest.

An example: simultaneously too simple and too complicated

Here is some code that attempts to determine whether rvalue references are available in the implementation in use:

#ifndef __USE_RVALUE_REFERENCES
  #if (__GNUC__ > 4 || __GNUC__ == 4 && __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

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 — even though it is possible for a customer of EDG to implement a feature before EDG does.

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.

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.

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.

The following table itemizes all the changes that were made to the working draft for C++14 as specified in a WG21 technical document. (Changes that were made as specified in a core or library issue are not included.) The table is sorted by the section of the standard primarily affected.

Significant changes to C++14
Doc. No. Title Primary Section Macro name
Is the difference between clang's __has_feature and __has_extension important enough for us to specify/recommend/mandate?
Value
What do we want?
Header
Should there be a specific header instead of predefined?
N3472 Binary Literals in the C++ Core Language 2.14 __cpp_binary_literals predefined
N3323 A Proposal to Tweak Certain C++ Contextual Conversions 4 __cpp_contextual_conversions predefined
N3648 Wording Changes for Generalized Lambda-capture 5.1 __cpp_generalized_capture predefined
N3649 Generic (Polymorphic) Lambda Expressions 5.1 __cpp_generic_lambda predefined
N3664 Clarifying Memory Allocation 5.3 __cpp_new_merging
Is this really necessary?
predefined
N3624 Core Issue 1512: Pointer comparison vs qualification conversions 5.9, 5.10 Core issue fix, not a feature; no macro needed
N3652 Relaxing constraints on constexpr functions / constexpr member functions and implicit const 5.19, 7.1 __cpp_relaxed_constexpr
generalized instead of relaxed?
predefined
N3638 Return type deduction for normal functions 7.1 __cpp_return_type_deduction
Do we also want __cpp_decltype_auto?
predefined
N3639 Runtime-sized arrays with automatic storage duration 8.3 __cpp_runtime_array predefined
N3653 Member initializers and aggregates 8.5 __cpp_aggregate_nsdmi predefined
N3667 Drafting for Core 1402 12.8 Core issue fix, not a feature; no macro needed
N3651 Variable Templates 14, 14.7 __cpp_variable_templates predefined
N3669 Fixing constexpr member functions without const various Library fix, not a feature; no macro needed
N3673 C++ Library Working Group Ready Issues Bristol 2013 various Library issue fixes, not a feature; no macro needed
N3471 Constexpr Library Additions: utilities 20.2-20.4 __cpp_lib_constexpr_functions <utility>
N3469 Constexpr Library Additions: chrono 20.11 <chrono>
N3470 Constexpr Library Additions: containers 23.3 <array>
N3658 Compile-time integer sequences 20 __cpp_lib_integer_sequences <utility>
N3668 exchange() utility function 20 __cpp_lib_exchange_function <utility>
N3670 Wording for Addressing Tuples by Type 20.2-20.4 __cpp_lib_tuples_by_type <utility>
N3672 A proposal to add a utility class to represent optional objects 20.5 __cpp_lib_header_optional predefined
How to handle new headers?
N3656 make_unique 20.7 __cpp_lib_make_unique <memory>
N3421 Making Operator Functors greater<> 20.8 __cpp_lib_operator_functors <functional>
N3462 std::result_of and SFINAE 20.9 __cpp_lib_result_of_sfinae <functional>
N3545 An Incremental Improvement to integral_constant 20.9 __cpp_lib_improved_integral_constant <type_traits>
N3655 TransformationTraits Redux 20.9 __cpp_lib_transformation_trait_aliases <type_traits>
N3642 User-defined Literals for Standard Library Types 20.11, 21.7 __cpp_lib_type_udls <string>
<chrono>
N3662 C++ Dynamic Arrays 23.2, 23.3 __cpp_lib_header_dynarray predefined
How to handle new headers?
N3657 Adding heterogeneous comparison lookup to associative containers 23.4 __cpp_lib_heterogeneous_comparison <map>
<set>
N3644 Null Forward Iterators 24.2 __cpp_lib_null_iterators <iterator>
N3671 Making non-modifying sequence operations more robust 25.2 __cpp_lib_robust_sequences
This name is lame.
<algorithm>
N3654 Quoted Strings Library Proposal 27.7 __cpp_lib_quoted_string_io <iomanip>

C++11 Features

This list from Tom, captured as a place-holder.

UCHAR 
CONSTEXPR
DECLTYPE
RAW_STRINGS
RVALUE_REF
USER_DEFINED_LITERALS
VARIADIC_TEMPLATE
DOUBLESQUARE_ATTRIBUTES