Doc. no.   J16/03-0141=WG21/N1588
Date:        14 November 2003
Project:     Programming Language C++
Reply to:   Beman Dawes <bdawes@acm.org>

Library Technical Report Component Detection

Motivation
Requirements and Objectives
Design Rationale
Granularity of macros
Transition between the TR and future standards
Names
Proposed additions to the TR

Motivation

Because the Library Technical Report (TR) is non-normative, implementers are permitted to ship partial implementations or to not implement the TR at all. At least one vendor has already begun shipping a partial implementation.

Users wishing to write portable programs that use TR components must therefore determine which TR components are actually available.

For example, several Boost libraries already use a component availability macro (BOOST_HAS_HASH) to determine if a non-standard hash map is available. If present, they use hash maps to speed execution, but otherwise rely on std::map.

Similarly, users of the Library TR code may wish to code something like this:

# include <some_std_lib_header>
# ifdef __TR12345_UNORDERED__
#   include <unordered_map>
# else
#   include <map>
# endif

(For brevity, the example above ignores namespace and other naming issues.)

Such usage is portable if the header and component macro are specified as part of the Library TR. If not specified by the TR, then users are forced to develop their own configuration mechanisms to determine TR component availability. This would be a serious burden for users wishing to write portable code.

A second use case might occur when user code requires std::tr1 components, and wishes to issue an explicit error message when they are not present:

# include <some_std_lib_header>
# ifndef __TR12345_UNORDERED__
#   error Standard Library Technical Report <unordered_map> header required
# endif

Note: This proposal does not deal with the question of how users request that std::tr1 components be made available by an implementation. That is an orthogonal issue, and is already dealt with in the TR working paper.

Requirements and Objectives

To provide a useful level of functionality to users without unduly burdening implementers, a design needs to consider the following as at least objectives if not downright requirements:

  1. Portable and consistent across implementations.

    Rationale: The whole point of specifying component availability reporting in the TR is to ensure it is portable. If component availability reporting is not consistent across implementations, users cannot write portable code.
     
  2. Existing standard library implementations already report std::tr1 component availability correctly.

    Rationale: Ensures a smooth transition for users and implementers.

    Implications: Component availability must be reported by presence rather than absence macros (assuming macros are the mechanism). The macros must reside in a current standard library header to ensure that current implementations are already conforming.
     
  3. Falsely reporting a component as not available is acceptable (although obviously not desirable). Falsely reporting a component as available is not acceptable.

    Rationale: Safety. Reliability.
     
  4. Works well with partial implementations of the TR.

    Rationale: Because the TR is non-normative, implementers are not required to provide all components. For example, an implementation may choose not to provide the special functions. Even if an implementation plans future support for the full TR, such full support may take several releases to become available.

    Implication: There needs to be some granularity in the reporting.
     
  5. Low overhead for users of the availability reporting, and no significant cost to programs not concerned with component availability reporting.

    Implications: Component macros should appear in a nominally low-cost header - not <iostream>, for example.
     
  6. Easy to specify, understand, implement, and use.

    Rationale: Feature detection is the appetizer, not the main meal. KISS.
     
  7. Compatible with C language. This may be a red-herring, but we should at least run this proposal by the C committee to see if they have any concerns or suggestions.

    Rationale: Since the C committee has indicated an intent to make the TR Special Functions available to C programmers, the C++ committee should strive to avoid gratuitous incompatibilities with the C language version.

Design Rationale

Much of the design is driven by the Requirements and Objectives.

The <limits> header is chosen as the location of the macros since it best meets requirements (2), (5). Requirement (5) implies the macros are defined in existing headers, so a new header can't be used.

The proposed granularity is based on intuition rather than any hard-and-fast rule. If the granularity is too fine, implementations will diverge through honest confusion, and the names will be hard to remember. If the granularity is too coarse, there will be a mismatch between what components some implementers will wish to actually deliver and what components the macros identify.

Granularity of macros

Pete Becker expressed concern over the fine granularity of the macros in c++std-lib-12274. Discussion followed.

Given that implementers are already shipping partial implementations of the TR, I continue to propose moderately macros with some granularity. I'm not adverse to reducing the granularity somewhat, but I feel it greatly benefits users to have some granularity.

Transition between the TR and future standards

Several LWG members expressed concern over the transition between the TR and future standards.

Two notes have been added to the proposal to make it clear to users that in the transition from the TR to future standards, the TR components will not remain in namespace std::tr1 and the configuration macros will disappear.

Names

The proposed text below uses __TRn as a macro name prefix, where n is to be replaced by the ISO/IEC  number assigned to the Technical Report. Other prefixes are possible.

Proposed Additions to the Library Technical Report

Proposed addition 1 (after [tr.intro.namespaces])

[Note: Should any library components from this technical report become part of a future version of the C++ standard, they will be placed in a namespace other than std::tr1. --end note]

Proposed addition 2 (at the end of [tr.intro])

The availability of components described in this technical report are reported by the presence of the macros described in the Component Availability Macros Table. Each macro shall be defined if and only if the entire component it identifies is available. Each macro definition shall appear in the standard's <limits> header and in all other standard library or technical report headers containing the component or partial component that it identifies . The value of each macro is unspecified.

[Note: These macros will not appear in future versions of the C++ standard. Future versions of the standard can be identified by the value of the predefined macro __cplusplus. --end note]

Component Availability Macros Table

[Note to editor: replace n below by the ISO/IEC  number assigned to the Technical Report.]

Macro Component
__TRn__ All. [note - not defined unless all TR components are available. - end note]
__TRn_UTILITY__ Reference wrappers ([tr.util.refwrp.synopsis])
__TRn_MEMORY__ Smart Pointers ([tr.util.smartptr])
__TRn_FUNCTIONAL__ Function objects and higher-order programming. ([tr.func])
__TRn_TYPE_TRAITS__ Metaprogramming and type traits ([tr.meta])
__TRn_RANDOM__ Random number generation ([tr.rand])
__TRn_MATH__ Mathematical special functions ([tr.rand])
__TRn_TUPLE__ Tuple types ([tr.tuple])
__TRn_UNORDERED__ Unordered associative containers ([tr.hash]) [note - also defined in <functional>. - end note]
__TRn_REGEX__ Regular expressions ([tr.re])
__TRn_ARRAY__ Fixed size array wrapper ([TBD])
__TRn_ITERATOR__ Iterator concepts, facades, and adaptors ([TBD])
__TRn_C99__ C99 library ([TBD])

Copyright Beman Dawes, 2003.

Revised 14 November, 2003