# C++ Standard Library Issues Resolved Directly In Rapperswil, 2014

Doc. no. | N4079
Date: | Revised 2014-06-20
Project: | Programming Language C++
Reply to: | Alisdair Meredith <lwgchair@gmail.com>

## Immediate Issues

### 2371. [fund.ts] No template aliases defined for new type traits

Section: 20.10.2 [meta.type.synop] Status: Immediate Submitter: Joe Gottman Opened: 2014-03-07 Last modified: 2014-06-20

View all issues with Immediate status.

Discussion:

Addresses: fund.ts

The library fundamentals specification defines two new type trait template classes: `invocation_type` and `raw_invocation_type`. But it does not define the corresponding template aliases. Note that both of these classes define a member typedef `type` and no other public members, so according to the argument in N3887 the template aliases should be defined.

[2014-06-16 Rapperswil]

Move as Immediate.

Proposed resolution:

This wording is relative to N3908.

1. Add the following to section 3.3.1[meta.type.synop] of the Library Fundamentals specification as indicated:

   >     namespace std {
   >     namespace experimental {
   >     inline namespace fundamentals_v1 {
   >       […]
   >       // 3.3.2, Other type transformations
   >       template <class> class invocation_type; // not defined
   >       template <class F, class... ArgTypes> class invocation_type<F(ArgTypes...)>;
   >       template <class> class raw_invocation_type; // not defined
   >       template <class F, class... ArgTypes> class raw_invocation_type<F(ArgTypes...)>;

   >       template <class T>
   >         using invocation_type_t = typename invocation_type<T>::type;
   >       template <class T>
   >         using raw_invocation_type_t = typename raw_invocation_type<T>::type;

   >     } // namespace fundamentals_v1
   >     } // namespace experimental
   >     } // namespace std

### 2374. [fund.ts] Remarks for `optional::to_value` are too restrictive

Section: X [optional.object.observe] Status: Immediate Submitter: Jonathan Wakely Opened: 2014-03-25 Last modified: 2014-06-20

View all issues with Immediate status.

Discussion:

Addresses: fund.ts

In Bristol I think I claimed that the remarks for `optional::to_value()` were unimplementable and the function could only be `constexpr` if both constructors that could be called were `constexpr`, but I was wrong. The remarks should be reverted to the original pre-n3793 form.

[2014-06-16 Rapperswil]

Move to Immediate

Proposed resolution:

This wording is relative to N3908.

1. Change [optional.object.observe] p23 of the Library Fundamentals specification as indicated:

   >     template <class U> constexpr T value_or(U&& v) const &;

   > > […]

   > > -23- Remarks: If both constructors of `T` which could be selected are `constexpr` constructors the selected constructor of `T` is a `constexpr` constructor, this function shall be a `constexpr` function.

### 2389. [fund.ts] `function::operator=` is over-specified and handles allocators incorrectly

Section: X [mods.func.wrap] Status: Immediate Submitter: Pablo Halpern Opened: 2014-05-23 Last modified: 2014-06-20

View other active issues in [mods.func.wrap].

View all other issues in [mods.func.wrap].

View all issues with Immediate status.

Discussion:

Addresses: fund.ts

This issue against the TS is similar to LWG 2386, which is against the standard. The Effects clauses for the assignment operator for class template `function` are written as code that constructs a temporary `function` and then swaps it with `*this`. The intention appears to be that assignment should have the strong exception guarantee, i.e., `*this` is not modified if an exception is thrown. The description in the standard is incorrect when `*this` was originally constructed using an allocator. The TS attempts to correct the problem, but the correction is incomplete.

The wording in the TS uses `get_memory_resource()` to construct a temporary `function` object with the same allocator as the left-hand size (lhs) of the assignment. The intended result of using this pattern was that the allocator for `*this` would be unchanged, but it doesn't quite work. The problem is that the allocator returned by `get_memory_resource()` is not the same type as the type-erased allocator used to construct the `function` object, but rather a type-erased distillation of that type that is insufficient for making a true copy of the allocator. The rules for type-erased allocators in the TS ([memory.type.erased.allocator]) specify that the lifetime of the object returned by `get_memory_resource()` is sometimes tied to the lifetime of `*this`, which might cause the (single copy of) the allocator to be destroyed if the `swap` operation destroys and reconstructs `*this`, as some implementations do (and are allowed to do).

The desired behavior is that assignment would leave the allocator of the lhs unchanged. The way to achieve this behavior is to construct the temporary `function` using the original allocator. Unfortunately, we cannot describe the desired behavior in pure code, because `get_memory_resource()` does not really name the type-erased allocator, as mentioned above. The PR below, therefore, uses pseudo-code, inventing a fictitious `ALLOCATOR_OF(f)` expression that evaluates to the actual allocator type, even if that allocator was type erased. I have implemented this PR successfully.

[2014-06-18, Rapperswil]

Move to Immediate (after removing the previous "Throws: Nothing" element to prevent an editorial conflict with 2401).

Proposed resolution:

This wording is relative to N3908.

1. Change in [mods.func.wrap] in the Library TS as indicated:

   > In the following descriptions, let `ALLOCATOR_OF(f)` be the allocator specified in the construction of `function` `f`, or `allocator<char>()` if no allocator was specified.

   >     function& operator=(const function& f);

   > > -5- Effects: `function(allocator_arg, get_memory_resource()ALLOCATOR_OF(*this), f).swap(*this);`

   > > […]

   >     function& operator=(function&& f);

   > > -8- Effects: `function(allocator_arg, get_memory_resource()ALLOCATOR_OF(*this), std::move(f)).swap(*this);`

   > > […]

   >     function& operator=(nullptr_t);

   > > -11- Effects: If `*this != NULL`, destroys the target of `this`.

   > > -12- Postconditions: `!(*this)`. The memory resource returned by `get_memory_resource()` after the assignment is equivalent to the memory resource before the assignment. [Note: the address returned by `get_memory_resource()` might change — end note]

   > > -13- Returns: `*this`

   >     template<class F> function& operator=(F&& f);

   > > -15- Effects: `function(allocator_arg, get_memory_resource()ALLOCATOR_OF(*this), std::forward<F>(f)).swap(*this);`

   > > […]

   >     template<class F> function& operator=(reference_wrapper<F> f);

   > > -18- Effects: `function(allocator_arg, get_memory_resource()ALLOCATOR_OF(*this), f).swap(*this);`

   > > […]

### 2390. [fund.ts] Invocation types and rvalues

Section: X [mods.func.wrap] Status: Immediate Submitter: Michael Spertus Opened: 2014-05-26 Last modified: 2014-06-20

View other active issues in [mods.func.wrap].

View all other issues in [mods.func.wrap].

View all issues with Immediate status.

Discussion:

Addresses: fund.ts

`invocation_type` falls short of its stated goals in the following case. Using the notation of Invocation type traits, consider

>     void f(int const& i);
>     more_perfect_forwarding_async(f, int(7)); // Oops. Dangling reference because rvalue gone when async runs

This was always the advertised intent of the proposal, but while the language reflects this for the first parameter in the case of a member pointer, it failed to include corresponding language for other parameters.

[2014-06-18, Rapperswil]

Mike Spertus, Richard Smith, Jonathan Wakely, and Jeffrey Yasskin suggest improved wording.

Previous resolution [SUPERSEDED]:

> This wording is relative to N3908.

> 1. Change Table 3, [meta.trans.other] in the Library TS as indicated:

>    > Table 3 — Other type transformations
>    > Template | Condition | Comments
>    > --- | --- | ---
>    > `…`
>    > `template <class Fn, class... ArgTypes> struct invocation_type<Fn(ArgTypes...)>;` | `Fn` and all types in the parameter pack `ArgTypes` shall be complete types, (possibly cv-qualified) `void`, or arrays of unknown bound. | If `A1, A2,...` denotes `ArgTypes...` and `raw_invocation_type<Fn(ArgTypes...)>::type` is the function type `R(T1, T2, ...)` then let `Ui` be `decay<Ai>::type` if `Ai` is an rvalue otherwise `Ti`. If and `Fn` is a pointer to member type and `T1` is an rvalue reference, then let `U1` be `R(decay<T1>::type, T2, ...)`. Otherwise, `raw_invocation_type<Fn(ArgTypes...)>::type` The member typedef `type` shall equal `R(U1, U2, ...)`.

Proposed resolution:

This wording is relative to N4023.

1. Change Table 3, [meta.trans.other] in the Library TS as indicated:

   > Table 3 — Other type transformations
   > Template | Condition | Comments
   > --- | --- | ---
   > `…`
   > `template <class Fn, class... ArgTypes> struct invocation_type<Fn(ArgTypes...)>;` | `Fn` and all types in the parameter pack `ArgTypes` shall be complete types, (possibly cv-qualified) `void`, or arrays of unknown bound. | The nested typedef `invocation_type<Fn(ArgTypes...)>::type` shall be defined as follows. If `raw_invocation_type<Fn(ArgTypes...)>::type` does not exist, there shall be no member typedef `type`. Otherwise: Let `A1, A2,` … denote `ArgTypes...` Let `R(T1, T2, …)` denote `raw_invocation_type_t<Fn(ArgTypes...)>` Then the member typedef `type` shall name the function type `R(U1, U2, …)` where `Ui` is `decay_t<Ai>` if `declval<Ai>()` is an rvalue otherwise `Ti`. If `raw_invocation_type<Fn(ArgTypes...)>::type` is the function type `R(T1, T2, …)` and `Fn` is a pointer to member type and `T1` is an rvalue reference, then `R(decay<T1>::type, T2, …)`. Otherwise, `raw_invocation_type<Fn(ArgTypes...)>::type`.

### 2395. [fund.ts] Preconditions: is defined nowhere

Section: X [mods.func.wrap], X [memory.resource.priv], X [memory.polymorphic.allocator.ctor], X [memory.polymorphic.allocator.mem], X [memory.resource.pool.ctor], X [memory.resource.monotonic.buffer.ctor] Status: Immediate Submitter: Zhihao Yuan Opened: 2014-06-09 Last modified: 2014-06-20

View other active issues in [mods.func.wrap].

View all other issues in [mods.func.wrap].

View all issues with Immediate status.

Discussion:

Addresses: fund.ts

This element has been introduced by N3916, but the standard does not define it. The standard defines Requires: to indicate a precondition (17.5.1.4 [structure.specifications] p3).

Proposed wording:

Substitute all Preconditions: with Requires:.

[2014-06-17, Rapperswil]

Move to Immediate

Proposed resolution:

This wording is relative to N4023.

1. Substitute all Preconditions: with Requires:.

### 2409. [fund.ts] SFINAE-friendly `common_type/iterator_traits` should be removed from the fundamental-ts

Section: X [mods.meta.trans.other], X [mods.iterator.traits] Status: Immediate Submitter: Daniel Krügler Opened: 2014-06-19 Last modified: 2014-06-20

View all issues with Immediate status.

Discussion:

Addresses: fund.ts

During the Rapperswil meeting the proposal N4041 had been discussed and there seemed to be strong consensus to apply the SFINAE-friendly definitions that currently exist within the fundamentals-ts to the C++17 working draft. If this happens, the fundamentals-ts needs to remove its own specification regarding these templates. This issue requests this change to happen.

Proposed resolution:

This wording is relative to N4023 in regard to fundamental-ts changes.

1. In fundamental-ts, change Table 2 — "Significant features in this technical specification" as indicated:

   > Table 2 — Significant features in this technical specification
   > Doc. No. | Title | Primary Section | Macro Name Suffix | Value | Header
   > --- | --- | --- | --- | --- | ---
   > `…`
   > N3843 | A SFINAE- Friendly `common_type` | 2.4 [mods.meta.trans.other] | `common_type_sfinae` | `201402` | `<type_traits>`
   > N3843 | A SFINAE- Friendly `iterator_traits` | 2.5 [mods.iterator.traits] | `iterator_traits_sfinae` | `201402` | `<iterator>`
   > `…`

2. In fundamental-ts, remove the existing sub-clause 2.4 [mods.meta.trans.other] in its entirety:

   2.4 Changes to `std::common_type` [mods.meta.trans.other]

   > -1- […]

3. In fundamental-ts, remove the existing sub-clause 2.5 [mods.iterator.traits] in its entirety:

   2.5 Changes to `std::iterator_traits` [mods.iterator.traits]

   > -1- […]