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 constructorsthe 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- […]