2013. Do library implementers have the freedom to add constexpr?

Suppose that a particular function is not tagged as constexpr in the standard,
but that, in some particular implementation, it is possible to write it within
the constexpr constraints. If an implementer tags such a function as constexpr,
is that a violation of the standard or is it a conforming extension?

There are two questions to consider. First, is this allowed under the
as-if rule? Second, if it does not fall under as-if, is there
(and should there be) any special license granted to implementers
to do this anyway, sort of the way we allow elision of copy constructors
even though it is detectable by users?

I believe that this does not fall under "as-if", so implementers
probably don't have that freedom today. I suggest changing the WP
to grant it. Even if we decide otherwise, however, I suggest that
we make it explicit.

[
2011 Bloomington
]

General surprise this was not already in 'Ready' status, and so moved.

[
2012 Kona
]

Some concern expressed when presented to full committee for the vote to WP status
that this issue had been resolved without sufficient thought of the consequences
for diverging library implementations, as users may use SFINAE to observe
different behavior from otherwise identical code. Issue moved back to Review
status, and will be discussed again in Portland with a larger group.
Note for Portland: John Spicer has agreed to represent Core's concerns during
any such discussion within LWG.

This standard explicitly requires that certain standard library functions
are constexpr [dcl.constexpr].
An implementation shall not declare any standard library function signature as constexpr
except for those where it is explicitly required.
Within any header that provides any non-defining declarations of constexpr
functions or constructors an implementation shall provide corresponding definitions.

returns true if f bitwise or'ed with the result of calling
lookup_classname with an iterator pair that designates the character
sequence "w" is not equal to 0 and c == '_'

If the bitmask value corresponding to "w" has a non-zero value (which
it must do) then the bitwise or with any value is also non-zero, and
so isctype('_', f) returns true for any f. Obviously this is wrong,
since '_' is not in every ctype category.

There's a similar problem with the following phrases discussing the
"blank" char class.

[2011-05-06: Jonathan Wakely comments and provides suggested wording]

DR 2019 added isblank support to <locale> which simplifies the
definition of regex_traits::isctype by removing the special case for the "blank" class.

My suggestion for 2018 is to add a new table replacing the lists of
recognized names in the Remarks clause of regex_traits::lookup_classname.
I then refer to that table in the Returns clause of regex_traits::isctype
to expand on the "in an unspecified manner" wording which is too vague. The conversion
can now be described using the "is set" term defined by 17.5.2.1.3 [bitmask.types] and
the new table to convey the intented relationship between e.g.
[[:digit:]] and ctype_base::digit, which is not actually stated in the
FDIS.

The effects of isctype can then most easily be described in code,
given an "exposition only" function prototype to do the not-quite-so-unspecified conversion
from char_class_type to ctype_base::mask.

The core of LWG 2018 is the "bitwise or'ed" wording which gives the
wrong result, always evaluating to true for all values of f. That is
replaced by the condition (f&x) == x where x is the result of calling
lookup_classname with "w". I believe that's necessary, because the
"w" class could be implemented by an internal "underscore" class i.e.
x = _Alnum|_Underscore in which case (f&x) != 0 would give the wrong
result when f==_Alnum.

The proposed resolution also makes use of ctype::widen which addresses
the problem that the current wording only talks about "w" and '_' which assumes
charT is char. There's still room for improvement here:
the regex grammar in 28.13 [re.grammar] says that the class names in the
table should always be recognized, implying that e.g. U"digit" should
be recognized by regex_traits<char32_t>, but the specification of
regex_traits::lookup_classname doesn't cover that, only mentioning
char and wchar_t. Maybe the table should not distinguish narrow and
wide strings, but should just have one column and add wording to say
that regex_traits widens the name as if by using use_facet<ctype<charT>>::widen().

Another possible improvement would be to allow additional
implementation-defined extensions in isctype. An implementation is
allowed to support additional class names in lookup_classname, e.g.
[[:octdigit:]] for [0-7] or [[:bindigit:]] for [01], but the current
definition of isctype provides no way to use them unless ctype_base::mask
also supports them.

[2011-05-10: Alberto and Daniel perform minor fixes in the P/R]

[
2011 Bloomington
]

Consensus that this looks to be a correct solution, and the presentation as a table is a big improvement.

Concern that the middle section wording is a little muddled and confusing, Stefanus volunteered to reword.

-9- Returns: an unspecified value that represents the character classification named by the character
sequence designated by the iterator range [first,last). If the parameter icase is true then the
returned mask identifies the character classification without regard to the case of the characters being
matched, otherwise it does honor the case of the characters being matched.(footnote 335) The value returned shall
be independent of the case of the characters in the character sequence. If the name is not recognized
then returns a value that compares equal to 0.

-11- Effects: Determines if the character c is a member of the character classification represented by f.

-12- Returns: Converts f into a value m of type std::ctype_base::mask in an
unspecified manner, and returns true if use_facet<ctype<charT> >(getloc()).is(m, c) is true. Otherwise
returns true if f bitwise or'ed with the result of calling lookup_classname with an iterator pair that
designates the character sequence "w" is not equal to 0 and c == '_', or if f bitwise or'ed
with the result of calling lookup_classname with an iterator pair that designates the character sequence "blank"
is not equal to 0 and c is one of an implementation-defined subset of the characters for
which isspace(c, getloc()) returns true, otherwise returns false.Given an exposition-only function prototype

-6- Throws: system_error if policy is launch::async and
the implementation is unable to start a new thread.

First it seems not clear whether this only applies if policy equals
launch::async of if the async launch mode flag is set
(if policy|launch::async!=0)

In the discussion Lawrence Crowl also wrote:

More generally, I think what we want to say is that if the
implementation cannot successfully execute on one of the policies
allowed, then it must choose another. The principle would apply
to implementation-defined policies as well.

Peter Sommerlad:

Should not throw. That was the intent. "is async" meat exactly.

[2012, Portland: move to Tentatively NAD Editorial]

If no launch policy, it is undefined behavior.

Agree with Lawrence, should try all the allowed policies. We will rephrase so that
the policy argument should be lauch::async. Current wording seems good enough.

We believe this choice of policy statement is really an editorial issue.

Proposed resolution:

This wording is relative to N3691.

Change 30.6.8 [futures.async] p6, p7 as indicated:

-6- Throws:system_error if policyis==launch::async and the implementation is unable to start a new
thread.

-7- Error conditions:

resource_unavailable_try_again -- if policyis==launch::async and the system is unable to
start a new thread.

With the proposed resolution of 2067, this no longer selects the
copy constructor:

std::packaged_task<void()> p1;
std::packaged_task<void()> p2(p1);

Instead this constructor is a better match:

template <class F>
explicit packaged_task(F&& f);

This attempts to package a packaged_task, which internally tries to
copy p2, which fails because the copy constructor is deleted. For at
least one implementation the resulting error message is much less
helpful than the expected "cannot call deleted function" because it
happens after instantiating several more templates rather than in the
context where the constructor is called.

I believe the solution is to constrain to the template constructors so
the template argument F cannot be deduced as (possibly cv)
packaged_task& or packaged_task. It could be argued
this constraint is already implied because packaged_task is not
copyable and the template constructors require that "invoking a copy of f
shall behave the same as invoking f".

Daniel points out that the variadic constructor of std::thread
described in 30.3.1.2 [thread.thread.constr] has a similar problem and
suggests a similar wording change, which has been integrated below.

An alternative is to declare thread(thread&) and
packaged_task(packaged_task&) as deleted.

[2012, Portland]

This issue appears to be more about library specification than technical
concurrency issues, so should be handled in LWG.

[2012, Portland]

Move to Immediate resolution.

Howard volunteered existing implementation experience with the first change, and saw no issue that the second would introduce any new issue.

Proposed resolution:

This wording is relative to the FDIS.

Insert a new Remarks element to 30.3.1.2 [thread.thread.constr] around p3 as indicated:

Please also note that examples are non-normative, according to the ISO directives, meaning that the wording
presents no normative way to use the macro.

it's said that "It is unspecified whether an uninitialized atomic_flag object has an initial state
of set or clear.". I believe the use of "uninitialized" is inappropriate. First of all, if an object is
uninitialized it is obvious that we cannot assert anything about its state. Secondly, it doesn't address the
following cases:

The object a.flag (as a sub-object of the object a) has static-duration, yet the initialization
has to be dynamic because A::A is not constexpr.

[2012, Portland]

We would like to be able to allow more initialisation contexts for example:

C struct

C++ constructor initializer-list

However we need further input from experts with implementation specific knowledge
to identify which additional contexts (if any) would be universally valid.

Moved to open

[2012, Portland]

Move to Immediate, following review.

Some discussion over the explicit use of only copy initialization, and not direct initializtion. This is necessary to
allow the implementation of atomic_flag as an aggregate, and may be further reviewed in the future.

Proposed resolution:

[This wording is relative to N3376.]

Change 29.7 [atomics.flag]/4 as follows:

The macro ATOMIC_FLAG_INIT shall be defined in such a way that it can be used to initialize an object of
type atomic_flag to the clear state. The macro can be used in the form:

atomic_flag guard = ATOMIC_FLAG_INIT;

It is unspecified whether the macro can be used in other initialization contexts. For a complete
static-duration object, that initialization shall be static. It is unspecified whether an uninitializedUnless initialized with ATOMIC_FLAG_INIT, it is unspecified whether anatomic_flag
object has an initial state of set or clear. [ Example:

The trait is_constructible<T, Args...> is defined in terms of a helper template, create<>,
that is identical to std::declval<> except for the latter's noexcept clause.

If the absence of noexcept is critical to this definition, insert a Note of explanation; otherwise, excise
create<> and reformulate in terms of declval<> the definition of is_constructible.

[2013-09-24 Daniel comments and provides resolution suggestion]

Replacing create<> by std::declval<> would make the situation worse, because the definition of
is_constructible is based on a well-formed variable definition and there is no way to specify a variable definition
without odr-using its initializer arguments. It should also be added, that there is another problem with the specification of
all existing is_trivially_* traits, because neither create<> nor std::declval<>
are considered as trivial functions, but this should be solved by a different issue.

[2013-09-26 Nico improves wording]

The additional change is just to keep both places were create() is defined consistent.

the predicate condition for a template specialization is_constructible<T, Args...> shall be satisfied
if and only if the following variable definition would be well-formed for some invented variable t:

the predicate condition for a template specialization is_convertible<From, To> shall be satisfied if and
only if the return expression in the following code would be well-formed, including any implicit conversions
to the return type of the function:

To test() {
return create<From>();
}

[…]

2300. [CD] Redundant sections for map and multimap members should be removed

-1- The find, lower_bound, upper_bound and equal_range member functions each have two versions,
one const and the other non-const. In each case the behavior of the two functions is identical except
that the const version returns a const_iterator and the non-const version an iterator (23.2.4).

-1- The find, lower_bound, upper_bound and equal_range member functions each have two versions,
one const and one non-const. In each case the behavior of the two versions is identical except
that the const version returns a const_iterator and the non-const version an iterator (23.2.4).