Doc. no.: P0996R1
Date: 2018-03-16
Project: Programming Language C++
Audience: Library Evolution Working Group
Library Working Group
Reply to: Alisdair Meredith <ameredith1@bloomberg.net>

Rebase Library Fundamentals TS on C++17

Table of Contents

Revision History

Revision 0

Original version of the paper for the 2018 Jacksonville meeting.

Revision 1

Simplify the paper to a simple set of editorial suggestions.

1 Introduction

The Lirary Fundamentals series of TSes are expected to produce new revisions several times per standard cycle. The current draft should be updated to reflect that C++17 was published shortly after the Albuqerque 2017 meeting.

2 Stating the problem

The library Fundamentals TS is expected to serve as a long-running sequence of TSes that provide experience on new library features that may be added to future standards. With the publication of the latest C++ Standard in 2017, we should rebase the current TS on that standard before adding new experimental components. The first of those components are expected to land soon.

3 Propose Solution

This paper proposes the simplest imagined rebasing of the document. It does not attempt to apply new C++17 language features to existing components. For example, it has not performed a review for class template deduction guides. It is expected such reviews will be much simpler once the text for the landed components is excised.

Similarly, this paper makes no attempt to resolve awkward wording updates where the underlying text of the referenced C++ standard has changes substantially between C++14 and C++17. In such cases, it provides a simple issues list to track the necessary updates, which should be provided by experts in the affected components.

First, we propose excising all components that have merged into the main standard, and update any remaining internal cross-references to point to the C++17 standard for their specification.

Then we update document references in clause 1, then update all numbered cross-references into the new standard to use the updated standard ISO clause numbering.

Finally, we give the project editor guidance on how to apply a few simple patterns to change the remaining text to refer to the updated experimental namespace. Similarly, we leave it as an exercise for the project editor to fix up cross-references from the C++14 standard to the C++17 standard.

4 Other Directions

A more detailed rebasing was attempted, but produced a much longer document than the Library Working Group would have an easy time reviewing during a meeting. The majority of the extra text were seen as minor changes performing obvious tasks such as fixing up cross references, and applying consistent editing patterns such as renaming the experimental namespace. It was seen as more appropriate to give editorial direction to the project editor to handle those cases, than have a detailed line-by-line review in LWG session.

5 Formal Wording

5.1 Strike out sections that landed in C++17

Completely excise from the document all the sections marked as deleted in the index table below.

Editor's note: Suggest move clause 8.12 (observer pointer) up the document to be adjacent to its related header synopsis, or move 8.1 down.

5.2 Revise The Front Matter

Note that in addition to the changes below, there may be a necessary application of an ISO template for clauses 1-3, and a subsequent renumbering,

1 General [general]

1.1 Scope [general.scope]

  1. This technical specification describes extensions to the C++ Standard Library (1.2). These extensions are classes and functions that are likely to be used widely within a program and/or on the interface boundaries between libraries written by different organizations.
  2. This technical specification is non-normative. Some of the library components in this technical specification may be considered for standardization in a future version of C++, but they are not currently part of any C++ standard. Some of the components in this technical specification may never be standardized, and others may be standardized in a substantially changed form.
  3. The goal of this technical specification is to build more widespread existing practice for an expanded C++ standard library. It gives advice on extensions to those vendors who wish to provide them.

1.2 Normative references [general.references]

  1. The following referenced document is indispensable for the application of this document. For dated references, only the edition cited applies. For undated references, the latest edition of the referenced document (including any amendments) applies.
    • ISO/IEC 14882:20147, Programming Languages — C++
  2. ISO/IEC 14882:— is herein called the C++ Standard. References to clauses within the C++ Standard are written as "C++147 §3.2". The library described in ISO/IEC 14882:— clauses 17–3020–33 is herein called the C++ Standard Library.
  3. Unless otherwise specified, the whole of the C++ Standard's Library introduction (C++14 §17C++17 §20) is included into this Technical Specification by reference.

1.3 Namespaces, headers, and modifications to standard classes [general.namespaces]

  1. Since the extensions described in this technical specification are experimental and not part of the C++ standard library, they should not be declared directly within namespace std. Unless otherwise specified, all components described in this technical specification either:
    • modify an existing interface in the C++ Standard Library in-place,
    • are declared in a namespace whose name appends ::experimental::fundamentals_v23 to a namespace defined in the C++ Standard Library, such as std or std::chrono, or
    • are declared in a subnamespace of a namespace described in the previous bullet, whose name is not the same as an existing subnamespace of namespace std.
    [ Example: This TS does not define std::experimental::fundamentals_v23::chronopmr because the C++ Standard Library defines std::chronopmr. This TS does not define std::pmr::experimental::fundamentals_v2 because the C++ Standard Library does not define std::pmr. — end example ]
  2. Each header described in this technical specification shall import the contents of std::experimental::fundamentals_v23 into std::experimental as if by
    namespace std {
      namespace experimental {
        inline namespace fundamentals_v2 {}
      }
    }
    
    namespace std::experimental {
      inline namespace fundamentals_v3 {}
    }
    
  3. Note for the future: It would have been much simpler if the following syntax were permitted, but that will require a separate proposal through EWG and Core, so would bind against C++20 at the earliest:
    namespace std::experimental::inline fundamentals_v3::pmr {
      // contents...
    }
    
  4. This technical specification also describes some experimental modifications to existing interfaces in the C++ Standard Library. These modifications are described by quoting the affected parts of the standard and using underlining to represent added text and strike-through to represent deleted text.
  5. Unless otherwise specified, references to other entities described in this technical specification are assumed to be qualified with std::experimental::fundamentals_v23::, and references to entities described in the standard are assumed to be qualified with std::.
  6. Extensions that are expected to eventually be added to an existing header are provided inside the <experimental/meow> header, which shall include the standard contents of <meow> as if by
    #include <meow>
    
  7. New headers are also provided in the <experimental/> directory, but without such an #include.

    Table 1 — C++ library headers
    <experimental/algorithm> <experimental/map> <experimental/string>
    <experimental/any> <experimental/memory> <experimental/string_view>
    <experimental/array> <experimental/memory_resource> <experimental/system_error>
    <experimental/chrono> <experimental/optional> <experimental/tuple>
    <experimental/deque> <experimental/propagate_const> <experimental/type_traits>
    <experimental/forward_list> <experimental/random> <experimental/unordered_map>
    <experimental/functional> <experimental/ratio> <experimental/unordered_set>
    <experimental/future> <experimental/regex> <experimental/utility>
    <experimental/iterator> <experimental/set> <experimental/vector>
    <experimental/list> <experimental/source_location>

1.4 Terms and definitions [general.defns]

  1. For the purposes of this document, the terms and definitions given in the C++ Standard and the following apply.

1.4.1 [general.defns.direct-non-list-init]

direct-non-list-initialization
A direct-initialization that is not list-initialization.

1.5 Future plans (Informative) [general.plans]

  1. This section describes tentative plans for future versions of this technical specification and plans for moving content into future versions of the C++ Standard.
  2. The C++ committee intends to release a new version of this technical specification approximately every year, containing the library extensions we hope to add to a near-future version of the C++ Standard. Future versions will define their contents in std::experimental::fundamentals_v34, std::experimental::fundamentals_v45, etc., with the most recent implemented version inlined into std::experimental.
  3. When an extension defined in this or a future version of this technical specification represents enough existing practice, it will be moved into the next version of the C++ Standard by removing the experimental::fundamentals_vN segment of its namespace and by removing the experimental/ prefix from its header's path.

1.6 Feature-testing recommendations (Informative) [general.feature.test]

  1. For the sake of improved portability between partial implementations of various C++ standards, WG21 (the ISO technical committee for the C++ programming language) recommends that implementers and programmers follow the guidelines in this section concerning feature-test macros. [ Note: WG21's SD-6 makes similar recommendations for the C++ Standard itself. — end note ]
  2. Implementers who provide a new standard 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. Implementers should define that macro with the value specified in the most recent version of this technical specification that they have implemented. The recommended macro name is "__cpp_lib_experimental_" followed by the string in the "Macro Name Suffix" column.
  3. Programmers who wish to determine whether a feature is available in an implementation should base that determination on the presence of the header (determined with __has_include(<header/name>)) and 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; presumably, on an implementation lacking necessary support, translation will fail.)
Table 2 - Significant features in this technical specification
Doc. No. Title Primary Section Macro Name Suffix Value Header
N3915 apply() call a function with arguments from a tuple 3.2.2 apply 201402 <experimental/tuple>
N3932 Variable Templates For Type Traits 3.3.1 type_trait_variable_templates 201402 <experimental/type_traits>
N3866 Invocation type traits 3.3.2 invocation_type 201406 <experimental/type_traits>
P0013R1 Logical Operator Type Traits 3.3.3 logical_traits 201511 <experimental/type_traits>
N4502 The C++ Detection Idiom 3.3.4 detect 201505 <experimental/type_traits>
N4388 A Proposal to Add a Const-Propagating Wrapper to the Standard Library 3.7 propagate_const 201505 <experimental/propagate_const>
N3916 Type-erased allocator for std::function 4.2 function_erased_allocator 201406 <experimental/functional>
N3905 Extending std::search to use Additional Searching Algorithms 4.3 boyer_moore_searching 201411 <experimental/functional>
N4076 A proposal to add a generalized callable negator 4.4 not_fn 201406 <experimental/functional>
N3672, N3793 A utility class to represent optional objects 5 optional 201411 <experimental/optional>
N3804 Any Library Proposal 6 any 201411 <experimental/any>
N3921 string_view: a non-owning reference to a string 7 string_view 201411 <experimental/string_view>
N3920 Extending shared_ptr to Support Arrays 8.2 shared_ptr_arrays 201406 <experimental/memory>
N3916 Polymorphic Memory Resources 8.4 memory_resources 201402 <experimental/memory_resource>
N4282 The World’s Dumbest Smart Pointer 8.12 observer_ptr 201411 <experimental/memory>
N4273 Uniform Container Erasure 9.1 erase_if 201411 <experimental/vector>, <experimental/deque>, <experimental/forward_list>, <experimental/list>, <experimental/map>, <experimental/set>, <experimental/unordered_map>, <experimental/unordered_set>,
N4391 make_array 9.2.2 make_array 201505 <experimental/array>
N4257 Delimited iterators 10.2 ostream_joiner 201411 <experimental/iterator>
N3916 Type-erased allocator for std::promise 11.2 promise_erased_allocator 201406 <experimental/future>
N3916 Type-erased allocator for std::packaged_task 11.3 packaged_task_erased_allocator 201406 <experimental/future>
N3925 A sample Proposal 12.3 sample 201402 <experimental/algorithm>
N4061 Greatest Common Divisor and Least Common Multiple 13.1.2, 13.1.3 gcd_lcm 201411 <experimental/numeric>
N4531 std::rand replacement 13.2.2.1 randint 201511 <experimental/random>
N4519 Source-Code Information Capture 14.1 source_location 201505 <experimental/source_location>

5.3 Global Search and Replace

There are a couple or repeating patterns in the normative text following the header synopses that should be applied universally. First, replace all opening/closing namespaces matching the following pattern:

namespace std {
namespace std::experimental {
inline namespace fundamentals_v23 {

    // some class definition or other specification ...
    
} // namespace fundamentals_v23
} // namespace std::experimental
} // namespace std

An example of updating a header synopsis:

14.1.1 Header <experimental/source_location> synopsis [reflection.src_loc.synop]

namespace std {
namespace std::experimental {
inline namespace fundamentals_v23 {

  struct source_location {
    // 14.1.2, source_location creation
    static constexpr source_location current() noexcept;

    constexpr source_location() noexcept;

    // 14.1.3, source_location field access
    constexpr uint_least32_t line() const noexcept;
    constexpr uint_least32_t column() const noexcept;
    constexpr const char* file_name() const noexcept;
    constexpr const char* function_name() const noexcept;
  };

} // namespace fundamentals_v23
} // namespace std::experimental
} // namespace std
  1. [ Note: The intent of source_location is to have a small size and efficient copying. — end note ]

5.4 Fix Cross-references

Some parts of the TS update wording in the main standard, so require normative updates to the cross-reference immediates.

2.1 Uses-allocator construction [mods.allocator.uses]

20.723.10.7 uses_allocator [allocator.uses]

20.723.10.7.1 uses_allocator trait [allocator.uses.trait]

20.723.10.7.2 uses-allocator construction [allocator.uses.construction]

Next, the remaining section on type-erased allocators should be using the pmr facility from the main std::pmr namespace that landed in C++17, as there is no further experimental version of this feature.

8.3 Type-erased allocator [memory.type.erased.allocator]

  1. A type-erased allocator is an allocator or memory resource, alloc, used to allocate internal data structures for an object X of type C, but where C is not dependent on the type of alloc. Once alloc has been supplied to X (typically as a constructor argument), alloc can be retrieved from X only as a pointer rptr of static type std::experimental::pmr::memory_resource* (8.5C++17 §23.12.2 [mem.res.class]). The process by which rptr is computed from alloc depends on the type of alloc as described in Table 15:
  2. Table 15 - Computed memory_resource for type-erased allocator
    If the type of alloc is then the value of rptr is
    non-existent — no alloc specified The value of experimental::pmr::get_default_resource() at the time of construction.
    nullptr_t The value of experimental::pmr::get_default_resource() at the time of construction.
    a pointer type convertible to pmr::memory_resource* static_cast<experimental::pmr::memory_resource*>(alloc)
    pmr::polymorphic_allocator<U> alloc.resource()
    any other type meeting the Allocator requirements (C++14 §17.6.3.5C++17 §20.5.3.5 [allocator.requirements]) a pointer to a value of type experimental::pmr::resource_adaptor<A> where A is the type of alloc. rptr remains valid only for the lifetime of X.
    None of the above The program is ill-formed.

  3. Additionally, class C shall meet the following requirements:
    • C::allocator_type shall be identical to std::experimental::erased_type.
    • X.get_memory_resource() returns rptr.

Then, there are many references to the C++14 standard, denoted thusly: (C++14 §17.6.3.5). They should be replaced as an editorial action with their corresponding reference to the C++17 standard, as (C++17 §20.5.3.5).

Finally, there are a few stylistic cleanups to apply

6 Acknowledgements

Thanks to the initial reviewers of R0 of this document, that helped produce this simplified document, and especially to Geoffrey Romer as editor of the Fundamentals TS who agreed that much of the fine detail was better left as an editorial task he would have to pick up.

7 References