Revised 2012-02-27 at 21:02:54 UTC

## Tentative Issues

### 2005. `unordered_map::insert(T&&)` protection should apply to `map` too

Section: 23.4.4.4 [map.modifiers], 23.4.5.3 [multimap.modifiers], X [unord.map.modifiers], X [unord.multimap.modifiers] Status: Tentatively Ready Submitter: P.J. Plauger Opened: 2010-10-14 Last modified: 2012-02-27

View all issues with Tentatively Ready status.

Discussion:

In [unord.map.modifiers], the signature:

>     template <class P>
>         pair<iterator, bool> insert(P&& obj);

now has an added Remarks paragraph:

> Remarks: This signature shall not participate in overload resolution unless `P` is implicitly convertible to `value_type`.

The same is true for `unordered_multimap`.

But neither `map` nor `multimap` have this constraint, even though it is a Good Thing(TM) in those cases as well.

[ The submitter suggests: Add the same Remarks clause to [map.modifiers] and [multimap.modifiers]. ]

[ 2010-10-29 Daniel comments: ]

I believe both paragraphs need more cleanup: First, the current Requires element conflict with the Remark; second, it seems to me that the whole single Requires element is intended to be split into a Requires and an Effects element; third, the reference to `tuple` is incorrect (noticed by Paolo Carlini); fourth, it refers to some non-existing `InputIterator` parameter relevant for a completely different overload; sixth, the return type of the overload with hint is wrong. The following proposed resolution tries to solve these issues as well and uses similar wording as for the corresponding unordered containers. Unfortunately it has some redundancy over Table 99, but I did not remove the specification because of the more general template parameter `P` - the Table 99 requirements apply only for an argument identical to `value_type`.

Daniel's Proposed resolution (not current):

> 1. Change 23.4.4.4 [map.modifiers] around p. 1 as indicated:

>    >     template <class P> pair<iterator, bool> insert(P&& x);
>    >     template <class P> pair<iterator, bool> insert(const_iterator position, P&& x);

>    > > 1 Requires: `P` shall be convertible to `value_type` is constructible from `std::forward<P>(x)`..

>    > > If `P` is instantiated as a reference type, then the argument `x` is copied from. Otherwise `x` is considered to be an rvalue as it is converted to `value_type` and inserted into the map. Specifically, in such cases `CopyConstructible` is not required of `key_type` or `mapped_type` unless the conversion from `P` specifically requires it (e.g., if `P` is a `tuple<const key_type, mapped_type>`, then `key_type` must be `CopyConstructible`). The signature taking `InputIterator` parameters does not require `CopyConstructible` of either `key_type` or `mapped_type` if the dereferenced `InputIterator` returns a non-const rvalue `pair<key_type,mapped_type>`. Otherwise `CopyConstructible` is required for both `key_type` and `mapped_type`.
>    > > ? Effects: Inserts `x` converted to `value_type` if and only if there is no element in the container with key equivalent to the key of `value_type(x)`. For the second form, the iterator `position` is a hint pointing to where the search should start.

>    > > ? Returns: For the first form, the `bool` component of the returned `pair` object indicates whether the insertion took place and the iterator component - or for the second form the returned iterator - points to the element with key equivalent to the key of `value_type(x)`.

>    > > ? Complexity: Logarithmic in general, but amortized constant if `x` is inserted right before `position`.

>    > > ? Remarks: These signatures shall not participate in overload resolution unless `P` is implicitly convertible to `value_type`.

> 2. Change 23.4.5.3 [multimap.modifiers] around p. 1 as indicated:

>    >     template <class P> iterator insert(P&& x);
>    >     template <class P> iterator insert(const_iterator position, P&& x);

>    > > 1 Requires: `P` shall be convertible to `value_type` is constructible from `std::forward<P>(x)`.

>    > > If `P` is instantiated as a reference type, then the argument `x` is copied from. Otherwise `x` is considered to be an rvalue as it is converted to `value_type` and inserted into the map. Specifically, in such cases `CopyConstructible` is not required of `key_type` or `mapped_type` unless the conversion from `P` specifically requires it (e.g., if `P` is a `tuple<const key_type, mapped_type>`, then `key_type` must be `CopyConstructible`). The signature taking `InputIterator` parameters does not require `CopyConstructible` of either `key_type` or `mapped_type` if the dereferenced `InputIterator` returns a non-const rvalue `pair<key_type, mapped_type>`. Otherwise `CopyConstructible` is required for both `key_type` and `mapped_type`.
>    > > ? Effects: Inserts `x` converted to `value_type`. For the second form, the iterator `position` is a hint pointing to where the search should start.

>    > > ? Returns: An iterator that points to the element with key equivalent to the key of `value_type(x)`.

>    > > ? Complexity: Logarithmic in general, but amortized constant if `x` is inserted right before `position`.

>    > > ? Remarks: These signatures shall not participate in overload resolution unless `P` is implicitly convertible to `value_type`.

[ 2010 Batavia: ]

We need `is_convertible`, not `is_constructible`, both in ordered and unordered containers.

[ 2011 Bloomington ]

The effects of these inserts can be concisely stated in terms of emplace(). Also, the correct term is "EmplaceConstructible", not "constructible".

New wording by Pablo, eliminating duplicate requirements already implied by the effects clause. Move to Review.

[ 2011-10-02 Daniel comments and refines the proposed wording ]

> Unfortunately the template constraints expressed as "`P` is implicitly convertible to `value_type`" reject the intended effect to support move-only key types, which was the original intention when the library became move-enabled through the rvalue-reference proposals by Howard (This can clearly be deduced from existing carefully selected wording that emphasizes that `CopyConstructible` is only required for special situations involving lvalues or const rvalues as arguments). The root of the problem is based on current core rules, where an "implicitly converted" value has copy-initialization semantics. Consider a move-only key type `KM`, some mapped type `T`, and a source value `p` of type `P` equal to `std::pair<KM, T>`, this is equivalent to:

> >     std::pair<const KM, T> dest = std::move(p);

> Now 8.5 [dcl.init] p16 b6 sb2 says that the effects of this heterogeneous copy-initialization (`p` has a different type than `dest`) are as-if a temporary of the target type `std::pair<const KM, T>` is produced from the rvalue `p` of type `P` (which is fine), and this temporary is used to initialize `dest`. This second step cannot succeed, because we cannot move from `const KM` to `const KM`. This means that `std::is_convertible<P, std::pair<const KM, T>>::value` is false.

> But the actual code that is required (with the default allocator) is simply a direct-initialization from `P` to `value_type`, so imposing an implicit conversion is more than necessary. Therefore I strongly recommend to reduce the "overload participation" constraint to `std::is_constructible<std::pair<const KM, T>, P>::value` instead. This change is the only change that has been performed to the previous proposed wording from Pablo shown below.

[2012, Kona]

Moved to Tentatively Ready by the post-Kona issues processing subgroup, after much discussion on Daniel's analysis of Copy Initialization and move semantics, which we ultimately agreed with.

Proposed resolution:

1. Change 23.4.4.4 [map.modifiers] around p. 1 as indicated:

   >     template <class P> pair<iterator, bool> insert(P&& x);
   >     template <class P> pair<iterator, bool> insert(const_iterator position, P&& x);

   > > 1 Requires: `P` shall be convertible to `value_type`.

   > > If `P` is instantiated as a reference type, then the argument `x` is copied from. Otherwise `x` is considered to be an rvalue as it is converted to `value_type` and inserted into the map. Specifically, in such cases `CopyConstructible` is not required of `key_type` or `mapped_type` unless the conversion from `P` specifically requires it (e.g., if `P` is a `tuple<const key_type, mapped_type>`, then `key_type` must be `CopyConstructible`). The signature taking `InputIterator` parameters does not require `CopyConstructible` of either `key_type` or `mapped_type` if the dereferenced `InputIterator` returns a non-const rvalue `pair<key_type,mapped_type>`. Otherwise `CopyConstructible` is required for both `key_type` and `mapped_type`.
   > > ? Effects: The first form is equivalent to `return emplace(std::forward<P>(x))`. The second form is equivalent to `return emplace_hint(position, std::forward<P>(x))`.

   > > ? Remarks: These signatures shall not participate in overload resolution unless `std::is_constructible<value_type, P&&>::value` is true.

2. Change 23.4.5.3 [multimap.modifiers] around p. 1 as indicated:

   >     template <class P> iterator insert(P&& x);
   >     template <class P> iterator insert(const_iterator position, P&& x);

   > > 1 Requires: `P` shall be convertible to `value_type`.

   > > If `P` is instantiated as a reference type, then the argument `x` is copied from. Otherwise `x` is considered to be an rvalue as it is converted to `value_type` and inserted into the map. Specifically, in such cases `CopyConstructible` is not required of `key_type` or `mapped_type` unless the conversion from `P` specifically requires it (e.g., if `P` is a `tuple<const key_type, mapped_type>`, then `key_type` must be `CopyConstructible`). The signature taking `InputIterator` parameters does not require `CopyConstructible` of either `key_type` or `mapped_type` if the dereferenced `InputIterator` returns a non-const rvalue `pair<key_type, mapped_type>`. Otherwise `CopyConstructible` is required for both `key_type` and `mapped_type`.
   > > ? Effects: The first form is equivalent to `return emplace(std::forward<P>(x))`. The second form is equivalent to `return emplace_hint(position, std::forward<P>(x))`.

   > > ? Remarks: These signatures shall not participate in overload resolution unless `std::is_constructible<value_type, P&&>::value` is true.

3. Change 23.5.4.4 [unord.map.modifers] around p. 1 as indicated:

   >     template <class P>
   >     pair<iterator, bool> insert(P&& obj);

   > > 1 Requires: `value_type` is constructible from `std::forward<P>(obj)`.

   > > 2 Effects: equivalent to `return emplace(std::forward<P>(obj))`. Inserts obj converted to `value_type` if and only if there is no element in the container with key equivalent to the key of `value_type(obj)`.

   > > 3 Returns: The bool component of the returned pair object indicates whether the insertion took place and the iterator component points to the element with key equivalent to the key of `value_type(obj)`.

   > > 4 Complexity: Average case O(1), worst case O(size()).

   > > 5 3 Remarks: This signature shall not participate in overload resolution unless `P` is implicitly convertible to `value_type` `std::is_constructible<value_type, P&&>::value` is true.

   >     template <class P>
   >     iterator insert(const_iterator hint, P&& obj);

   > > 6 Requires: `value_type` is constructible from `std::forward<P>(obj)`.

   > > 7? Effects: equivalent to `return emplace_hint(hint, std::forward<P>(obj))`. Inserts obj converted to `value_type` if and only if there is no element in the container with key equivalent to the key of `value_type(obj)`. The iterator hint is a hint pointing to where the search should start.

   > > 8 Returns: An iterator that points to the element with key equivalent to the key of `value_type(obj)`.

   > > 9 Complexity: Average case O(1), worst case O(size()).

   > > 10? Remarks: This signature shall not participate in overload resolution unless `P` is implicitly convertible to `value_type` `std::is_constructible<value_type, P&&>::value` is true.

4. Change 23.5.5.3 [unord.multimap.modifers] around p. 1 as indicated:

   >     template <class P>
   >     iterator insert(P&& obj);

   > > 1 Requires: `value_type` is constructible from `std::forward<P>(obj)`.

   > > 2 Effects: equivalent to `return emplace(std::forward<P>(obj))`. Inserts obj converted to `value_type`.

   > > 3 Returns: An iterator that points to the element with key equivalent to the key of `value_type(obj)`.

   > > 4 Complexity: Average case O(1), worst case O(size()).

   > > 5 3 Remarks: This signature shall not participate in overload resolution unless `P` is implicitly convertible to `value_type` `std::is_constructible<value_type, P&&>::value` is true.

   >     template <class P>
   >     iterator insert(const_iterator hint, P&& obj);

   > > 6 Requires: `value_type` is constructible from `std::forward<P>(obj)`.

   > > 7? Effects: equivalent to `return emplace_hint(hint, std::forward<P>(obj))`. Inserts obj converted to `value_type`. The iterator hint is a hint pointing to where the search should start.

   > > 8 Returns: An iterator that points to the element with key equivalent to the key of `value_type`(obj).

   > > 9 Complexity: Average case O(1), worst case O(size()).

   > > 10? Remarks: This signature shall not participate in overload resolution unless `P` is implicitly convertible to `value_type` `std::is_constructible<value_type, P&&>::value` is true.

### 2011. Unexpected output required of strings

Section: 21.4.8.9 [string.io] Status: Tentatively Ready Submitter: James Kanze Opened: 2010-07-23 Last modified: 2012-02-27

View all other issues in [string.io].

View all issues with Tentatively Ready status.

Discussion:

What should the following code output?

>     #include <string>
>     #include <iostream>
>     #include <iomanip>

>     int main()
>     {
>        std::string test("0X1Y2Z");
>        std::cout.fill('*');
>        std::cout.setf(std::ios::internal, std::ios::adjustfield);
>        std::cout << std::setw(8) << test << std::endl;
>     }

I would expect "`**0X1Y2Z`", and this is what the compilers I have access to (VC++, g++ and Sun CC) do. But according to the standard, it should be "`0X**1Y2Z`":

21.4.8.9 [string.io]/5:

>     template<class charT, class traits, class Allocator>
>       basic_ostream<charT, traits>&
>         operator<<(basic_ostream<charT, traits>& os, const basic_string<charT,traits,Allocator>& str);

> > Effects: Behaves as a formatted output function (27.7.3.6.1 [ostream.formatted.reqmts]). After constructing a `sentry` object, if this object returns `true` when converted to a value of type `bool`, determines padding as described in 22.4.2.2.2 [facet.num.put.virtuals], then inserts the resulting sequence of characters seq as if by calling `os.rdbuf()->sputn(seq, n)`, where `n` is the larger of `os.width()` and `str.size()`; then calls `os.width(0)`.

22.4.2.2.2 [facet.num.put.virtuals]/5:

> […]

> Stage 3: A local variable is initialized as

> >     fmtflags adjustfield= (flags & (ios_base::adjustfield));

> The location of any padding is determined according to Table 88.

> If `str.width()` is nonzero and the number of `charT`'s in the sequence after stage 2 is less than `str.width()`, then enough fill characters are added to the sequence at the position indicated for padding to bring the length of the sequence to `str.width()`. `str.width(0)` is called.

> Table 88 — Fill padding
> State | Location
> --- | ---
> `adjustfield == ios_base::left` | pad after
> `adjustfield == ios_base::right` | pad before
> `adjustfield == internal` and a sign occurs in the representation | pad after the sign
> `adjustfield == internal` and representation after stage 1 began with 0x or 0X | pad after x or X
> otherwise | pad before

Although it's not 100% clear what "the sequence after stage 2" should mean here, when there is no stage 2, the only reasonable assumption is that it is the contents of the string being output. In the above code, the string being output is "`0X1Y2Z`", which starts with "`0X`", so the padding should be inserted "after x or X", and not before the string. I believe that this is a defect in the standard, and not in the three compilers I tried.

[ 2010 Batavia (post meeting session) ]

Consensus that all known implementations are consistent, and disagree with the standard. Preference is to fix the standard before implementations start trying to conform to the current spec, as the current implementations have the preferred form. Howard volunteered to drught for Madrid, move to Open.

[2011-03-24 Madrid meeting]

Daniel Krügler volunteered to provide wording, interacting with Dietmar and Bill.

[2011-06-24 Daniel comments and provides wording]

The same problem applies to the output provided by `const char*` and similar character sequences as of 27.7.3.6.4 [ostream.inserters.character] p. 5. and even for single character output (!) as described in 27.7.3.6.4 [ostream.inserters.character] p. 1, just consider the character value '-' where '-' is the sign character. In this case Table 91 — "Fill padding" requires to pad after the sign, i.e. the output for the program

>     #include <iostream>
>     #include <iomanip>

>     int main()
>     {
>        char c = '-';
>        std::cout.fill('*');
>        std::cout.setf(std::ios::internal, std::ios::adjustfield);
>        std::cout << std::setw(2) << c << std::endl;
>     }

According to the current wording this program should output "`-*`", but all tested implementations output "`*-`" instead.

I suggest to replace the reference to 22.4.2.2.2 [facet.num.put.virtuals] in all three places. It is not very complicated to describe the padding rules for simple character sequences "inline". A similar approach is used as for the `money_put` functions.

[ 2011 Bloomington ]

Move to Review, the resolution seems correct but it would be nice if some factoring of the common words were proposed.

[2012, Kona]

Moved to Tentatively Ready by the post-Kona issues processing subgroup.

While better factoring of the common words is desirable, it is also editorial and should not hold up the progress of this issue. As the edits impact two distinct clauses, it is not entirely clear what a better factoring should look like.

Proposed resolution:

The new wording refers to the FDIS numbering.

1. Change 21.4.8.9 [string.io]/5 as indicated:

   >     template<class charT, class traits, class Allocator>
   >       basic_ostream<charT, traits>&
   >         operator<<(basic_ostream<charT, traits>& os,
   >                    const basic_string<charT,traits,Allocator>& str);

   > > -5- Effects: Behaves as a formatted output function ([ostream.formatted.reqmts]). After constructing a sentry object, if this object returns `true` when converted to a value of type `bool`, determines padding as described in [facet.num.put.virtuals],follows: A `charT` character sequence is produced, initially consisting of the elements defined by the range `[str.begin(), str.end())`. If `str.size()` is less than `os.width()`, then enough copies of `os.fill()` are added to this sequence as necessary to pad to a width of `os.width()` characters. If `(os.flags() & ios_base::adjustfield) == ios_base::left` is `true`, the fill characters are placed after the character sequence; otherwise, they are placed before the character sequence. T then inserts the resulting sequence of characters `seq` as if by calling `os.rdbuf()->sputn(seq, n)`, where `n` is the larger of `os.width()` and `str.size()`; then calls `os.width(0)`.

2. Change 27.7.3.6.4 [ostream.inserters.character]/1 as indicated (An additional editorial fix is suggested for the first prototype declaration):

   >     template<class charT, class traits>
   >       basic_ostream<charT,traits>& operator<<(basic_ostream<charT,traits>& out,
   >                                               charT c});
   >     template<class charT, class traits>
   >       basic_ostream<charT,traits>& operator<<(basic_ostream<charT,traits>& out,
   >                                               char c);
   >     // specialization
   >     template<class traits>
   >       basic_ostream<char,traits>& operator<<(basic_ostream<char,traits>& out,
   >                                              char c);
   >     // signed and unsigned
   >     template<class traits>
   >       basic_ostream<char,traits>& operator<<(basic_ostream<char,traits>& out,
   >                                              signed char c);
   >     template<class traits>
   >       basic_ostream<char,traits>& operator<<(basic_ostream<char,traits>& out,
   >                                              unsigned char c);

   > > -1- Effects: Behaves like a formatted inserter (as described in [ostream.formatted.reqmts]) of `out`. After a sentry object is constructed it inserts characters. In case `c` has type `char` and the character type of the stream is not `char`, then the character to be inserted is `out.widen(c)`; otherwise the character is `c`. Padding is determined as described in [facet.num.put.virtuals]follows: A character sequence is produced, initially consisting of the insertion character. If `out.width()` is greater than one, then enough copies of `out.fill()` are added to this sequence as necessary to pad to a width of `out.width()` characters. If `(out.flags() & ios_base::adjustfield) == ios_base::left` is `true`, the fill characters are placed after the insertion character; otherwise, they are placed before the insertion character. `width(0)` is called. The insertion character and any required padding are inserted into `out`; then calls `os.width(0)`.

3. Change 27.7.3.6.4 [ostream.inserters.character]/5 as indicated:

   >     template<class charT, class traits>
   >       basic_ostream<charT,traits>& operator<<(basic_ostream<charT,traits>& out,
   >                                               const charT* s);
   >     template<class charT, class traits>
   >       basic_ostream<charT,traits>& operator<<(basic_ostream<charT,traits>& out,
   >                                               const char* s);
   >     template<class traits>
   >       basic_ostream<char,traits>& operator<<(basic_ostream<char,traits>& out,
   >                                              const char* s);
   >     template<class traits>
   >       basic_ostream<char,traits>& operator<<(basic_ostream<char,traits>& out,
   >                                              const signed char* s);
   >     template<class traits>
   >       basic_ostream<char,traits>& operator<<(basic_ostream<char,traits>& out,
   >                                              const unsigned char* s);

   > > […]

   > > -5- Padding is determined as described in [facet.num.put.virtuals]. The `n` characters starting at `s` are widened using `out.widen` ([basic.ios.members])follows: A character sequence is produced, initially consisting of the elements defined by the `n` characters starting at `s` widened using `out.widen` ([basic.ios.members]). If `n` is less than `out.width()`, then enough copies of `out.fill()` are added to this sequence as necessary to pad to a width of `out.width()` characters. If `(out.flags() & ios_base::adjustfield) == ios_base::left` is `true`, the fill characters are placed after the character sequence; otherwise, they are placed before the character sequence. The widened characters and any required padding are inserted into `out`. Calls `width(0)`.

### 2048. Unnecessary `mem_fn` overloads

Section: 20.8 [function.objects], 20.8.10 [func.memfn] Status: Tentatively Ready Submitter: Jonathan Wakely Opened: 2011-04-18 Last modified: 2012-02-27

View all other issues in [function.objects].

View all issues with Tentatively Ready status.

Discussion:

The `mem_fn` overloads for member functions are redundant and misleading and should be removed from the post-C++11 WP.

I believe the history of the overloads is as follows:

In TR1 and in C++0x prior to the N2798 draft, `mem_fn` was specified by a single signature:

>     template<class R, class T> unspecified mem_fn(R T::* pm);

and was accompanied by the remark "Implementations may implement `mem_fn` as a set of overloaded function templates." This remark predates variadic templates and was presumably to allow implementations to provide overloads for a limited number of function parameters, to meet the implementation-defined limit on numbers of template parameters.

N2770 "Concepts for the C++0x Standard Library: Utilities" added separate overloads for pointers to member functions, apparently so that function parameters would require the `CopyConstructible` concept (those overloads first appeared in N2322.) The overloads failed to account for varargs member functions (i.e. those declared with an ellipsis in the parameter-declaration-clause) e.g.

>     struct S {
>      int f(int, ...);
>     };

Syntactically such a function would be handled by the original `mem_fn(R T::* pm)` signature, the only minor drawback being that there would be no `CopyConstructible` requirement on the parameter list. (Core DR 547 clarifies that partial specializations can be written to match cv-qualified and ref-qualified functions to support the case where `R T::*` matches a pointer to member function type.)

LWG issue 920 pointed out that additional overloads were missing for member functions with ref-qualifiers. These were not strictly necessary, because such functions are covered by the `mem_fn(R T::* pm)` signature.

Concepts were removed from the draft and N3000 restored the original single signature and accompanying remark.

LWG 1230 was opened to strike the remark again and to add an overload for member functions (this overload was unnecessary for syntactic reasons and insufficient as it didn't handle member functions with cv-qualifiers and/or ref-qualifiers.)

920 (and 1230) were resolved by restoring a full set of (non-concept-enabled) overloads for member functions with cv-qualifiers and ref-qualifiers, but as in the concept-enabled draft there were no overloads for member functions with an ellipsis in the parameter-declaration-clause. This is what is present in the FDIS.

Following the thread beginning with message c++std-lib-30675, it is my understanding that all the `mem_fn` overloads for member functions are unnecessary and were only ever added to allow concept requirements. I'm not aware of any reason implementations cannot implement `mem_fn` as a single function template. Without concepts the overloads are redundant, and the absence of overloads for varargs functions can be interpreted to imply that varargs functions are not intended to work with `mem_fn`. Clarifying the intent by adding overloads for varargs functions would expand the list of 12 redundant overloads to 24, it would be much simpler to remove the 12 redundant overloads entirely.

[Bloomington, 2011]

Move to Review.

The issue and resolution appear to be correct, but there is some concern that the wording of INVOKE may be different depending on whether you pass a pointer-to-member-data or pointer-to-member-function. That might make the current wording necessary after all, and then we might need to add the missing elipsis overloads.

There was some concern that the Remark confirming implementors had freedom to implement this as a set of overloaded functions may need to be restored if we delete the specification for these overloads.

[2012, Kona]

Moved to Tentatively Ready by the post-Kona issues processing subgroup.

Proposed resolution:

This wording is relative to the FDIS.

1. Change the `<functional>` synopsis 20.8 [function.objects] p. 2 as follows:

   >     namespace std {
   >       […]
   >       // [func.memfn], member function adaptors:
   >       template<class R, class T> unspecified mem_fn(R T::*);
   >       template<class R, class T, class... Args>
   >       unspecified mem_fn(R (T::*)(Args...));
   >       template<class R, class T, class... Args>
   >       unspecified mem_fn(R (T::*)(Args...) const);
   >       template<class R, class T, class... Args>
   >       unspecified mem_fn(R (T::*)(Args...) volatile);
   >       template<class R, class T, class... Args>
   >       unspecified mem_fn(R (T::*)(Args...) const volatile);
   >       template<class R, class T, class... Args>
   >       unspecified mem_fn(R (T::*)(Args...) &);
   >       template<class R, class T, class... Args>
   >       unspecified mem_fn(R (T::*)(Args...) const &);
   >       template<class R, class T, class... Args>
   >       unspecified mem_fn(R (T::*)(Args...) volatile &);
   >       template<class R, class T, class... Args>
   >       unspecified mem_fn(R (T::*)(Args...) const volatile &);
   >       template<class R, class T, class... Args>
   >       unspecified mem_fn(R (T::*)(Args...) &&);
   >       template<class R, class T, class... Args>
   >       unspecified mem_fn(R (T::*)(Args...) const &&);
   >       template<class R, class T, class... Args>
   >       unspecified mem_fn(R (T::*)(Args...) volatile &&);
   >       template<class R, class T, class... Args>
   >       unspecified mem_fn(R (T::*)(Args...) const volatile &&);

   >       […]
   >     }

2. Change 20.8.10 [func.memfn] as follows:

   >     template<class R, class T> unspecified mem_fn(R T::*);
   >     template<class R, class T, class... Args>
   >     unspecified mem_fn(R (T::*)(Args...));
   >     template<class R, class T, class... Args>
   >     unspecified mem_fn(R (T::*)(Args...) const);
   >     template<class R, class T, class... Args>
   >     unspecified mem_fn(R (T::*)(Args...) volatile);
   >     template<class R, class T, class... Args>
   >     unspecified mem_fn(R (T::*)(Args...) const volatile);
   >     template<class R, class T, class... Args>
   >     unspecified mem_fn(R (T::*)(Args...) &);
   >     template<class R, class T, class... Args>
   >     unspecified mem_fn(R (T::*)(Args...) const &);
   >     template<class R, class T, class... Args>
   >     unspecified mem_fn(R (T::*)(Args...) volatile &);
   >     template<class R, class T, class... Args>
   >     unspecified mem_fn(R (T::*)(Args...) const volatile &);
   >     template<class R, class T, class... Args>
   >     unspecified mem_fn(R (T::*)(Args...) &&);
   >     template<class R, class T, class... Args>
   >     unspecified mem_fn(R (T::*)(Args...) const &&);
   >     template<class R, class T, class... Args>
   >     unspecified mem_fn(R (T::*)(Args...) volatile &&);
   >     template<class R, class T, class... Args>
   >     unspecified mem_fn(R (T::*)(Args...) const volatile &&);

### 2049. `is_destructible` is underspecified

Section: 20.9.4.3 [meta.unary.prop] Status: Tentatively Ready Submitter: Daniel Krügler Opened: 2011-04-18 Last modified: 2012-02-27

View other active issues in [meta.unary.prop].

View all other issues in [meta.unary.prop].

View all issues with Tentatively Ready status.

Discussion:

The conditions for the type trait `is_destructible` to be true are described in Table 49 — Type property predicates:

> For a complete type `T` and given
> `template <class U> struct test { U u; };`,
> `test<T>::~test()` is not deleted.

This specification does not say what the result would be for function types or for abstract types:

1. For an abstract type `X` the instantiation `test<X>` is already ill-formed, so we cannot say anything about whether the destructor would be deleted or not.
2. In regard to function types, there exists a special rule in the core language, 14.3.1 [temp.arg.type] p. 3, which excludes member functions to be declared via the type of the template parameter:

   > If a declaration acquires a function type through a type dependent on a template-parameter and this causes a declaration that does not use the syntactic form of a function declarator to have function type, the program is ill-formed.

   > [ Example:

   > >     template<class T> struct A {
   > >       static T t;
   > >     };
   > >     typedef int function();
   > >     A<function> a; // ill-formed: would declare A<function>::t
   > >                    // as a static member function

   > — end example ]

   which has the same consequence as for abstract types, namely that the corresponding instantiation of `test` is already ill-formed and we cannot say anything about the destructor.

To solve this problem, I suggest to specify function types as trivially and nothrowing destructible, because above mentioned rule is very special for templates. For non-templates, a typedef can be used to introduce a member as member function as clarified in 8.3.5 [dcl.fct] p. 10.

For abstract types, two different suggestions have been brought to my attention: Either declare them as unconditionally non-destructible or check whether the expression

>     std::declval<T&>().~T()

is well-formed in an unevaluated context. The first solution is very easy to specify, but the second version has the advantage for providing more information to user-code. This information could be quite useful, if generic code is supposed to invoke the destructor of a reference to a base class indirectly via a delete expression, as suggested by Howard Hinnant:

>     template <class T>
>     my_pointer<T>::~my_pointer() noexcept(is_nothrow_destructible<T>::value)
>     {
>        delete ptr_;
>     }

Additional to the `is_destructible` traits, its derived forms `is_trivially_destructible` and `is_nothrow_destructible` are similarly affected, because their wording refers to "the indicated destructor" and probably need to be adapted as well.

[ 2011 Bloomington ]

After discussion about to to handle the exceptional cases of reference types, function types (available by defererencing a function pointer) and `void` types, Howard supplied proposed wording.

[ 2011-08-20 Daniel comments and provides alternatives wording ]

The currently proposed wording would have the consequence that every array type is not destructible, because the pseudo-destructor requires a scalar type with the effect that the expression

>     std::declval<T&>().~T()

is not well-formed for e.g. `T` equal to `int[3]`. The intuitive solution to fix this problem would be to adapt the object type case to refer to the expression

>     std::declval<U&>().~U()

with `U` equal to `remove_all_extents<T>::type`, but that would have the effect that arrays of unknown bounds would be destructible, if the element type is destructible, which was not the case before (This was intentionally covered by the special "For a complete type T" rule in the FDIS).

Suggestion: Use the following definition instead:

> Let `U` be `remove_all_extents<T>::type`.
> For incomplete types and function types, `is_destructible<T>::value` is `false`.
> For object types, if the expression `std::declval<U&>().~U()` is well-formed
> when treated as an unevaluated operand (Clause 5), then `is_destructible<T>::value`
> is `true`, otherwise it is `false`.
> For reference types, `is_destructible<T>::value` is `true`.

This wording also harmonizes with the "unevaluated operand" phrase used in other places, there does not exist the definition of an "unevaluated context"

Note: In the actually proposed wording this wording has been slightly reordered with the same effects.

Howard's (old) proposed resolution:

> Update 20.9.4.3 [meta.unary.prop], table 49:

> `template <class T> struct is_destructible;` | For a complete type `T` and given `template <class U> struct test { U u; };`, `test<T>::~test()` is not deleted. For object types, if the expression: `std::declval<T&>().~T()` is well-formed in an unevaluated context then `is_destructible<T>::value` is `true`, otherwise it is `false`. For `void` types, `is_destructible<T>::value` is `false`. For reference types, `is_destructible<T>::value` is `true`. For function types, `is_destructible<T>::value` is `false`. | `T` shall be a complete type, (possibly cv-qualified) `void`, or an array of unknown bound.

[2012, Kona]

Moved to Tentatively Ready by the post-Kona issues processing subgroup.

Proposed resolution:

Update 20.9.4.3 [meta.unary.prop], table 49:

`template <class T> struct is_destructible;` | For a complete type `T` and given `template <class U> struct test { U u; };`, `test<T>::~test()` is not deleted. For reference types, `is_destructible<T>::value` is `true`. For incomplete types and function types, `is_destructible<T>::value` is `false`. For object types and given `U` equal to `remove_all_extents<T>::type`, if the expression `std::declval<U&>().~U()` is well-formed when treated as an unevaluated operand (Clause 5 [expr]), then `is_destructible<T>::value` is `true`, otherwise it is `false`. | `T` shall be a complete type, (possibly cv-qualified) `void`, or an array of unknown bound.

### 2056. `future_errc` enums start with value 0 (invalid value for `broken_promise`)

Section: 30.6.1 [futures.overview] Status: Tentatively Ready Submitter: Nicolai Josuttis Opened: 2011-05-18 Last modified: 2012-02-27

View all other issues in [futures.overview].

View all issues with Tentatively Ready status.

Discussion:

In 30.6.1 [futures.overview] `enum class future_errc` is defined as follows:

>     enum class future_errc {
>       broken_promise,
>       future_already_retrieved,
>       promise_already_satisfied,
>       no_state
>     };

With this declaration `broken_promise` has value 0, which means that for a `future_error f` with this code

>     f.code().operator bool()

yields false, which makes no sense. 0 has to be reserved for "no error". So, the enums defined here have to start with 1.

Howard, Anthony, and Jonathan have no objections.

[Discussion in Bloomington 2011-08-16]

Previous resolution:

> This wording is relative to the FDIS.

> 1. In 30.6.1 [futures.overview], header `<future>` synopsis, fix the declaration of `future_errc` as follows:

>    >     namespace std {
>    >       enum class future_errc {
>    >         broken_promise,
>    >         future_already_retrieved = 1,
>    >         promise_already_satisfied,
>    >         no_state,
>    >         broken_promise
>    >       };
>    >       […]
>    >     }

Is this resolution overspecified? These seem to be all implementation-defined. How do users add new values and not conflict with established error codes?

PJP proxy says: over-specified. boo.

Other error codes: look for `is_error_code_enum` specializations. Only one exists `io_errc`

Peter: I don't see any other parts of the standard that specify error codes where we have to do something similar.

Suggest that for every place where we add an error code, the following:

1. no zero values
2. all implementation defined values, so future_already_retrieved = implementation_defined
3. values are distinct

[2012, Kona]

Moved to Tentatively Ready by the post-Kona issues processing subgroup.

Proposed resolution:

This wording is relative to the FDIS.

In 30.6.1 [futures.overview], header `<future>` synopsis, fix the declaration of `future_errc` as follows:

>     namespace std {
>       enum class future_errc {
>         broken_promise = implementation defined,
>         future_already_retrieved = implementation defined,
>         promise_already_satisfied = implementation defined,
>         no_state = implementation defined
>       };
>       […]
>     }

In 30.6.1 [futures.overview], header `<future>` synopsis, add a paragraph after paragraph 2 as follows:

The enum values of `future_errc` are distinct and not zero.

### 2058. `valarray` and `begin/end`

Section: 26.6 [numarray] Status: Tentatively Ready Submitter: Gabriel Dos Reis Opened: 2011-05-17 Last modified: 2012-02-27

View all other issues in [numarray].

View all issues with Tentatively Ready status.

Discussion:

It was just brought to my attention that the pair of functions `begin/end` were added to `valarray` component. Those additions strike me as counter to the long standing agreement that `valarray<T>` is not yet another container. Valarray values are in general supposed to be treated as a whole, and as such has a loose specification allowing expression template techniques.

The addition of these functions sound to me as making it much harder (or close to impossible) to effectively use expression templates as implementation techniques, for no clear benefits.

My recommendation would be to drop `begin/end` - or at least for the `const valarray<T>&` version. I strongly believe those are defects.

[This issue was discussed on the library reflector starting from c++std-lib-30761. Some of the key conclusions of this discussion were:]

1. The `begin/end` members were added to allow `valarray` to participate in the new range-based for-loop by n2930 and not to make them container-like.
2. It is currently underspecified when the iterator values returned from `begin/end` become invalidated. To fix this, these invalidation rules need at least to reflect the invalidation rules of the references returned by the `operator[]` overloads of `valarray` (26.6.2.4 [valarray.access]).
3. A further problem is that the requirements expressed in 26.6.1 [valarray.syn] p.3-5 enforce an implementation to provide further overloads of `begin/end`, if the replacement type technique is used (which was clearly part of the design of `valarray`). Providing such additional overloads would also lead to life-time problems in examples like `begin(x + y)` where `x` and `y` are expressions involving `valarray` objects. To fix this, the `begin/end` overloads could be explicitly excluded from the general statements of 26.6.1 [valarray.syn] p.3-5. This would make it unspecified whether the expression `begin(x + y)` would be well-formed, portable code would need to write this as `begin(std::valarray<T>(x + y))`.

[ 2011 Bloomington ]

The intent of these overloads is entirely to support the new for syntax, and not to create new containers.

Stefanus provides suggested wording.

[2012, Kona]

Moved to Tenatively Ready by post-meeting issues processing group, after confirmation from Gaby.

Proposed resolution:

In 26.6.1 [valarray.syn]/4, make the following insertion:

4 Implementations introducing such replacement types shall provide additional functions and operators as follows:

- for every function taking a `const valarray<T>&` other than `begin` and `end` (26.6.10 [valarray.range]), identical functions taking the replacement types shall be added;
- for every function taking two `const valarray<T>&` arguments, identical functions taking every combination of `const valarray<T>&` and replacement types shall be added.

In 26.6.10 [valarray.range], make the following insertion:

1 In the `begin` and `end` function templates that follow, unspecified1 is a type that meets the requirements of a mutable random access iterator (24.2.7) whose `value_type` is the template parameter `T` and whose `reference` type is `T&`. unspecified2 is a type that meets the requirements of a constant random access iterator (24.2.7) whose `value_type` is the template parameter `T` and whose `reference` type is `const T&`.

2 The iterators returned by `begin` and `end` for an array are guaranteed to be valid until the member function `resize(size_t, T)` (26.6.2.8 [valarray.members]) is called for that array or until the lifetime of that array ends, whichever happens first.

### 2124. Seed sequence over-specified

Section: 26.5.1.2 [rand.req.seedseq] Status: Tentatively NAD Submitter: Alberto Ganesh Barbati Opened: 2012-01-16 Last modified: 2012-02-27

Discussion:

The seed sequence requirements described in 26.5.1.2 [rand.req.seedseq] appear to be over-specified. All seed sequence types are required to have a `result_type` nested type, a specific set of constructors, function members `size()` and `param()`, which are never used by the library. In fact, the only library components that actively use seed sequences are the random engines and all the engines need is the `generate()` member function. In particular, library components never attempts to construct seed sequence objects. These extraneous requirements are clearly written to describe the library provided type `seed_seq` type; while it's good that seed_seq has all those constructors and members, it's not a compelling reason to require a user-provided seed sequence type to implement all of them.

Suppose I want to write my own seed sequence class, this should do fine (and actually works as expected with libc++):

>     class my_seed_seq
>     {
>       /* internals */
>     public:
>       my_seed_seq(/* my own parameters */);

>       template <class It>
>       void generate(It first, It last);
>     };

>     my_seed_seq s(/* params */);
>     std::default_random_engine e(s);

The only reason to have these extra members would be to provide some support for generic serializability/persistence of seed sequence objects. I believe that would be out of the scope of the random library, so I doubt we will ever need those requirements in the future.

I therefore propose to remove all requirements from 26.5.1.2 [rand.req.seedseq] except for the presence of the `generate()` function.

[2012, Kona]

Move to Tenatively NAD. (Tentative as issue was not in pre-meeting mailing)

The 'overspecification', as such, was a deliberate intent to provide guarantees consumers of the whole random number framework may rely upon, especially in generic code. While the standard engines may be built without relying on these guarantees, this specification is part of a commitment to a broader framework, and Walter indicated future proposals in preparation for parallel generation of random numbers that may depend more inimately on these existing requirements.

Alisdair noted that the `result_type` typedef was a call-back to how we used to specify adaptable functors before TR1 `result_of` and the addition of `std::bind` and is probably not something we should be actively promoting in future libraries. However, it is too late to remove this requirement from seed sequences unless we are doing further surgery, as recommended by this issue.

Walter notes that the `result_type` protocol has not been formally deprecated by the standard. Alisdair replies that was the intent of deprecating the `bind_1st`/ `unary_function` set of templates in C++11, although we did not say anything about `result_type` in general.

Proposed resolution:

This wording is relative to the FDIS.

1. Edit 26.5.1.2 [rand.req.seedseq] p2 as indicated:

   > A class `S` satisfies the requirements of a seed sequence if the expressions shown in Table 115 are valid and have the indicated semantics, and if `S` also satisfies all other requirements of this section 26.5.1.2 [rand.req.seedseq]. In that Table and throughout this section:

   > 1. `T` is the type named by `S`'s associated `result_type`;
   > 2. `q` is a value of `S` and `r` is a possibly const value of `S`; and
   > 3. `ib` and `ie` are input iterators with an unsigned integer `value_type` of at least 32 bits;
   > 4. `rb` and `re` are mutable random access iterators with an unsigned integer `value_type` of at least 32 bits;
   > 5. `ob` is an output iterator; and
   > 6. `il` is a value of `initializer_list<T>`.

2. Ditto, in Table 115, remove all rows except the one describing `q.generate(rb, re)`:

   Table 115 — Seed sequence requirements
   Expression | Return type | Pre/Post-condition | Complexity
   --- | --- | --- | ---
   `S::result_type` | `T` | `T` is an unsigned integer type (3.9.1 [basic.fundamental]) of at least 32 bits. | compile-time
   `S()` |  | Creates a seed sequence with the same initial state as all other default-constructed seed sequences of type `S`. | constant
   `S(ib,ie)` |  | Creates a seed sequence having internal state that depends on some or all of the bits of the supplied sequence `[ib, ie)`. | `𝒪(ie - ib)`
   `S(il)` |  | Same as `S(il.begin(), il.end())`. | same as `S(il.begin(), il.end())`
   `q.generate(rb,re)` | `void` | Does nothing if `rb == re`. Otherwise, fills the supplied sequence `[rb, re)` with 32-bit quantities that depend on the sequence supplied to the constructor and possibly also depend on the history of `generate`'s previous invocations. | `𝒪(re - rb)`
   `r.size()` | `size_t` | The number of 32-bit units that would be copied by a call to `r.param`. | constant
   `r.param(ob)` | `void` | Copies to the given destination a sequence of 32-bit units that can be provided to the constructor of a second object of type `S`, and that would reproduce in that second object a state indistinguishable from the state of the first object. | `𝒪(r.size())`