This document is part of a group of related documents that
together describe the issues that have been raised regarding the
C++ Standard. The other documents in the group are:

Closed Issues List, which contains
the issues which the Committee has decided are not defects
in the International Standard, including a brief rationale
explaining the reason for the decision.

Defect Reports List, which contains
the issues that have been categorized by the Committee as Defect
Reports, as well as other issues accepted by the Committee, along
with their proposed resolutions.

Table of Contents, which contains a
summary listing of all issues in numerical order.

Index by Section, which contains a
summary listing of all issues arranged in the order of the
sections of the Standard with which they deal most directly.

Index by Status, which contains a
summary listing of all issues grouped by status.

Section references in this document reflect the section numbering
of document
WG21 N4700.

The purpose of these documents is to record the disposition of issues
that have come before the Core Language Working Group of the ANSI
(INCITS PL22.16) and ISO (WG21) C++ Standard Committee.

Some issues represent potential defects in the ISO/IEC IS
14882:2014 document and corrected defects in the earlier
2011, 2003, and 1998 documents; others refer to text in the
working draft for the next revision of the C++ language and
not to any Standard text. Issues are not necessarily formal
ISO Defect Reports (DRs). While some issues will eventually
be elevated to DR status, others will be disposed of in
other ways.

The most current public version of this document can be found at
http://www.open-std.org/jtc1/sc22/wg21.
Requests for further information about these documents should include
the document number, reference ISO/IEC 14882:2014, and be
submitted to the InterNational Committee for Information Technology Standards
(INCITS),
1250 Eye Street NW, Suite 200, Washington, DC 20005,
USA.

Revision 96, 2016-02-15: Changed the status of
issue 2047 from "ready" to
"tentatively ready" to reflect revisions to accommodate
changes in the underlying wording after the October, 2015
meeting. Reflected the results of drafting review
teleconferences held 2016-01-11 and 2016-02-08.

Revision 88, 2014-03-03: Changed the "FDIS" status to "C++11",
reflecting having voted out a new DIS. Changed issues in "WP" and
"DRWP" status to "CD3", reflecting the fact that their resolutions were
contained in the Committee Draft approved for balloting at the April, 2013
meeting. Changed the status of issue 344 to
"CD3" when it was noticed that it was resolved by the resolution of
issue 1435. Changed the status of
issue 1491 to "CD3" when it was noticed that it
was resolved by the resolution of issue 1402.
Reflected the deliberations of the
February, 2014 (Issaquah) meeting.
Added new issues
1837,
1838,
1839,
1840,
1841,
1842,
1843,
1844,
1845,
1846,
1847,
1848,
1849,
1850,
1851,
1852,
1853,
1854,
1855,
1856,
1857,
1858,
1859,
1860,
1861,
1862,
1863,
1864, and
1865.

Revision 84, 2013-05-03: Incorporated the results of the drafting
review teleconference held 2013-03-25 and the deliberations of the April, 2013
(Bristol) meeting. Changed
issue 1568 to "dup" status. Changed the
status of issue 1492 to "drafting" status,
although it was approved as a DR at the meeting, because its resolution
is to be given by another resolution that was not moved. Similarly,
issues 1356 and 1465
were incorrectly moved as defect reports and have been returned to "review"
status awaiting the adoption of issue 1351.
Also, issue 1531 was moved as a DR but was
lacking the proposed resolution in the document in the pre-meeting mailing,
so it has been returned to "ready" status to be moved at the next meeting.
Changed the resolutions of issues 1374 and
1543 to correct
clerical errors transcribing the original proposed resolutions. Began the
practice of marking proposed resolutions as "[SUPERSEDED]" when a newer
one is added.
Added new issues
1642,
1643,
1644,
1645,
1646,
1647,
1648,
1649,
1650,
1651,
1652,
1653,
1654,
1655, and
1656.

Revision 76, 2011-04-10: Reflected the results of the March
7, 2011 teleconference and the March, 2011 (Madrid) meeting, including
adding a new status, "FDIS," for issues that are resolved in the draft
advanced at that meeting for FDIS balloting. In respect for ISO rules
governing work during the balloting process, no new issues have been
included in this version of the list.

Revision 75, 2011-02-28: Reflected results of two
between-meetings teleconferences, including moving a number of issues
to "tentatively ready" status. Added drafting for a number of issues
and moved them to "review" status. Reopened issue 109 in light of recent discussion. Moved issue 1028 back to "open" status after further analysis. Moved
issues 1109 and 1127
to "DR" status, as they had been overlooked in the results of the
November, 2010 (Batavia) meeting. Added new issues
1227,
1228,
1229,
1230,
1231,
1232,
1233,
1234,
1235,
1236,
1237,
1238,
1239,
1240,
1241,
1242,
1243,
1244,
1245, and
1246.

Revision 70, 2010-08-06: Reflected results of between-meetings
teleconference, including moving a number of issues to "tentatively ready"
status, updating proposed resolutions, and moving issues
341,
355,
472, and
529 to "drafting" status for more work.
Changed issue 979 to "CD2" status, which
was overlooked in the results of the March, 2010 meeting. Closed issues
1041, 1019, and
507 as duplicates of issues
924, 314, and
260, respectively.

Revision 59, 2008-10-05: Reflected deliberations from the
San Francisco (September, 2008) meeting. Placed all issues with
"WP" status and newly-approved "DR" issues into "CD1" status, to
reflect advancing the Committee Draft for balloting. Added new
proposed resolutions to issues 696,
704, and 705
and moved them to "review" status. Changed
issue 265 to "dup" status in favor of
issue 353, which was approved in 2003.
Added new issues
710,
711,
712,
713,
714,
715,
716,
717,
718,
719,
720,
721,
722, and
723.

Revision 58, 2008-08-25: Fixed some incorrect section
references. Fixed the title of issue 692.
Changed the status of issue 603 to "WP",
as the paper that resolved it was approved in April, 2007. Moved
issue 657 back to "review" status and
added proposed wording. Added discussion to issues
693 and 697.
Added or revised resolutions for issues
606,
614,
652,
685, and
694 and moved them to "review" status.
Added new issues
704,
705,
706,
707,
708, and
709.

Revision 57, 2008-07-27: Updated the status of issues
222, 309, and
632 to reflect actions at the June, 2008
meeting that were inadvertently omitted in the preceding revision.
Added proposed wording for
issue 683 and moved it to "review" status.
Added new issues
697,
698,
699,
700,
701,
702, and
703.

Revision 55, 2008-05-18: Added proposed resolutions for
issues
220,
257,
292,
341,
539,
554,
570,
571,
576,
597,
621,
624,
626,
633,
634,
639, and
642,
and moved them to "review" status.
Moved issue 155 to "dup" status in
favor of issue 632, which was changed
to "review" status in light of its connection with the
initializer-list proposal. Moved issues 530
and 551
to "WP" status because they were resolved by the constexpr proposal.
Moved issue 646 to "review" status because
it appears to be "NAD". Changed issue 240
to "review" status (from "ready") in light of input from WG14 regarding
a similar issue. Added new issues
685,
686,
687,
688,
689,
690,
691,
692,
693, and
694.

Revision 54, 2008-03-17: Reflected deliberations from the
Bellevue (February, 2008) meeting. Restructured references inside
“definitions” sections (3 [intro.defs],
20.3 [definitions]) because the individual definitions are not
sections. Returned issue 646 to "open"
status (it was previously erroneously in "drafting" status). Moved
issues 347, 512,
and 236 to "review" status with a
recommendation to close them as "NAD." Changed issues 220 and 256 back to "open"
status and
annotated them to indicate that they have been accepted by EWG and
referred to CWG for action for C++0x. Changed issues 6 and 150 back to "open"
status and
annotated them to indicate that they have been accepted by EWG and
referred to CWG for action, but not for C++0x. Closed issues
107,
168,
229,
294, and
359 as "NAD" to reflect the recommendation
of EWG. Added new issues
673,
674,
675,
676,
677,
678,
679,
680,
681,
682,
683, and
684.

Revision 50, 2007-09-09: Updated section reference numbers to use
the numbering of the most recent working draft and added text identifying
the document number of that draft at the beginning of each issues
list document. Updated issue 475
with discussion regarding the point at which
std::uncaught_exception() becomes false. Added new issues
642,
643,
644,
645,
646,
647,
648,
649,
650, and
651.

Revision 15: 2000-11-18: Reflected deliberations from the
Toronto (October, 2000) meeting; moved the discussion of empty and
fully-initialized const objects from issue 78 into new issue 253;
added new issues 254-264.

Revision 14: 2000-10-21: Added issues 246-252; added an extra
question to issue 221 and changed its
status back to "review."

Issue status

Issues progress through various statuses as the Core Language
Working Group and, ultimately, the full PL22.16 and WG21 committees
deliberate and act. For ease of reference, issues are grouped in these
documents by their status. Issues have one of the following statuses:

Open: The issue is new or the working group has not yet
formed an opinion on the issue. If a Suggested Resolution is
given, it reflects the opinion of the issue's submitter, not
necessarily that of the working group or the Committee as a whole.

Drafting: Informal consensus has been reached in the
working group and is described in rough terms in a Tentative
Resolution, although precise wording for the change is not yet
available.

Review: Exact wording of a Proposed Resolution is now
available for an issue on which the working group previously reached
informal consensus.

Ready: The working group has reached consensus that a change
in the working draft is required, the Proposed Resolution is
correct, and the issue is ready to forward to the full Committee for
ratification.

Tentatively Ready: Like "ready" except that the resolution
was produced and approved by a subset of the working group membership
between meetings. Persons not participating in these between-meeting
activities are encouraged to review such resolutions carefully and to
alert the working group with any problems that may be found.

DR: The full Committee has approved the item as a proposed
defect report. The Proposed Resolution in an issue with this
status reflects the best judgment of the Committee at this time
regarding the action that will be taken to remedy the defect; however,
the current wording of the Standard remains in effect until such time
as a Technical Corrigendum or a revision of the Standard is
issued by ISO.

Accepted: Like a DR except that the issue concerns the
wording of the current Working Paper rather than that of the current
International Standard.

TC1: A DR issue included in Technical Corrigendum 1.
TC1 is a revision of the Standard issued in 2003.

CD1: A DR issue not resolved in TC1 but included in
Committee Draft 1. CD1 was advanced for balloting at the
September, 2008 WG21 meeting.

CD2: A DR issue not resolved in CD1 but included in
the Final Committee Draft advanced for balloting at the
March, 2010 WG21 meeting.

C++11: A DR issue not resolved in CD2 but included
in ISO/IEC 14882:2011.

CD3: A DR/DRWP or Accepted/WP issue not resolved
in C++11 but included in the Committee Draft advanceed for
balloting at the April, 2013 WG21 meeting.

C++14: A DR/DRWP or Accepted/WP issue not resolved
in CD3 but included in ISO/IEC 14882:2014.

CD4: A DR/DRWP or Accepted/WP issue not resolved in
C++14 but included in the Committee Draft advanced for balloting
at the June, 2014 WG21 meeting.

C++17: a DR/DRWP or Accepted/WP issue not resolved in
CD4 but included in ISO/IEC 14882:2017.

DRWP: A DR issue whose resolution is reflected in
the current Working Paper. The Working Paper is a draft for a
future version of the Standard.

WP: An Accepted issue whose resolution is reflected in
the current Working Paper.

Dup: The issue is identical to or a subset of another issue,
identified in a Rationale statement.

NAD: The working group has reached consensus that the issue
is not a defect in the Standard. A Rationale statement
describes the working group's reasoning.

Extension: The working group has reached consensus that the
issue is not a defect in the Standard but is a request for an
extension to the language. The working group
expresses no opinion on the merits of an issue with this status;
however, the issue will be maintained on the list for possible future
consideration as an extension proposal.

Concepts: The issue relates to the “Concepts”
proposal that was removed from the working paper at the Frankfurt (July,
2009) meeting and hence is no longer under consideration.

Concurrency: The issue deals with concurrency and
is to be handled by the Concurrency and Parallelism Study
Group (SG1) within WG21.

According to 6.4.1 [basic.lookup.unqual], lookup for
i finds T::N::i and stops. However,
according to 6.3.10 [basic.scope.hiding] paragraph 1,
the appearance of T::N::i in namespace T
does not hide ::i, so both declarations of
i are visible in the declaration of a.

It seems strange that we specify this name hiding rule
in two different ways in two different places, but they
should at least be consistent.

On a related note, the wording in 6.4.1 [basic.lookup.unqual]
paragraph 2, “as if they were declared in the nearest
enclosing namespace...” could be confusing with regard to
the “declared in the same scope” provisions of
6.3.10 [basic.scope.hiding].

Proposed resolution (November, 2017)

Change 6.3.10 [basic.scope.hiding] paragraphs 1 and 2 as follows:

A name can be hidden by an explicit declaration of that same name
in a nested declarative region or derived class
(13.2 [class.member.lookup])A declaration of a name in a nested
declarative region hides a declaration of the same name in an enclosing
declarative region; see 6.3.1 [basic.scope.declarative] and
6.4.1 [basic.lookup.unqual].

A class name (12.1 [class.name]) or enumeration name
(10.2 [dcl.enum]) can be hidden by the name of a variable, data
member, function, or enumerator declared in the same scope. If a
class name (12.1 [class.name]) or enumeration
name (10.2 [dcl.enum]) and a variable, data member,
function, or enumerator are declared in the same scopedeclarative region (in any order) with the same
name (excluding declarations made visible via using-directives
(6.4.1 [basic.lookup.unqual])), the class or enumeration name is
hidden wherever the variable, data member, function, or enumerator name is
visible.

1910.
“Shall” requirement applied to runtime behavior

If an allocation function declared with a
non-throwing exception-specification (18.4 [except.spec])
fails to allocate storage, it shall return a null pointer. Any other
allocation function that fails to allocate storage shall indicate failure
only by throwing an exception (18.1 [except.throw]) of a type that
would match a handler (18.3 [except.handle]) of
type std::bad_alloc (21.6.3.1 [bad.alloc]).

The use of the word “shall” to constrain runtime behavior
is inappropriate, as it normally identifies cases requiring a compile-time
diagnostic.

Proposed resolution (November, 2017)

Change 6.7.4 [basic.stc.dynamic] paragraph 3 as follows:

Any allocation and/or deallocation functions defined in a C ++
program, including the default versions in the library, shall conform to
the semanticsIf the behavior of an allocation or deallocation
function does not satisfy the semantic constraints specified in
6.7.4.1 [basic.stc.dynamic.allocation] and 6.7.4.2 [basic.stc.dynamic.deallocation], the
behavior is undefined.

Change 6.7.4.1 [basic.stc.dynamic.allocation] paragraph 1 as follows:

...The value of the first parameter shall beis
interpreted as the requested size of the allocation...

Change 6.7.4.1 [basic.stc.dynamic.allocation] paragraph 2 as follows:

TheAn allocation function attempts to allocate the
requested amount of storage. If it is successful, it shall returnreturns the address of the start of a block of storage whose
length in bytes shall beis at least as large as the requested size. There are no
constraints on the contents of the allocated storage on return from the
allocation function. The order, contiguity, and initial value of
storage allocated by successive calls to an allocation function are
unspecified. TheFor an allocation function other than a
reserved placement allocation function (21.6.2.3 [new.delete.placement],
the pointer returned shall beis suitably
aligned so that it can be converted to a pointer to any suitable complete
object type (21.6.2.1 [new.delete.single]) and then used to access the
object or array in the storage allocated (until the storage is explicitly
deallocated by a call to a corresponding deallocation function). Even if
the size of the space requested is zero, the request can fail. If the
request succeeds, the value returned shall beby a
replaceable allocation function is a non-null pointer value
(7.11 [conv.ptr]) p0 different from any previously
returned value p1, unless that value p1 was subsequently
passed to an operator deletea replaceable deallocation
function. Furthermore, for the library allocation
functions in 21.6.2.1 [new.delete.single] and
21.6.2.2 [new.delete.array], p0shall representrepresents the address of a block of storage disjoint from the
storage for any other object accessible to the caller. The effect of
indirecting through a pointer returned asfrom
a request for zero size is undefined.38

Change 6.7.4.1 [basic.stc.dynamic.allocation] paragraph 3 as follows:

An allocation function that fails to allocate storage can invoke the
currently installed new-handler function (21.6.3.3 [new.handler]),
if any. [Note: A program-supplied allocation function can obtain the
address of the currently installed new_handler using the
std::get_new_handler function
(21.6.3.4 [set.new.handler]). —end note] If anAn allocation function that has a non-throwing exception
specification (18.4 [except.spec]) fails to allocate storage,
it shall returnindicates failure by returning a null
pointer value. Any other allocation function that fails to
allocate storage shall indicatenever returns a null pointer
value and indicates failure only by throwing an exception
(18.1 [except.throw]) of a type that would match a handler
(18.3 [except.handle]) of type std::bad_alloc
(21.6.3.1 [bad.alloc]).

2249.
identifiers and id-expressions

An identifier is an id-expression provided it has been
suitably declared (Clause 10 [dcl.dcl]).

Not only is an identifier an id-expression by
(grammatical) definition, declarator-id is defined in terms of
id-expression, which makes this circular. If the intention was
to disallow use of undeclared identifiers as primary expressions, this
should be altered accordingly.

Proposed resolution, February, 2018:

Change 8.1.4.1 [expr.prim.id.unqual] paragraph 1 as follows:

An identifier is only an id-expressionprovidedif it has been suitably declared (Clause
10 [dcl.dcl]) or if it appears as part of a
declarator-id (Clause 11 [dcl.decl]). [Note:
For operator-function-ids, see...

A simple-type-specifier (10.1.7.2 [dcl.type.simple])
or typename-specifier (17.7 [temp.res]) followed by a
parenthesized expression-list constructs a value of the specified
type given the expression list. If the expression list is a single
expression, the type conversion expression is equivalent (in definedness,
and if defined in meaning) to the corresponding cast expression
(8.4 [expr.cast]). If the type specified is a class type, the
class type shall be complete. If the expression list specifies more than a
single value, the type shall be a class with a suitably declared
constructor (11.6 [dcl.init], 15.1 [class.ctor]), and the
expression T(x1, x2, ...) is equivalent in effect to the
declaration T t(x1, x2, ...); for some invented temporary
variable t, with the result being the value of t as a
prvalue.

This does not cover the cases when the expression-list
contains a single braced-init-list (which is neither an
expression nor more than a single value) or if it contains no
expressions as the result of an empty pack expansion.

If the initializer is a parenthesized single expression, the type
conversion expression is equivalent to the corresponding cast expression
(8.4 [expr.cast]). Otherwise, if the type is cvvoid and the initializer is ()(after pack
expansion, if any), the expression is a prvalue of the specified type
that performs no initialization. Otherwise, the expression is a prvalue of
the specified type whose result object is direct-initialized
(11.6 [dcl.init]) with the initializer. For an expression of
the form T(), TIf the initializer is a
parenthesized optional expression-list, the specified type
shall not be an array type.

2226.
Xvalues vs lvalues in conditional expressions

the most appropriate result would seem to be that the expression is
an lvalue of type const T that refers to either a or
b. However, because 8.16 [expr.cond] bullet 4.1
requires that the conversion bind directly to an lvalue, while
std::move(b) is an xvalue, the result is a const T
temporary copy-initialized from std::move(b).

Proposed resolution (November, 2017)

Change 8.16 [expr.cond] bullet 4.1 as follows:

Attempts are made to form an implicit conversion sequence from an
operand expression E1 of type T1 to a target type related
to the type T2 of the operand expression E2 as
follows:

If E2
is an lvalue, the target type is “lvalue reference to
T2”, subject to the constraint that in the conversion the
reference must bind directly (11.6.3 [dcl.init.ref]) to an
lvaluea glvalue.

...

2299.
constexpr vararg functions

It is not clear whether a constexpr function can be a vararg
function or not. In particular, it is unclear if va_list is a
literal type and whether va_start, va_arg, and
va_end produce constant expressions.

Proposed resolution (November, 2017)

Add a new bullet to the list in 8.20 [expr.const]
paragraph 2, and update the text as follows:

An expression e
is a core constant expression unless the evaluation of e,
following the rules of the abstract machine (4.6 [intro.execution]),
would evaluate one of the following expressions:

...

a relational (8.9 [expr.rel]) or equality
(8.10 [expr.eq]) operator where the result is
unspecified; or

a throw-expression (8.17 [expr.throw]).; or

an invocation of the va_arg macro
(21.10.1 [cstdarg.syn]).

If e satisfies the constraints of a core constant expression,
but evaluation of e would evaluate an operation that has undefined
behavior as specified in Clause 20 [library] through Clause
33 [thread] of this document, or an invocation of the
va_start macro (21.10.1 [cstdarg.syn]), it is
unspecified whether e is a core constant expression.

2059.
Linkage and deduced return types

Use of function return type deduction makes it possible to
define functions whose return type is a type without linkage.
Although 6.5 [basic.link] paragraph 8 permits such a
usage if the function is defined in the same translation unit
as it is used, it may be helpful to consider changing the overall
rules regarding the use of types with internal or no linkage.
As an example, the following example permits access to a local
static variable that has not been initialized:

CWG agreed that the current rule in
6.5 [basic.link] paragraph 8 is unneeded; the ODR
already prohibits use of an entity that is not defined in
the current translation unit and cannot be defined in a
different translation unit.

Proposed resolution (November, 2017)

Change 6.5 [basic.link] paragraph 8 as follows:

...A type without linkage shall not be used as the type of a
variable or function with external linkage unless

the entity has C language linkage
(10.5 [dcl.link]), or

the entity is declared within an unnamed namespace
(10.3.1 [namespace.def]), or

the entity is not odr-used (6.2 [basic.def.odr]) or is
defined in the same translation unit.

[Note: In other words, a type without linkage contains a class or
enumeration that cannot be named outside its translation unit. An
entity with external linkage declared using such a type could not
correspond to any other entity in another translation unit of the program
and thus must be defined in the translation unit if it is odr-used. Also
note that classesClasses with linkage may contain members
whose types do not have linkage, and that typedef.
Typedef names are ignored in the determination of whether a type has
linkage. —end note] [Example:

Redeclarations or specializations of a function or function
template with a declared return type that uses a placeholder
type shall also use that placeholder, not a deduced type.

The inverse should also be true (a specialization cannot use
a placeholder type if the template used a non-placeholder), but
this is not said explicitly.

Proposed resolution (November, 2017)

Change 10.1.7.4 [dcl.spec.auto] paragraph 11 as follows:

Redeclarations or specializations of a function or function template with a
declared return type that uses a placeholder type shall also use that
placeholder, not a deduced type. Similarly, redeclarations or
specializations of a function or function template with a declared return
type that does not use a placeholder type shall not use a
placeholder. [Example:

However, it fails to do so, since any parameters resulting from the
expansion of the pack would be ordinary parameters without default
arguments following a parameter with a default argument, which is
ill-formed. Thus only an empty pack would be usable with such a
declaration, which violates the restriction against such contexts in
17.7 [temp.res] bullet 8.3.

Proposed resolution, February, 2018:

Change 8.2.2 [expr.call] paragraph 4 as follows:

When a function is called, each parameter (11.3.5 [dcl.fct])
shall beis initialized (11.6 [dcl.init],
15.8 [class.copy], 15.1 [class.ctor]) with its
corresponding argument. If there is no corresponding argument, the default argument for the parameter is used; the program is ill-formed if one is not present. [Example:

—end example] If the function is a non-static
member function, the this parameter of the function
(12.2.2.1 [class.this]) shall beis
initialized with a pointer to the object of the call, converted as if by an
explicit type conversion (8.4 [expr.cast]). [Note: There is
no access or ambiguity checking...

Change 11.3.6 [dcl.fct.default] paragraph 1 as follows:

If an initializer-clause is specified in
a parameter-declaration this initializer-clause is used as a
default argument. [Note: Default arguments will be used
in calls where trailing arguments are
missing (8.2.2 [expr.call]). —end
note]

Change 11.3.6 [dcl.fct.default] paragraph 4 as follows:

For non-template functions, default arguments can be added in later
declarations of a function in the same scope. Declarations in different
scopes have completely distinct sets of default arguments. That is,
declarations in inner scopes do not acquire default arguments from
declarations in outer scopes, and vice versa. In a given function
declaration, each parameter subsequent to a parameter with a default
argument shall have a default argument supplied in this or a previous
declaration, unless the parameter was expanded from a parameter
pack, or shall be a function parameter pack. A default argument
shall not be redefined by a later declaration (not even to the same
value). [Example:

2285.
Issues with structured bindings

What is the point of declaration of a name introduced by a
structured binding? If it's the point at which it appears, we're missing a
rule to make it ill-formed to reference the name before its type is deduced
(similar to what we have for 'auto'). [Suggestion: point of declaration is
after the identifier-list, program is ill-formed if the name is
mentioned before the end of the initializer.]

Are structured bindings permitted at namespace scope? There doesn't
seem to be a rule against that. If so, what's their linkage? Is it
intentional that static , extern are disallowed? Should
we only allow automatic storage duration? [Suggestion: only permit
automatic storage duration, per the design paper.]

(If the answer to 2 is yes...) is the declaration in a variable
template permitted to use structured bindings? If so, how do you name the
result? (The bindings themselves aren't introduced
as template-names by the current wording.) If not, we're missing a
restriction on that. [Suggestion: no to question 2.]

Did we intend to guarantee that the object whose members are denoted
by bindings is kept "together":

(If yes, this means we can't synthesize independent variables for each
element of an array or struct that's bound in this way, and it's harder to
remove dead components of a destructured object.) Obviously we may need to
keep the object together if it has a non-trivial destructor. [Suggestion:
do not allow reaching the complete object from a binding.]

Should the copy->move promotion be permitted for a return of a
structured binding?

[Suggestion: allow promotion to move -- as if the binding were a real local
variable -- if the implicit underlying variable is not a reference. Maybe
also allow NRVO, depending on answer to question 8.]

Notes from the April, 2017 teleconference:

Items 1 and 3 are core issues; item 4 is NAD - the bindings are kept
together, which is implied by the existing rules about copying the object
into a hidden temporary. The remaining items are questions for EWG and
new items in "extension" status will be opened for them.

Proposed resolution, February, 2018:

Change 6.3.2 [basic.scope.pdecl] paragraph 9 as follows and
add the following new paragraph thereafter:

The point of declaration for a function-local predefined variable
(11.4 [dcl.fct.def]11.4.1 [dcl.fct.def.general])
is immediately before the function-body of a function definition.

The point of declaration of a structured binding
(11.5 [dcl.struct.bind]) is immediately after the
identifier-list of the structed binging declaration.

Add the following as a new paragraph following
11.5 [dcl.struct.bind] paragraph 1:

...taken from the corresponding structured binding declaration. The type
of the id-expressione is called E. [Note:
E is never a reference type (Clause 8 [expr]). —end
note]

If the initializer refers to one of the names introduced
by the structured binding declaration, the program is ill-formed.

(Note: In response to item 3, the current wording of
17 [temp] paragraph 1 does not allow templated structured
binding declarations, and no change is being proposed.)

...A class declaration where the class-name in the
class-head-name is a simple-template-id shall be an explicit
specialization (17.8.3 [temp.expl.spec]) or a partial specialization
(17.6.5 [temp.class.spec]). A class-specifier
whose class-head omits the class-head-name defines an unnamed
class. [Note: An unnamed class thus can't be final. —end
note]

2254.
Standard-layout classes and bit-fields

If a standard-layout class object has any non-static data members, its
address is the same as the address of its first non-static data
member. Otherwise, its address is the same as the address of its first base
class subobject (if any). [Note: There might therefore be unnamed
padding within a standard-layout struct object, but not at its beginning,
as necessary to achieve appropriate alignment. —end note]
[Note: The object and its first subobject are
pointer-interconvertible (6.9.2 [basic.compound],
8.2.9 [expr.static.cast]). —end note]

This wording does not consider the case when the first non-static
data member is a bit-field, which cannot have its address taken.

Proposed resolution, February, 2018:

Change 12.2 [class.mem] paragraph 25 as follows:

If a standard-layout class object has any non-static data members, its
address is the same as the address of its first non-static data
member if that member is not a bit-field. Otherwise, itsIts address is also the same as the address
of each of its first base class subobjects(if any). [Note: There might therefore be unnamed padding
within a standard-layout struct object inserted by an
implementation, but not at its beginning, as necessary to achieve
appropriate alignment. —end note] [Note: The object and
its first subobject are pointer-interconvertible
(6.9.2 [basic.compound], 8.2.9 [expr.static.cast]). —end
note]

2229.
Volatile unnamed bit-fields

According to 12.2.4 [class.bit] paragraph 2, unnamed bit-fields
are not members, but there does not appear to be a prohibition against
their being declared volatile. Is this intended?

Proposed resolution (November, 2017)

Change 12.2.4 [class.bit] paragraph 2 as follows:

A declaration for a bit-field that omits the identifier declares an
unnamed bit-field. Unnamed bit-fields are not members and cannot be
initialized. An unnamed bit-field shall not be declared with a
cv-qualified type. [Note: An unnamed bit-field is useful for
padding...

2237.
Can a template-id name a constructor?

Bullet 1.2 of 15.1 [class.ctor], describing declarator forms
that are considered to declare a constructor, says:

...and the id-expression has one of the following forms:

...

in a member-declaration that belongs to
the member-specification of a class template but is not a friend
declaration, the id-expression is a class-name that names the
current instantiation (17.7.2.1 [temp.dep.type]) of the
immediately-enclosing class template; or

...

The term class-name includes simple-template-id. It is
not clear that allowing a constructor declaration of the form

template<class T> struct X {
X<T>(T); // constructor
};

is useful or helpful.

Proposed resolution (November, 2017)

Change 15.1 [class.ctor] paragraph 1 as follows:

...and the id-expression has one of the following forms:

in a member-declaration that belongs to
the member-specification of a class or class template but
is not a friend declaration (14.3 [class.friend]),
the id-expression is the injected-class-name (Clause
12 [class]) of the immediately-enclosing class;entity or

in a member-declaration that belongs to
the member-specification of a class template but is not a friend
declaration, the id-expression is a class-name that names the
current instantiation (17.7.2.1 [temp.dep.type]) of the
immediately-enclosing class template; or

in a declaration at namespace scope or in a friend declaration,
the id-expression is a qualified-id that names a constructor
(6.4.3.1 [class.qual]).

Change 15.4 [class.dtor] paragraph 1 as follows:

...and the id-expression has one of the following forms:

in a member-declaration that belongs to
the member-specification of a class or class template
but is not a friend declaration
(14.3 [class.friend]), the id-expression
is ~class-name and the class-name is the
injected-class-name (Clause 12 [class]) of the
immediately-enclosing class;entity or

in a member-declaration that belongs to
the member-specification of a class template but is not a friend
declaration, the id-expression is ~class-name and
the class-name names the current instantiation
(17.7.2.1 [temp.dep.type]) of the immediately-enclosing class
template; or

in a declaration at namespace scope or in a friend declaration,
the id-expression
is nested-name-specifier~class-name and
the class-name names the same class as the
nested-name-specifier.

Add the following as a new paragraph in
C.5 [diff.cpp17]:

C.5.x Clause 15: Special member functions
[diff.cpp17.special]

Affected subclauses: 15.1 [class.ctor],
15.4 [class.dtor]
Change: A simple-template-id is no longer valid as the
declarator-id of a constructor or destructor.
Rationale: Remove potentially error-prone option for redundancy.
Effect on original feature: Valid C++ 2017 code may fail to compile.

Should X's destructor be potentially invoked by this attempt
to initialize an X object? Or,

auto *y = new Y {};

No constructor for Y is used, because this is aggregate
initialization, and a destructor for X is not strictly necessary
as there is no later initialization that might throw, but in the
corresponding default constructor case we do require that the destructor
be valid.

Perhaps the most consistent answer is that the default member
initializer should not potentially invoke the destructor unless it's used
(for symmetry with default arguments), but that aggregate initialization
should potentially invoke the destructors of all subobjects (including the
final one - exceptions could theoretically be thrown between the completion
of the construction of the final aggregate element and the notional
completion of the construction of the aggregate itself.

Proposed resolution (November, 2017)

Add the following as a new paragraph following
11.6.1 [dcl.init.aggr] paragraph 7:

An aggregate that is a class can also be initialized with a single
expression not enclosed in braces, as described in
11.6 [dcl.init].

The destructor for each element of class type is potentially
invoked (15.4 [class.dtor]) from the context where the aggregate
initialization occurs. [Note: This provision ensures that
destructors can be called for fully-constructed subobjects in case an
exception is thrown (18.2 [except.ctor]). —end
note]

Change 15.4 [class.dtor] paragraph 12 as follows:

...A destructor is potentially invoked if it is invoked or as
specified in
8.3.4 [expr.new], 11.6.1 [dcl.init.aggr],
15.6.2 [class.base.init], and 18.1 [except.throw]. A program is
ill-formed if a destructor that is potentially invoked is deleted or not
accessible from the context of the invocation.

2356.
Base class copy and move constructors should not be inherited

Base class copy and move constructors brought into a derived class via a
using-declaration should not be considered by overload resolution
when constructing a derived class object.

Proposed resolution, February, 2018:

Change 16.3.1 [over.match.funcs] paragraph 8 as follows:

A defaulted move special function (15.8 [class.copy]) that is
defined as deleted is excluded from the set of candidate functions in all
contexts. A constructor inherited from class type C
(15.6.3 [class.inhctor.init]) that has a first parameter of type
“reference to cv1P” (including such a
constructor instantiated from a template) is excluded from the set of
candidate functions when constructing an object of type cv2D if the argument list has exactly one argument and C
is reference-related to P and P is reference-related
to D. [Example:

2255.
Instantiated static data member templates

The current wording does not state that a specialization of a static
data member template (17 [temp] paragraph 1) is a static
data member, which leaves the status of an example like the following
unclear (since 8.2.5 [expr.ref] bullet 4.1 is phrased in
terms of static data members):

A function instantiated from a function template is called an instantiated
function. A class instantiated from a class template is called an
instantiated class. A member function, a member class, a member
enumeration, or a static data member of a class template instantiated from
the member definition of the class template is called, respectively, an
instantiated member function, member class, member enumeration, or static
data member. A member function instantiated from a member function template
is called an instantiated member function. A member class instantiated from
a member class template is called an instantiated member class. A
variable instantiated from a variable template is called an instantiated
variable. A static data member instantiated from a static data member
template is called an instantiated static data member.

2260.
Explicit specializations of deleted member functions

Although the Standard allows for explicitly specializing a deleted
function template, member function of a class template, or member
function template with a non-deleted definition, this seems to be
problematic for non-template member functions of class templates. For
example:

the implicit instantiation of the declarations, but not of the
definitions, default arguments, or noexcept-specifiers of
the non-deleted class member functions, member classes, scoped
member enumerations, static data members, member templates, and friends;
and

it causes the implicit instantiation of the definitions
of deleted member functions, unscoped member
enumerations, and member anonymous unions.

The implicit instantiation of a class template specialization does not cause the implicit instantiation of default arguments or noexcept-specifiers of the class member functions. [Example:

—end example] However, for the purpose of
determining whether an instantiated redeclaration is valid according to
6.2 [basic.def.odr] and 12.2 [class.mem], a declaration that
corresponds to a definition in the template is considered to be a
definition. [Example:

2088.
Late tiebreakers in partial ordering

The late tiebreakers for lvalue-vs-rvalue references and
cv-qualification in 17.9.2.4 [temp.deduct.partial] paragraph 9 are
applied

If, for a given type, deduction succeeds in both directions
(i.e., the types are identical after the transformations
above) and both P and A were reference
types (before being replaced with the type referred to
above):

(see also issues 1847 and
1157.). We need to
decide whether the rule is “deduction succeeds in both
directions” or “the types are identical.” The
latter seems more reasonable.

Proposed resolution (November, 2017)

Change 17.9.2.4 [temp.deduct.partial] paragraph 9 as follows:

If, for a given type, deduction succeeds in both directions
(i.e., the types are identical after the transformations
above) and both P and A were reference types
(before being replaced with the type referred to above):

if the type from the argument template was an lvalue reference
and the type from the parameter template was not, the parameter type is not
considered to be at least as specialized as the argument type;
otherwise,

if the type from the argument template is more cv-qualified than the
type from the parameter template (as described above), the parameter type
is not considered to be at least as specialized as the argument
type.

The intent is that this should call #4; that template clearly ought to
be more specialized.

Proposed resolution (November, 2017)

Change 17.9.2.4 [temp.deduct.partial] paragraph 4 as
follows:

:

Each type nominated above from the parameter template and the corresponding
type from the argument template are used as the types of P
and A. If a particular P contains
no template-parameters that participate in template argument
deduction, that P is not used to determine the ordering.

Change 17.9.2.5 [temp.deduct.type] paragraph 4 as follows:

...If a template parameter is used only in non-deduced contexts and is not
explicitly specified, template argument deduction fails. [Note:
Under 17.9.2.1 [temp.deduct.call] and
17.9.2.4 [temp.deduct.partial], if P contains
no template-parameters that appear in deduced contexts, no deduction
is done, so P and A need not have the same
form. —end note]

most/all implementations reject this code. However, the wording
of the Standard only invokes 17.9.3 [temp.over]
(“Overload resolution”) in cases where there is more
than one function or function template, which is not the case here.
The current wording would appear to make this well-formed because
of the application of 17.9.1 [temp.arg.explicit] paragraph 2.
Perhaps overload resolution should apply even when there is a single
function template?

Notes from the May, 2015 meeting:

This issue is mostly a duplicate of
issue 1582. However, CWG felt that it
should be clarified that overload resolution applies in all cases,
not just when templates are overloaded, so the issue is being left
open to deal with that aspect.

Proposed resolution (November, 2017)

Change 8.2.2 [expr.call] paragraph 1, splitting
it into three paragraphs, as follows:

A function call is a postfix expression followed by parentheses containing
a possibly empty, comma-separated list of initializer-clauses which
constitute the arguments to the function. The postfix expression shall have
function type or function pointer type. For a call to a non-member function
or to a static member function, the postfix expression shall be either an
lvalue that refers to a function (in which case the function-to-pointer
standard conversion (7.3 [conv.func]) is suppressed on the postfix
expression), or it shall have function pointer type. Calling a function
through an expression whose function type is different from the function
type of the called function's definition results in undefined behavior
(10.5 [dcl.link]).

For a call to a non-static member function, the postfix expression shall
be an implicit (12.2.2 [class.mfct.non-static], 12.2.3 [class.static])
or explicit class member access (8.2.5 [expr.ref]) whose
id-expression is a function member name, or a pointer-to-member
expression (8.5 [expr.mptr.oper]) selecting a function member; the call
is as a member of the class object referred to by the object expression. In
the case of an implicit class member access, the implied object is the one
pointed to by this. [Note: A member function call of the
form f() is interpreted as (*this).f() (see
12.2.2 [class.mfct.non-static]). —end note]

If a function or member function name is used, the name can be
overloaded (Clause 16 [over]), in which case the
appropriate function shall be selectedand the validity of
the call are determined according to the rules in
16.3 [over.match]. If the selected function is non-virtual, or if
the id-expression in the class member access expression is a
qualified-id, that function is called. Otherwise, its final overrider
(13.3 [class.virtual]) in the dynamic type of the object expression is
called; such a call is referred to as a virtual function
call. [Note: The dynamic type is the type of the object referred
to by the current value of the object expression. 15.7 [class.cdtor]
describes the behavior of virtual function calls when the object expression
refers to an object under construction or destruction. —end
note]

Add the following to 8.2.2 [expr.call] as a new paragraph
before the existing paragraph 4:

Calling a function through an expression whose function type is different from the function type of the called function's definition results in undefined behavior (10.5 [dcl.link]).

When a function is called, each parameter (11.3.5 [dcl.fct])
shall be initialized...

Change 16 [over] paragraph 2 as follows:

When an overloadeda function name is used in a call,
which overloaded function declaration is being
referenced isand the validity of the call are
determined by comparing the types of the arguments at the point of use with
the types of the parameters in the overloaded declarations that
are visible at the point of use. This function selection process is
called overload resolution...

Change 17.9.3 [temp.over] paragraph 1 as follows:

A function template can be overloaded either by (non-template)
functions of its name or by (other) function templates of the same
name. When a call to thatthe name of a
function or function template is written (explicitly, or implicitly
using the operator notation), template argument deduction...

Issues with "Review" Status

2297.
Unclear specification of atomic operations

It is not sufficiently clear that the only atomic operations are the
ones defined in clause 32 [atomics] by the library. The intent
is that no accesses are atomic unless the Standard describes them as
such.

An additional problem is that, e.g., new and delete
are defined to be synchronization operations, but they are not defined
in Clauses 32 [atomics] and 33 [thread].

Suggested resolution:

Change 4.7.1 [intro.races] paragraph 3 as follows:

The library defines a numberthe set of atomic
operations (Clause 32 [atomics]) and operations on mutexes
(Clause 33 [thread]) that. Some of these, and some
other library operations, such as those on mutexes (Clause
33 [thread]) are specially identified as synchronization
operations. These operations...

Notes from the April, 2017 teleconference:

CWG determined that this issue should be handled editorially; it
will be in "review" status until the change has been made and verified.

1924.
Definition of “literal” and kinds of literals

The term “literal” is used without definition except
the implicit connection with the syntactic nonterminal literal.
The relationships of English terms to syntactic nonterminals (such
as “integer literal” and integer-literal) should
be examined throughout 5.13 [lex.literal] and its subsections.

Notes from the November, 2016 meeting:

This issue will be handled editorially. It is being placed in
"review" status until that point.

1906.
Name lookup in member friend declaration

In a friend declaration naming a member function, a name used in the
function declarator and not part of a template-argument in
the declarator-id is first looked up in the scope of the member
function's class (13.2 [class.member.lookup]). If it is not found, or if the
name is part of a template-argument in the declarator-id, the
look up is as described for unqualified names in the definition of the
class granting friendship.

The corresponding specification for non-friend declarations
in paragraph 8 applies the class-scope lookup only to names that
follow the declarator-id. The same should be true in
friend declarations.

Proposed resolution (February, 2018):

Change 6.4.1 [basic.lookup.unqual] paragraph 8 as follows:

For the members of a class X, a name used in a member function
body, in a default argument, in a noexcept-specifier, in
the brace-or-equal-initializer of a non-static data member
(12.2 [class.mem]), or in the definitiondeclaration of a class member outside of the definition
of X, following the
member's declarator-id32, shall be declared in one of the
following ways:

before its use in the block in which it is used or in an
enclosing block (9.3 [stmt.block]) within the body of the
member function, or

shall beas a member of class X
or beas a member of a base class of X
(13.2 [class.member.lookup]), or

if X is a nested class of class Y
(12.2.5 [class.nest]), shall be a member of Y, or shall be
a member of a base class of Y (this lookup applies in turn
to Y's enclosing classes, starting with the innermost enclosing
class),33 or

if X is a local class (12.4 [class.local]) or is a
nested class of a local class, before the definition of class X in
a block enclosing the definition of class X, or

if X is a member of namespace N, or is a nested
class of a class that is a member of N, or is a local class or a
nested class within a local class of a function that is a member
of N, before the use of the name, in namespace N or in
one of N's enclosing namespaces., or

for a friend declaration in a class Y, in a scope that
would be searched for a name appearing within Y.

Delete 6.4.1 [basic.lookup.unqual] paragraph 10 and combine its
example with that of paragraph 8:

In a friend declaration naming a member function, a name
used in the function declarator and not part of a template-argument
in the declarator-id is first looked up in the scope of the member
function's class (13.2 [class.member.lookup]). If it is not found, or if the
name is part of a template-argument in the declarator-id, the
look up is as described for unqualified names in the definition of the
class granting friendship. [Example:

There was some concern as to whether the added lookup for friend
function declarations placed the additional lookups in the correct sequence
relative to the existing lookups and whether the new specification reflects
any existing practice.

2280.
Matching a usual deallocation function with placement new

A declaration of a placement deallocation function matches the declaration
of a placement allocation function if it has the same number of parameters
and, after parameter transformations (11.3.5 [dcl.fct]), all
parameter types except the first are identical. If the lookup finds a
single matching deallocation function, that function will be called;
otherwise, no deallocation function will be called. If the lookup finds a
usual deallocation function with a parameter of
type std::size_t (6.7.4.2 [basic.stc.dynamic.deallocation]) and that
function, considered as a placement deallocation function, would have been
selected as a match for the allocation function, the program is
ill-formed. For a non-placement allocation function, the normal
deallocation function lookup is used to find the matching deallocation
function (8.3.5 [expr.delete]).

2194.
Impossible case in list initialization

If the initializer list has no elements and T has a default
constructor, the first phase is omitted.

However, this case cannot occur. If T is a non-aggregate
class type with a default constructor and the initializer is an
empty initializer list, the object will be value-constructed, per
11.6.4 [dcl.init.list] bullet 3.4. Overload resolution is only
necessary if default-initialization (or a check of its semantic
constraints) is implied, with the relevant section concerning
candidates for overload resolution being 16.3.1.3 [over.match.ctor].

When objects of non-aggregate class type T are list-initialized
such that 11.6.4 [dcl.init.list] specifies that overload resolution is
performed according to the rules in this section, overload resolution
selects the constructor in two phases:

Initially, the candidate functions are the initializer-list
constructors (11.6.4 [dcl.init.list]) of the class T and the
argument list consists of the initializer list as a single
argument.

If no viable initializer-list constructor is found, overload
resolution is performed again, where the candidate functions are all the
constructors of the class T and the argument list consists of the
elements of the initializer list.

If the initializer list has no elements and T has a
default constructor, the first phase is omitted. In
copy-list-initialization, if an explicit constructor is chosen...

the rule in question is not used for the initialization of the
parameter. However, it is used to determine whether a valid implicit
conversion sequence exists for a. It is unclear whether an
additional change to resolve this discrepancy is needed or not.

Issues with "Drafting" Status

536.
Problems in the description of id-expressions

There are at least a couple of problems in the description of
the various id-expressions in _N4567_.5.1.1 [expr.prim.general]:

Paragraph 4 embodies an incorrect assumption about the
syntax of qualified-ids:

The operator :: followed by an identifier, a
qualified-id, or an operator-function-id is a
primary-expression.

The problem here is that the :: is actually part of the
syntax of qualified-id; consequently, “:: followed by...
a qualified-id” could be something like
“:: ::i,” which is ill-formed. Presumably
this should say something like, “A qualified-id with
no nested-name-specifier is a primary-expression.”

More importantly, some kinds of id-expressions are not
described by _N4567_.5.1.1 [expr.prim.general]. The structure of this
section is that the result, type, and lvalue-ness are specified for
each of the cases it covers:

paragraph 4 deals with qualified-ids that have no
nested-name-specifier

paragraph 7 deals with bare identifiers and with
qualified-ids containing a nested-name-specifier
that names a class

paragraph 8 deals with qualified-ids containing a
nested-name-specifier that names a namespace

This treatment leaves unspecified all the non-identifierunqualified-ids (operator-function-id,
conversion-function-id, and template-id), as well as
(perhaps) “::template-id” (it's not clear
whether the “:: followed by a qualified-id” case
is supposed to apply to template-ids or not). Note also that the
proposed resolution of issue 301 slightly
exacerbates this problem by removing the form
of operator-function-id that contains
a tmeplate-argument-list; as a result, references like
“::operator+<X>” are no longer covered in
_N4567_.5.1.1 [expr.prim.general].

1837.
Use of this in friend and local class declarations

The description of the use of this found in
_N4567_.5.1.1 [expr.prim.general] paragraphs 3 and 4 allow it to appear
in the declaration of a non-static member function following the
optional cv-qualifier-seq and in the
brace-or-equal-initializer of a non-static data member; all
other uses are prohibited. These restrictions appear to allow
questionable uses of this in several contexts. For example:

1938.
Should hosted/freestanding be implementation-defined?

Whether an implementation is hosted or freestanding is only
required to be documented by the value of
the __STDC_HOSTED__ macro
(19.8 [cpp.predefined]). Should this characteristic be
classified as implementation-defined, thus requiring
documentation?

In particular, it appears that the call
to std::launder has undefined behaviour because the
captured copy of space is not established to provide storage for
an object of type int (subclause
4.5 [intro.object] paragraph 1). Furthermore, the code has
undefined behaviour also because it attempts to access the stored
value of the int object through a glvalue of an array
type other than one of the ones allowed by subclause
6.10 [basic.lval] paragraph 8.

1332.
Handling of invalid universal-character-names

The character designated by the universal-character-name
\UNNNNNNNN is that character whose character short name in
ISO/IEC 10646 is NNNNNNNN; the character designated by the
universal-character-name \uNNNN is that character whose
character short name in ISO/IEC 10646 is 0000NNNN. If the
hexadecimal value for a universal-character-name corresponds to a
surrogate code point (in the range 0xD800-0xDFFF,
inclusive), the program is ill-formed. Additionally, if the
hexadecimal value for a universal-character-name outside the
c-char-sequence, s-char-sequence, or
r-char-sequence of a character or string literal corresponds to
a control character (in either of the ranges 0x00-0x1F or 0x7F-0x9F,
both inclusive) or to a character in the basic source character set,
the program is ill-formed.

It is not specified what should happen if the hexadecimal value
does not designate a Unicode code point: is that undefined behavior
or does it make the program ill-formed?

As an aside, a note should be added explaining why these
requirements apply to to an r-char-sequence when, as the
footnote at the end of the paragraph explains,

A sequence of characters resembling a universal-character-name in an
r-char-sequence (5.13.5 [lex.string]) does not form a
universal-character-name.

369.
Are new/delete identifiers or preprocessing-op-or-punc?

5.4 [lex.pptoken] paragraph 2 specifies that there are 5
categories of tokens in phases 3 to 6. With 5.12 [lex.operators]
paragraph 1, it is unclear whether new is an identifier or a
preprocessing-op-or-punc; likewise for delete. This is
relevant to answer the question whether

#define delete foo

is a well-formed control-line, since that requires an identifier
after the define token.

1655.
Line endings in raw string literals

If the input stream has been parsed into preprocessing
tokens up to a given character:

If the next character begins a sequence of characters that
could be the prefix and initial double quote of a raw string
literal, such as R", the next preprocessing token shall be a
raw string literal. Between the initial and final double
quote characters of the raw string, any transformations
performed in phases 1 and 2 (trigraphs,
universal-character-names, and line splicing) are reverted;
this reversion shall apply before
any d-char, r-char, or delimiting parenthesis
is identified.

However, phase 1 is defined as:

Physical source file characters are mapped, in an
implementation-defined manner, to the basic source character
set (introducing new-line characters for end-of-line
indicators) if necessary. The set of physical source file
characters accepted is implementation-defined. Trigraph
sequences (_N4140_.2.4 [lex.trigraph]) are replaced by
corresponding single-character internal representations. Any
source file character not in the basic source character set
(5.3 [lex.charset]) is replaced by the
universal-character-name that designates that character.

The reversion described in 5.4 [lex.pptoken] paragraph
3 specifically does not mention the replacement of physical
end-of-line indicators with new-line characters. Is it intended
that, for example, a CRLF in the source of a raw string literal
is to be represented as a newline character or as the original
characters?

1901.
punctuator referenced but not defined

The syntactic nonterminal punctuator appears in the grammar
for token in 5.6 [lex.token], but it is nowhere
defined. It should be merged with operator and given an
appropriate list of tokens as a definition for the merged term.

Proposed resolution (October, 2017):

Change 5.5 [lex.digraph] paragraph 2 as follows

In all respects of the language except in an
attribute-token (10.6.1 [dcl.attr.grammar]), each
alternative token behaves the same, respectively, as its primary token,
except for its spelling.18 The set of alternative tokens...

There are fivefour kinds of tokens: identifiers,
keywords, literals,19operators, and other separatorsand symbols. Blanks, horizontal and vertical tabs, newlines,
formfeeds, and comments (collectively, “white space”), as
described below, are ignored except as they serve to separate
tokens. [Note: Some white space is required to separate otherwise
adjacent identifiers, keywords, numeric literals, and alternative tokens
containing alphabetic characters. —end note]Each preprocessing-token resulting from translation phase 6
is converted into the corresponding token as follows:

If the preprocessing-token is an identifier
or is one of the preprocessing-op-or-punc tokens new or
delete, the resulting token is a keyword if it is
listed in Table 5, and otherwise is an identifier.

Otherwise, if the preprocessing-token is a
pp-number with the lexical form of an integer-literal or
floating-literal, or is a character-literal or
string-literal, the resulting token is of the corresponding
form.

Otherwise, if the preprocessing-token is a
pp-number with the lexical form of
a user-defined-integer-literal
or user-defined-floating-literal or is
a user-defined-character-literal or
user-defined-string-literal, the resulting token is a
user-defined-literal.

Otherwise, if the preprocessing-token is a
preprocessing-op-or-punc, and there is a corresponding symbol
(after converting alternative token representations to their primary
tokens), the resulting token is that symbol.

Otherwise, the program is ill-formed.

[Note: Within an attribute-token
(10.6.1 [dcl.attr.grammar]), a token formed from a
preprocessing-token that satisfies the syntactic requirements of
an identifier is considered to be an identifier with the
spelling of the preprocessing-token. —end
note]

Delete the final sentence of 5.12 [lex.operators] paragraph 1.

Each preprocessing-op-or-punc is converted to a single token in
translation phase 7 (5.2 [lex.phases]).

189.
Definition of operator and punctuator

The nonterminals operator and punctuator in
5.6 [lex.token]
are not defined. There is
a definition of the nonterminal operator in
16.5 [over.oper]
paragraph 1, but it is
apparent that the two nonterminals are not the same: the latter
includes keywords and multi-token operators and does not include the
nonoverloadable operators mentioned in paragraph 3.

There is a definition of preprocessing-op-or-punc in
5.12 [lex.operators]
, with the notation that

Each preprocessing-op-or-punc is converted to a single token in
translation phase 7 (2.1).

However, this list doesn't distinguish between operators and
punctuators, it includes digraphs and keywords (can a given
token be both a keyword and an operator at the
same time?), etc.

Suggested resolution:

Change 16.5 [over.oper]
to use the term
overloadable-operator.

Change 5.6 [lex.token]
to use the term
operator-token instead of operator (since there are
operators that are keywords and operators that are composed of more
than one token).

Change 5.12 [lex.operators]
to define
the nonterminals operator-token and punctuator.

Additional note (April, 2005):

The resolution for this problem should also address the fact that
sizeof and typeid (and potentially others like
decltype that may be added in the future) are described in
some places as “operators” but are not listed in
16.5 [over.oper] paragraph 3 among the operators that cannot be
overloaded.

1656.
Encoding of numerically-escaped characters

The escape \ooo consists of the backslash followed by one, two, or
three octal digits that are taken to specify the value of the desired
character. The escape \xhhh consists of the backslash followed
by x followed by one or more hexadecimal digits that are taken to
specify the value of the desired character. There is no limit to the number
of digits in a hexadecimal sequence. A sequence of octal or hexadecimal
digits is terminated by the first character that is not an octal digit or a
hexadecimal digit, respectively. The value of a character literal is
implementation-defined if it falls outside of the implementation-defined
range defined for char (for literals with no
prefix), char16_t (for literals prefixed
by 'u'), char32_t (for literals prefixed
by 'U'), or wchar_t (for literals prefixed
by 'L').

It is not clearly stated whether the “desired character”
being specified reflects the source or the target encoding. This
particularly affects UTF-8 string literals (5.13.5 [lex.string]
paragraph 7):

A string literal that begins with u8, such as u8"asdf",
is a UTF-8 string literal and is initialized with the given characters as
encoded in UTF-8.

For example, assuming the source encoding is Latin-1, is
u8"\xff" supposed to specify a three-byte string whose
first two bytes are 0xc3 0xbf (the UTF-8 encoding of
\u00ff) or a two-byte string whose first byte has the
value 0xff? (At least some current implementations assume the
latter interpretation.)

Notes from the September, 2013 meeting:

The second interpretation (that the escape sequence specifies the
execution-time code unit) is intended.

2333.
Escape sequences in UTF-8 character literals

The meaning of a numeric escape appearing in a UTF-8 character
literal is not clear. 5.13.3 [lex.ccon] paragraph 3
assumes that the contents of the quoted string is a character with
an ISO 10646 code point value, which is not necessarily the case
with a numeric escape, and paragraph 8 could be read to indicate
that a numeric escape specifies the actual runtime value of the
object rather than a Unicode code point. In addition, paragraph
8 only specifies the result for unprefixed and wide-character
literals, not for UTF-8 literals, so that could be read as
indicating that a numeric escape in a UTF-8 character literal is
undefined behavior (i.e., not defined by the Standard).

Notes from the August, 2017 teleconference:

An escape sequence in a UTF-8 character literal should be ill-formed.

1859.
UTF-16 in char16_t string literals

The resolution of issue 1802 clarified
that char16_t string literals can contain surrogate pairs, in
contrast to char16_t character literals. However, there is
no explicit requirement that char16_t literals be encoded as
UTF-16, although that is explicitly stated for char16_t
character literals, so it's not clear what the value is required to be
in the surrogate-pair case.

1723.
Multicharacter user-defined character literals

According to 5.13.3 [lex.ccon] paragraph 1, a multicharacter
literal like 'ab' is conditionally-supported and has
type int.

According to 5.13.8 [lex.ext] paragraph 6,

If L is a user-defined-character-literal, let ch be
the literal without its ud-suffix. S shall contain a literal
operator (16.5.8 [over.literal]) whose only parameter has the type
of ch and the literal L is treated as a call of the form

operator ""X(ch)

A user-defined-character-literal like 'ab'_foo would
thus require a literal operator

operator "" _foo(int)

However, that is not one of the signatures permitted by
16.5.8 [over.literal] paragraph 3.

Should multicharacter user-defined-character-literals be
conditionally-supported? If so, 16.5.8 [over.literal] paragraph 3
should be adjusted accordingly. If not, a note in
5.13.8 [lex.ext] paragraph 6 saying explicitly that they are not
supported would be helpful.

1735.
Out-of-range literals in user-defined-literals

The description of the numeric literals occurring as part of
user-defined-integer-literals and
user-defined-floating-literals in 5.13.8 [lex.ext] says
nothing about whether they are required to satisfy the same constraints as
literals that are not part of a user-defined-literal. In
particular, because it is the spelling, not the value, of the literal
that is used for raw literal operators and literal operator templates,
there is no particular reason that they should be restricted to the
maximum values and precisions that apply to ordinary literals (and one
could imagine that this would be a good notation for allowing literals
of extended-precision types).

Is this relaxation of limits intended to be required, or is it a
quality-of-implementation issue? Should something be said, either
normatively or non-normatively, about this question?

1529.
Nomenclature for variable vs reference non-static data member

A variable is introduced by the declaration of a reference other than
a non-static data member or of an object.

In other words, non-static data members of reference type are not
variables. This complicates the wording in a number of places, where
the text refers to “variable or data member,” presumably to
cover the reference case, but that phrasing could lead to the mistaken
impression that all data members are not variables. It would be better
if either there were a term for the current phrase “variable or
data member” or if there were a less-unwieldy term for
“non-static data member of reference type” that could be
used in place of “data member” in the current phrasing.

The issue here is that we are not permitted to implicitly define
constexpr duration::duration(duration&&) in this
program, so the expression in the initializer list is not a constant
expression (because it invokes a constexpr function which has
not been defined), so the braced initializer contains a narrowing
conversion, so the program is ill-formed.

If we uncomment line #1, the move constructor is implicitly defined
and the program is valid. This spooky action at a distance is
extremely unfortunate. Implementations diverge on this point.

There are also similar problems with implicit instantiation of
constexpr functions. It is not clear which contexts require
their instantiation. For example:

constexpr function instantiation is triggered by
constant expression evaluation. In that case, the validity of the
above program depends on the order in which that evaluation
proceeds:

If the LHS of the + is evaluated first, the program might
be valid, because the implementation might bail out evaluation before
triggering the ill-formed instantiation of h<int>.

If the RHS is evaluated first, the program is invalid, because
the instantiation fails.

constexpr function instantiation is triggered whenever
a constexpr function is referenced from an expression which
could be evaluated (note that this is not the same as being
potentially-evaluated)

These two approaches can be distinguished by code like this:

int k = sizeof(U<0 && h(0)>);

Under the first approach, this code is valid; under the second, it
is ill-formed.

A possible approach to resolving this issue would be to change the
definition of “potentially-evaluated” such that template
arguments, array bounds, and braced-init-lists (and any other
expressions which are constant evaluated) are always
potentially-evaluated, even if they appear within an unevaluated
context, and to change 17.8.1 [temp.inst] paragraph 3 to say
simply that function template specializations are implicitly
instantiated when they are odr-used.

A related question is whether putatively constexpr
constructors must be instantiated in order to determine whether their
class is a literal type or not. See
issue 1358.

Jason Merrill:

I'm concerned about unintended side-effects of such a large change
to “potentially-evaluated;” I would prefer something that
only affects constexpr.

It occurs to me that this is parallel to issue 1330: just like we want to instantiate exception specifiers
for calls in unevaluated context, we also want to instantiate
constexpr functions. I think we should define some other
term to say when there's a reference to a declaration, and then say
that the declaration is odr-used when that happens in
potentially-evaluated context.

Notes from the April, 2013 meeting:

An additional question was raised about whether constexpr
functions should be instantiated as a result of appearing within
unevaluated subexpressions of constant expressions. For example:

If constexpr instantiation happens during constant expression
evaluation, f<A> is never instantiated and the program is
well-formed. If constexpr instantiation happens during parsing,
f<A> is instantiated and the program is ill-formed.

1897.
ODR vs alternative tokens

In all respects of the language, each alternative token behaves the same,
respectively, as its primary token, except for its spelling.

However, the primary and alternative tokens are different tokens,
which runs afoul of the ODR requirement in 6.2 [basic.def.odr]
paragraph 6 that the definitions consist of the “same
sequence of tokens.” This wording should be amended to allow
for use of primary and alternative tokens.

A function whose name appears as a potentially-evaluated
expression is odr-used if it is the unique lookup result or
the selected member of a set of overloaded functions
(6.4 [basic.lookup], 16.3 [over.match],
16.4 [over.over]), unless it is a pure virtual
function and its name is not explicitly
qualified. [Note: This covers calls to named
functions (8.2.2 [expr.call]), operator overloading
(Clause 16 [over]), user-defined conversions
(15.3.2 [class.conv.fct]), allocation function for
placement new (8.3.4 [expr.new]), as well as
non-default initialization (11.6 [dcl.init]). A
constructor selected to copy or move an object of class type
is odr-used even if the call is actually elided by the
implementation (15.8 [class.copy]). —end
note] An allocation or deallocation function for a class
is odr-used by a new expression appearing in a
potentially-evaluated expression as specified in
8.3.4 [expr.new] and 15.5 [class.free]. A
deallocation function for a class is odr-used by a delete
expression appearing in a potentially-evaluated expression
as specified in 8.3.5 [expr.delete] and
15.5 [class.free].

There are a couple of problems with this specification. First,
contrary to the note, the names of overloaded operators, conversion
functions, etc., do not appear in potentially-evaluated expressions,
so the normative text does not make the note true. Also, the
“as specified in” references do not cover odr-use
explicitly, only the invocation of the functions.

One possible way of addressing these deficiencies would be a
blanket rule like,

A function is odr-used if it is invoked by a potentially-evaluated
expression.

(The existing wording about appearing in a potentially-evaluated
expression would still be needed for non-call references.)

2103.
Lvalue-to-rvalue conversion is irrelevant in odr-use of a reference

Issue 1741 accidentally caused
6.2 [basic.def.odr] to indicate that an lvalue-to-rvalue
conversion is necessary for the odr-use of a reference. This
is incorrect; any appearance of the reference name in a
potentially-evaluated expression should require the reference
to be defined.

2170.
Unclear definition of odr-use for arrays

The current definition of odr-use of a variable is problematic
when applied to an array:

A variable x whose name appears as a
potentially-evaluated expression ex is odr-used
by ex unless applying the lvalue-to-rvalue
conversion (7.1 [conv.lval]) to x yields a
constant expression (8.20 [expr.const]) that does
not invoke any non-trivial functions and, if x is
an object, ex is an element of the set of potential
results of an expression e, where either the
lvalue-to-rvalue conversion (7.1 [conv.lval]) is
applied to e, or e is a discarded-value
expression (Clause 8 [expr]).

Although the “set of potential results” test
correctly handles the subscripting operation (since the
resolution of issue 1926), it
requires applying the lvalue-to-rvalue conversion to
S::arr itself and not just to the result of the
subscripting operation. Class objects exhibit a similar
problem.

2300.
Lambdas in multiple definitions

A lambda expression in two translation units has distinct closure
types, because each such expression's type is unique within the program.
This results in an issue with the ODR, which requires that the definitions
of an entity are identical. For example, if

template <int> void f() {std::function<void()> f = []{};}

appears in two translation units, different specializations of
function's constructor template are called, which violates
6.2 [basic.def.odr] bullet 6.4.

Issue 765 dealt with a similar problem
for inline functions, but the issue still remains for templates.

554.
Definition of “declarative region” and “scope”

The various uses of the term “declarative region”
throughout the Standard indicate that the term is intended to refer
to the entire block, class, or namespace that contains a given
declaration. For example, 6.3 [basic.scope] paragraph 2
says, in part:

[Example: in

int j = 24;
int main()
{
int i = j, j;
j = 42;
}

The declarative region of the first j includes the entire
example... The declarative region of the second declaration
of j (the j immediately before the semicolon)
includes all the text between { and }...

However, the actual definition given for “declarative
region” in 6.3 [basic.scope] paragraph 1
does not match this usage:

Every name is introduced in some portion of program text called a
declarative region, which is the largest part of the program in
which that name is valid, that is, in which that name may be
used as an unqualified name to refer to the same entity.

Because (except in class scope) a name cannot be used before
it is declared, this definition contradicts the statement in the
example and many other uses of the term throughout the Standard.
As it stands, this definition is identical to that of the scope
of a name.

The term “scope” is also misused. The scope of a
declaration is defined in 6.3 [basic.scope] paragraph 1 as
the region in which the name being declared is valid. However, there
is frequent use of the phrase “the scope of a class,” not
referring to the region in which the class's name is valid but to the
declarative region of the class body, and similarly for namespaces,
functions, exception handlers, etc. There is even a mention of
looking up a name “in the scope of the
complete postfix-expression” (6.4.5 [basic.lookup.classref] paragraph 3), which is the exact inverse of the scope
of a declaration.

This terminology needs a thorough review to make it logically
consistent. (Perhaps a discussion of the scope of template
parameters could also be added to section 6.3 [basic.scope]
at the same time, as all other kinds of scopes are described there.)

Proposed resolution (November, 2006):

Change 6.3 [basic.scope] paragraph 1 as follows:

Every name is introduced in some portion of program text called a
declarative region, which is the largest part of the
program in which that name is valid, that is, in which
that name may be used as an unqualified name to refer to the same
entitya statement, block, function declarator,
function-definition, class, handler, template-declaration,
template-parameter-list of a template
template-parameter, or namespace. In general, each
particular name is validmay be used as an unqualified
name to refer to the entity of its declaration or to the
label only within some possibly discontiguous portion of
program text called its scope. To determine the scope of a
declaration...

Change 6.3 [basic.scope] paragraph 3 as follows:

The names declared by a declaration are introduced into the
scope in which the declaration occursdeclarative
region that directly encloses the declaration, except that
declaration-statements, function parameter names in the
declarator of a function-definition,
exception-declarations (6.3.3 [basic.scope.block]),
the presence of a friend specifier (14.3 [class.friend]), certain uses of the
elaborated-type-specifier (10.1.7.3 [dcl.type.elab]),
and using-directives (10.3.4 [namespace.udir]) alter
this general behavior.

Change 6.3.3 [basic.scope.block] paragraphs 1-3 and add a
new paragraph 4 before the existing paragraph 4 as follows:

A name declared in a block (9.3 [stmt.block]) is
local to that block. Its potential scope begins at its point of
declaration (6.3.2 [basic.scope.pdecl]) and ends at the end of
its declarative region.The declarative region of a name
declared in a declaration-statement is the directly
enclosing block (9.3 [stmt.block]). Such a name is local
to the block.

The potential scopedeclarative region of a
function parameter name (including one appearing in
the declarator of a function-definition or in a
lambda-parameter-declaration-clause) or of a
function-local predefined variable in a function definition
(11.4 [dcl.fct.def]) begins at its point of
declaration. If the function has a function-try-block the
potential scope of a parameter or of a function-local predefined
variable ends at the end of the last associated handler,
otherwise it ends at the end of the outermost block of the
function definition. A parameter nameis the entire
function definition or lambda-expression. Such a name is
local to the function definition and shall not be redeclared
in theany outermost block of the function
definition nor in the outermost block of any handler associated
with a function-try-blockfunction-body (including handlers of a
function-try-block) or lambda-expression.

The name in a catch exception-declarationThe declarative region of a name declared in an
exception-declaration is its entire handler. Such a
name is local to the handler and shall not be redeclared in
the outermost block of the handler.

The potential scope of any local name begins at its point
of declaration (6.3.2 [basic.scope.pdecl]) and ends at the end
of its declarative region.

Change 6.3.5 [basic.funscope] as indicated:

Labels (9.1 [stmt.label]) have function scope and
may be used anywhere in the function in which they are declared
except in members of local classes (12.4 [class.local])
of that function. Only labels have function scope.

Change 9.7 [stmt.dcl] paragraph 1 as follows:

A declaration statement introduces one or more new identifiersnames into a block; it has the form

declaration-statement:

block-declaration

[Note: If an identifiera name
introduced by a declaration was previously declared in an outer
block, the outer declaration is hidden for the remainder of the
block, after which it resumes its force (6.3.10 [basic.scope.hiding]). —end note]

[Drafting notes: This resolution deals almost exclusively
with the unclear definition of “declarative region.”
I've left the ambiguous use of “scope” alone for now.
However sections 3.3.x all have headings reading “xxx
scope,” but they don't mean the scope of a declaration but
the different kinds of declarative regions and their effects on
the scope of declarations contained therein. To me, it looks like
most of 3.4 should refer to “declarative region” and
not to “scope.”

The change to 6.7 fixes an “identifier” misuse
(e.g., extern T operator+(T,T); at block scope
introduces a name but not an identifier) and removes normative
redundancy.]

Notes from the October, 2015 meeting:

This issue has been returned to "drafting" status to be
reconciled with changes to the underlying existing text.

2165.
Namespaces, declarative regions, and translation units

The definition of “declarative region” given in
6.3.1 [basic.scope.declarative] paragraph 1 is,

Every name is introduced in some portion of program text
called a declarative region, which is the largest part of
the program in which that name is valid, that is, in which
that name may be used as an unqualified name to refer to the
same entity.

According to 10.3 [basic.namespace] paragraph 1,

Unlike other declarative regions, the definition of a
namespace can be split over several parts of one or more
translation units.

This seems like a misuse of the term “declarative
region”; in particular, a name x declared in
namespace N in translation unit A cannot
be used as an unqualified name in the part of namespace
N in translation unit B unless it is also
declared in B. See also issue 1884.

555.
Pseudo-destructor name lookup

The Standard does not completely specify how to look up the
type-name(s) in a pseudo-destructor-name (8.2 [expr.post] paragraph 1, 8.2.4 [expr.pseudo]), and what
information it does have is incorrect and/or in the wrong place.
Consider, for instance, 6.4.5 [basic.lookup.classref] paragraphs
2-3:

If the id-expression in a class member access (8.2.5 [expr.ref]) is an unqualified-id, and the type of the
object expression is of a class type C (or of pointer to a
class type C), the unqualified-id is looked up in the scope
of class C. If the type of the object expression is of pointer to
scalar type, the unqualified-id is looked up in the context of the
complete postfix-expression.

If the unqualified-id is ~type-name, and the
type of the object expression is of a class type C (or of
pointer to a class type C), the type-name is looked up
in the context of the entire postfix-expression and in the
scope of class C. The type-name shall refer to
a class-name. If type-name is found in both contexts,
the name shall refer to the same class type. If the type of the object
expression is of scalar type, the type-name is looked up in the
scope of the complete postfix-expression.

There are at least three things wrong with this passage with
respect to pseudo-destructors:

A pseudo-destructor call (8.2.4 [expr.pseudo]) is not
a “class member access”, so the statements about scalar
types in the object expressions are vacuous: the object expression in
a class member access is required to be a class type or pointer to
class type (8.2.5 [expr.ref] paragraph 2).

On a related note, the lookup for the type-name(s) in a
pseudo-destructor name should not be described in a section entitled
“Class member access.”

Although the class member access object expressions are
carefully allowed to be either a class type or a pointer to a class
type, paragraph 2 mentions only a “pointer to scalar type”
(disallowing references) and paragraph 3 deals only with a
“scalar type,” presumably disallowing pointers (although
it could possibly be a very subtle way of referring to both non-class
pointers and references to scalar types at once).

The other point at which lookup of pseudo-destructors is
mentioned is 6.4.3 [basic.lookup.qual] paragraph 5:

If a pseudo-destructor-name (8.2.4 [expr.pseudo])
contains a nested-name-specifier, the type-names are
looked up as types in the scope designated by the
nested-name-specifier.

Again, this specification is in the wrong location (a
pseudo-destructor-name is not a qualified-id and
thus should not be treated in the “Qualified name lookup”
section).

Finally, there is no place in the Standard that describes the
lookup for pseudo-destructor calls of the form
p->T::~T() and r.T::~T(), where p
and r are a pointer and reference to scalar, respectively.
To the extent that it gives any guidance at all,
6.4.5 [basic.lookup.classref] deals only with the case where the
~ immediately follows the . or ->, and
6.4.3 [basic.lookup.qual] deals only with the case where the
pseudo-destructor-name contains
a nested-name-specifier that designates a scope in which
names can be looked up.

See document J16/06-0008 = WG21 N1938 for further discussion of
this and related issues, including 244,
305, 399,
and 414.

Proposed resolution (June, 2008):

Add a new paragraph following 8.2 [expr.post]
paragraph 2 as follows:

When a postfix-expression is followed by a dot . or
arrow -> operator, the interpretation depends on the type
T of the expression preceding the operator. If the operator
is ., T shall be a scalar type or a complete class
type; otherwise, T shall be a pointer to a scalar type or a
pointer to a complete class type. When T is a (pointer to) a
scalar type, the postfix-expression to which the operator
belongs shall be a pseudo-destructor call (8.2.4 [expr.pseudo]); otherwise, it shall be a class member access
(8.2.5 [expr.ref]).

Change 8.2.4 [expr.pseudo] paragraph 2 as follows:

The left-hand side of the dot operator shall be of scalar type. The
left-hand side of the arrow operator shall be of pointer to scalar
type. This scalar typeThe type of the expression preceding the dot
operator, or the type to which the expression preceding the arrow
operator points, is the object type...

Change 8.2.5 [expr.ref] paragraph 2 as follows:

For the first option (dot) the type of the first expression (the
object expression) shall be “class object” (of a
complete type)is a class type. For the second option
(arrow) the type of the first expression (the pointer expression)
shall be “pointer to class object” (of a complete
type)is a pointer to a class type. In these cases, the
id-expression shall name a member of the class or of one of its
base classes.

Add a new paragraph following 6.4 [basic.lookup]
paragraph 2 as follows:

In a pseudo-destructor-name that does not include a
nested-name-specifier, the type-names are looked up as
types in the context of the complete expression.

Delete the last sentence of 6.4.5 [basic.lookup.classref]
paragraph 2:

If the id-expression in a class member access (8.2.5 [expr.ref]) is an unqualified-id, and the type of the object
expression is of a class type C, the
unqualified-id is looked up in the scope of class
C. If the type of the object expression is of pointer to
scalar type, the unqualified-id is looked up in the
context of the complete postfix-expression.

Notes from the August, 2011 meeting:

The proposed resolution must be updated with respect to the current
wording of the WP.

192.
Name lookup in parameters

The description of name lookup in the
parameter-declaration-clause of member functions in
6.4.1 [basic.lookup.unqual]
paragraphs 7-8 is
flawed in at least two regards.

First, both paragraphs 7 and 8 apply to the
parameter-declaration-clause of a member function definition
and give different rules for the lookup. Paragraph 7 applies to names
"used in the definition of a class X outside of a member
function body...," which includes the
parameter-declaration-clause of a member function definition,
while paragraph 8 applies to names following the function's
declarator-id (see the proposed resolution of
issue 41), including the
parameter-declaration-clause.

Second, paragraph 8 appears to apply to the type names used in the
parameter-declaration-clause of a member function defined
inside the class definition. That is, it appears to allow the
following code, which was not the intent of the Committee:

struct S {
void f(I i) { }
typedef int I;
};

Additional note, January, 2012:

brace-or-equal-initializers for non-static data members are
intended effectively as syntactic sugar for mem-initializers in
constructor definitions; the lookup should be the same.

Its resolution attempted to make such constructs unambiguously
ill-formed by allowing any identifier, not just namespaces and types,
to appear in a nested-name-specifier, apparently on the
assumption that C in this case would become part of an
ill-formed nested-name-specifier instead of being taken as
the unqualified-id in a qualified-id. Unfortunately,
the current specification does not implement that intent, leaving
both parses as valid possibilities.

A different approach might be to adjust the specification of the
lookup of names appearing in nested-name-specifiers from

If a :: scope resolution operator in
a nested-name-specifier is not preceded by
a decltype-specifier, lookup of the name preceding
that :: considers only namespaces, types, and templates
whose specializations are types. If the name found does not
designate a namespace or a class, enumeration, or dependent
type, the program is ill-formed.

to

Lookup of an identifier followed by a ::
scope resolution operator considers only namespaces, types, and
templates whose specializations are types. If an identifer,
template-id, or decltype-specifier is followed by
a :: scope resolution operator, the name shall designate
a namespace, class, enumeration, or dependent type, and shall form
part of a nested-name-specifier.

This approach would also remove the need for deferred lookup
for template-ids and thus resolve
issue 1771.

2070.
using-declaration with dependent nested-name-specifier

It makes no sense for a user to write a class template that
contains a using-declaration that is sometimes an
inheriting constructor declaration and sometimes pulls in a
named value from a base class; These are sufficiently
different things that we're doing them a disservice by
conflating them. We're also doing a disservice to all
readers of the code, by allowing an inheriting constructor
to be written using a syntax that does not look like one.

In an inheriting constructor using-declaration, the
nested-name-specifier and the unqualified-id should
be required to be the same identifier.

Notes from the May, 2015 meeting:

The consensus of CWG was that the same name should be required
when the nested-name-specifier is dependent and in the
using-declaration case but should be allowed to be different
in all other cases. See also issues 156
and 399.

156.
Name lookup for conversion functions

If the id-expression is a conversion-function-id, its
conversion-type-id shall denote the same
type in both the context in which the
entire postfix-expression occurs
and in the context of the class of the object
expression (or the class pointed to by the pointer expression).

a conversion-type-id of an
operator-function-id is looked up both
in the scope of the class and in the
context in which the entire postfix-expression
occurs and shall refer to the
same type in both contexts

(Note bullets 2 and 3 in paragraph 1 of
6.4.3.1 [class.qual]
refer to
postfix-expression. It would be better to use
qualified-id in both cases.)

Erwin Unruh:
The intent was that you look in both contexts. If you find it only once,
that's the symbol. If you find it in both, both symbols must be "the same"
in some respect. (If you don't find it, its an error).

Mike Miller:
What's not clear to me in these examples is whether what is
being looked up is T or int.
Clearly the T has to be
looked up somehow, but the "name" of a conversion function
clearly involves the base (non-typedefed) type, not typedefs
that might be used in a definition or reference (cf
6 [basic]
paragraph 7 and
15.3 [class.conv]
paragraph 5).
(This is true even for types that must be written
using typedefs because of the limited syntax in
conversion-type-ids — e.g., the "name" of the conversion
function in the following example

typedef void (*pf)();
struct S {
operator pf();
};

is S::operator void(*)(), even though you can't write its name
directly.)

My guess is that this means that in each scope you look up
the type named in the reference and form the canonical
operator name; if the name used in the reference isn't found
in one or the other scope, the canonical name constructed
from the other scope is used. These names must be identical,
and the conversion-type-id in the canonical operator name must
not denote different types in the two scopes (i.e., the type
might not be found in one or the other scope, but if it's found
in both, they must be the same type).

1089.
Template parameters in member selections

The nested-name-specifierT:: looks like it refers
to the template parameter. However, if this is instantiated with a
type like

struct T { int x; };
struct S: T { };

the reference will be ambiguous, since it is looked up in both the
context of the expression, finding the template parameter, and in the
class, finding the base class injected-class-name, and this could be
a deduction failure. As a result, the same declaration with a
different parameter name

template<typename U> void f(U p)->decltype(p.U::x);

is, in fact, not a redeclaration because the two can be distinguished
by SFINAE.

It would be better to add a new lookup rule that says that if a
name in a template definition resolves to a template parameter, that
name is not subject to further lookup at instantiation time.

1291.
Looking up a conversion-type-id

The Standard talks about looking up a conversion-type-id as if
it were an identifier (6.4.5 [basic.lookup.classref] paragraph 7), but that
is not exactly accurate. Presumably it should talk instead about looking
up names (if any) appearing in the type-specifier-seq of the
conversion-type-id.

1835.
Dependent member lookup before <

In a class member access expression
(8.2.5 [expr.ref]), if
the . or -> token is immediately
followed by an identifier followed by
a <, the identifier must be looked up to
determine whether the < is the beginning of a
template argument list (17.2 [temp.names]) or a
less-than operator. The identifier is first looked up in the
class of the object expression. If the identifier is not
found, it is then looked up in the context of the
entire postfix-expression and shall name a class
template.

since it is dependent and thus end cannot
be looked up in the class of the object expression, it is looked
up in the context of the postfix-expression. This lookup
finds the function template, making the expression ill-formed.

One possibility might be to limit the lookup to the class of
the object expression when the object expression is dependent.

1908.
Dual destructor lookup and template-ids

If the unqualified-id is ~type-name,
the type-name is looked up in the context of the
entire postfix-expression. If the type T of the object
expression is of a class type C, the type-name is also
looked up in the scope of class C. At least one of the lookups
shall find a name that refers to (possibly cv-qualified) T.

1839.
Lookup of block-scope extern declarations

The name of a function declared in block scope and the name of a variable
declared by a block scope extern declaration have linkage. If
there is a visible declaration of an entity with linkage having the same
name and type, ignoring entities declared outside the innermost enclosing
namespace scope, the block scope declaration declares that same entity and
receives the linkage of the previous declaration. If there is more than one
such matching entity, the program is ill-formed.

It is not clear how declarations that are in the lexical scope of
the block-scope declaration but not members of the nearest enclosing
namespace (see 10.3.1 [namespace.def] paragraph 6) should be
treated. (For example, the definition of the function in which the
block extern appears might be defined in an enclosing
namespace, with a visible declaration of the name in that namespace,
or it might be a member function of a class containing a member
function of the name being declared.) Should such declarations be
produce an error or should the lexically-nearer declaration simply
be ignored? There is implementation divergence on this point.

1884.
Unclear requirements for same-named external-linkage entities

Two names that are the same (Clause 6 [basic]) and that are
declared in different scopes shall denote the same variable, function,
type, enumerator, template or namespace if

both names have external linkage or else both names have
internal linkage and are declared in the same translation unit;
and

both names refer to members of the same namespace or to members, not
by inheritance, of the same class; and

when both names denote functions, the parameter-type-lists of the
functions (11.3.5 [dcl.fct]) are identical; and

when both names denote function templates, the signatures
(17.6.6.1 [temp.over.link]) are the same.

This is not as clear as it should be. The intent is that this
rule prevents declaring a name with extenal linkage to be, for instance,
a type in one translation unit and a namespace in a different translation
unit. It has instead been read as begging the question of what it means
for two entities to be the same. The wording should be tweaked to make
the intention clear. Among other things, it should be clarified that
"declared in" refers to the namespace of which the name is a member, not
the lexical scope in which the declaration appears (which affects friend
declarations, block-scope extern declarations, and
elaborated-type-specifiers).

There is a similar restriction in 6.3.1 [basic.scope.declarative]
paragraph 4 dealing with declarations within a single declarative
region, while 6.5 [basic.link] paragraph 9 deals with names
that are associated via linkage. The relationship between these
complementary requirements may need to be clarified as well.

2058.
More errors from internal-linkage namespaces

Issue 1603 dealt with omissions in the
application of the change to give unnamed namespaces internal linkage,
but its resolution overlooked a couple of items. According to
6.5 [basic.link] paragraph 6,

The name of a function declared in block scope and the name
of a variable declared by a block scope extern declaration
have linkage. If there is a visible declaration of an entity
with linkage having the same name and type, ignoring
entities declared outside the innermost enclosing namespace
scope, the block scope declaration declares that same entity
and receives the linkage of the previous declaration. If
there is more than one such matching entity, the program is
ill-formed. Otherwise, if no matching entity is found, the
block scope entity receives external linkage.

The last sentence should say, “...receives the
linkage of the innermost enclosing namespace.”

Also, 6.5 [basic.link] paragraph 8 says,

A type without linkage shall not be used as the type of a
variable or function with external linkage unless

...

the entity is declared within an unnamed namespace
(10.3.1 [namespace.def]), or

...

This bullet cannot occur, since a function or variable declared
within an unnamed namespace cannot have external linkage.

1294.
Side effects in dynamic/static initialization

An implementation is permitted to perform the initialization of a
non-local variable with static storage duration as a static
initialization even if such initialization is not required to be done
statically, provided that

the dynamic version of the initialization does not change the value
of any other object of namespace scope prior to its initialization,
and

the static version of the initialization produces the same value in
the initialized variable as would be produced by the dynamic
initialization if all variables not required to be initialized
statically were initialized dynamically.

This does not consider side effects of the initialization in this
determination, only the values of namespace-scope variables.

1986.
odr-use and delayed initialization

The current wording of 6.6.2 [basic.start.static] allows deferral
of static and thread_local initialization until a variable or function
in the containing translation unit is odr-used. This requires
implementations to avoid optimizing away the relevant odr-uses. We
should consider relaxing the rule to allow for such optimizations.

Proposed resolution (November, 2014):

For a variable V with thread or static storage duration,
let X be the set of all variables with the same storage duration
as V that are defined in the same translation unit
as V. If the observable behavior of the abstract machine
(4.5 [intro.object]) depends on the value of V through an
evaluation E, and E is not sequenced before the end of the
initialization of any variable in X, then the end of the
initialization of all variables in X is sequenced before E.

There is also a problem (submitted by David Majnemer) if the odr-use
occurs in a constexpr context that does not require the variable to be
constructed. For example,

CWG determined that the second part of the issue (involving
constexpr) is not a defect because the address of an
object with thread storage duration is not a constant
expression.

Additional note, May, 2015:

CWG failed to indicate where and how to apply the wording
in the proposed resolution. In addition, further review has
raised concern that “sequenced before” may be the
wrong relation to use for the static storage duration case
because it implies “in the same thread.”

Notes from the October, 2015 meeting:

The suggested wording is intended to replace some existing
wording in 6.6.2 [basic.start.static] paragraph 2. CWG
affirmed that the correct relationship is “happens
before” and not “sequenced before.”

2148.
Thread storage duration and order of initialization

The terms “ordered” and “unordered”
initialization are only defined in 6.6.2 [basic.start.static]
paragraph 2 for entities with static storage duration. They
should presumably apply to entities with thread storage duration
as well.

1634.
Temporary storage duration

Static, thread, and automatic storage durations are associated with objects
introduced by declarations (6.1 [basic.def]) and implicitly
created by the implementation (15.2 [class.temporary]).

The apparent intent of the reference to 15.2 [class.temporary] is
that a temporary whose lifetime is extended to be that of a reference with
one of those storage durations is considered also to have that storage
duration. This interpretation is buttressed by use of the phrase “an
object with the same storage duration as the temporary” (twice) in
15.2 [class.temporary] paragraph 5.

There are two problems, however: first, the specification of lifetime
extension of temporaries (also in 15.2 [class.temporary] paragraph 5)
does not say anything about storage duration. Also, nothing is said in
either of these locations about the storage duration of a temporary whose
lifetime is not extended.

The latter point is important because 6.8 [basic.life] makes
a distinction between the lifetime of an object and the acquisition and
release of the storage the object occupies, at least for objects with
non-trivial initialization and/or a non-trivial destructor. The
assumption is made in 15.2 [class.temporary] and elsewhere that the
storage in which a temporary is created is no longer available for
reuse, as specified in 6.8 [basic.life], after the lifetime of
the temporary has ended, but this assumption is not explicitly stated.
One way to make that assumption explicit would be to define a storage
duration for temporaries whose lifetime is not extended.

2073.
Allocating memory for exception objects

[Note: In particular, a global allocation function is
not called to allocate storage for objects with static
storage duration (6.7.1 [basic.stc.static]), for objects
or references with thread storage duration
(6.7.2 [basic.stc.thread]), for objects of type
std::type_info (8.2.8 [expr.typeid]), or for an
exception object (18.1 [except.throw]). —end
note]

The restriction against allocating exception objects on the
heap was intended to ensure that heap exhaustion could be reported
by throwing an exception, i.e., that obtaining storage for
std::bad_alloc could not fail because the heap was full.
However, this implicitly relied on the assumption of a single
thread and does not scale to large numbers of threads, so the
restriction should be lifted and another mechanism found for
guaranteeing the ability to throw std::bad_alloc.

Notes from the February, 2016 meeting:

The prohibition of using an allocation function appears only in a
note, although there is a normative reference to the rule in
18.1 [except.throw] paragraph 4. CWG was in favor of
retaining the prohibition of using a C++ allocation function for
the memory of an exception object, with the implicit understanding
that use of malloc would be permitted. The resolution
for this issue should delete the note and move the prohibition to
normative text in the relevant sections.

2042.
Exceptions and deallocation functions

If a deallocation function terminates by throwing an
exception, the behavior is undefined.

This seems to be in conflict with the provisions of
18.4 [except.spec]: if a deallocation function throws an
exception that is not allowed by its exception-specification,
18.4 [except.spec] paragraph 10 would appear to give the
program defined behavior (calling std::unexpected() or
std::terminate()). (Note that 18.4 [except.spec]
paragraph 18 explicitly allows an explicit
exception-specification for a deallocation function.)

If, after the lifetime of an object has ended and before the
storage which the object occupied is reused or released, a new
object is created at the storage location which the original
object occupied, a pointer that pointed to the original object, a
reference that referred to the original object, or the name of
the original object will automatically refer to the new object
and, once the lifetime of the new object has started, can be used
to manipulate the new object, if:

the storage for the new object exactly overlays the
storage location which the original object occupied, and

the new object is of the same type as the original object
(ignoring the top-level cv-qualifiers), and...

The problem here is that this wording only applies
“after the lifetime of an object has ended and
before the storage which the object occupied is
reused;” for an object of a scalar type, its lifetime only
ends when the storage is reused or released (paragraph 1),
so it appears that these restrictions cannot apply to such
objects.

1530.
Member access in out-of-lifetime objects

According to 6.8 [basic.life] paragraphs 5 and 6, a program
has undefined behavior if a pointer or glvalue designating an
out-of-lifetime object

is used to access a non-static data member or call a non-static member
function of the object

It is not clear what the word “access” means in this
context. A reasonable interpretation might be using the pointer or
glvalue as the left operand of a class member access expression;
alternatively, it might mean to read or write the value of that
member, allowing a class member access expression that is used only
to form an address or bind a reference.

This needs to be clarified. A relevant consideration is the
recent adoption of the resolution of issue 597,
which eased the former restriction on simple address manipulations
involving out-of-lifetime objects: if base-class offset calculations
are now allowed, why not non-static data member offset calculations?

This clause is phrased in terms of the execution of the constructor.
However, it is possible for an aggregate to have a non-trivial default
constructor and be initialized without executing a constructor. The
wording needs to be updated to allow for non-constructor initialization
to avoid appearing to imply undefined behavior for an example like:

1701.
Array vs sequence in object representation

The object representation of an object of type T is the sequence
of Nunsigned char objects taken up by the object of
type T, where N equals sizeof(T).

However, it is not clear that a “sequence” can be indexed,
as an array can and as is required for the implementation of
memcpy and similar code.

Additional note, November, 2014:

An additional point of concern has been raised
as to whether it is appropriate
to refer to the constituent bytes of an object as being
“objects” themselves, along with the interaction of
this specification with copying or not copying parts of the object
representation that do not participate in the value representation
of the object (“padding” bytes).

2323.
Expunge POD

The term POD no longer serves a purpose in the standard, it is
merely defined, and restrictions apply for when a few other types
preserve this vestigial property. The is_pod trait
should be deprecated, moving the definition of a POD type
alongside the trait in Annex D [depr], and any
remaining wording referring to POD should be struck, or revised
to clearly state intent (usually triviality) without mentioning
PODs.

2051.
Simplifying alias rules

The aliasing rules of 6.10 [basic.lval] paragraph 10 were
adapted from C with additions for C++. However, a number of the points
either do not apply or are subsumed by other points. For example, the
provision for aggregate and union types is needed in C for struct
assignment, which in C++ is done via constructors and assignment
operators in C++, not by accessing the complete object.

Suggested resolution:

Replace 6.10 [basic.lval] paragraph 10 as follows:

If a program attempts to access the stored value of an object
through a glvalue whose type is not similar (7.5 [conv.qual])
to one of the following types the behavior is undefined:
[Footnote:... —end footnote]

the dynamic type of the object,

the signed or unsigned type corresponding to the dynamic
type of the object, or

a char or unsigned char type.

Additional note, October, 2015:

It has been suggested
that the aliasing rules should be extended to permit an object of
an enumeration with a fixed underlying type to alias an object with
that underlying type.

1211.
Misaligned lvalues

6.11 [basic.align] speaks of “alignment
requirements,” and 6.7.4.1 [basic.stc.dynamic.allocation] requires
the result of an allocation function to point to “suitably
aligned” storage, but there is no explicit statement of
what happens when these requirements are violated (presumably
undefined behavior).

617.
Lvalue-to-rvalue conversions of uninitialized char objects

According to 7.1 [conv.lval] paragraph 1, applying the
lvalue-to-rvalue conversion to any uninitialized object results in
undefined behavior. However, character types are intended to allow
any data, including uninitialized objects and padding, to be copied
(hence the statements in 6.9.1 [basic.fundamental] paragraph 1
that “For character types, all bits of the object representation
participate in the value representation” and in
6.10 [basic.lval] paragraph 15 that char and
unsigned char types can alias any object). The
lvalue-to-rvalue conversion should be permitted on uninitialized
objects of character type without evoking undefined behavior.

In a static_cast, a conversion in which the class in
the target pointer-to-member type is a base of the class in which
the member is declared is permitted and required to work correctly,
as long as the resulting pointer-to-member is eventually
dereferenced with an object whose dynamic type contains the
member. That is, the class of the target pointer-to-member type
is not required to contain the member referred to by the value
being converted. The specification of implicit pointer-to-member
conversion is silent on this question.

(This situation cannot arise in an implicit pointer-to-member
conversion where the source value is something like &X::f,
since you can only implicitly convert from pointer-to-base-member
to pointer-to-derived-member. However, if the source value is
the result of an explicit "up-cast," the target type of the
conversion might still not contain the member referred to by the
source value.)

The target type in a static_cast is allowed to be
more cv-qualified than the source type; in an implicit conversion,
however, the cv-qualifications of the two types are required to
be identical.

The first difference seems like an oversight. It is not clear
whether the latter difference is intentional or not.

1249.
Cv-qualification of nested lambda capture

Because the l1 lambda is not marked as mutable,
its operator() is const; however, it is not clear from
the wording of 8.1.5 [expr.prim.lambda] paragraph 16 whether the
captured member of the enclosing lambda is considered const or
not.

x is only odr-used if the operand of typeid is a
polymorphic lvalue; otherwise, the operand is unevaluated
(8.2.8 [expr.typeid] paragraphs 2-3). Whether the operand is a
polymorphic lvalue depends on overload resolution in this case, which
depends on whether x is captured or not: if x is
captured, since the lambda is not mutable, the type of
x in the body of the lambda is const int, while if
it is not captured, it is just int. However, the const
int version of f returns int and the
int version of f returns a polymorphic lvalue,
leading to a conundrum: x is only captured if it is not
captured, and vice versa.

Notes from the October, 2012 meeting:

The approach favored by CWG was to specify that the operand of
typeid is considered to be odr-used for the purpose of
determining capture.

1913.
decltype((x)) in lambda-expressions

Every occurrence of decltype((x)) where x is a possibly
parenthesized id-expression that names an entity of automatic
storage duration is treated as if x were transformed into an
access to a corresponding data member of the closure type that would have
been declared if x were an odr-use of the denoted entity.

This formulation is problematic because it assumes that x
can be captured and, if captured, would result in a member of the
closure class. The former is not true if the lambda has no
capture-default, and the latter is not guaranteed if the
capture-default is &.

1937.
Incomplete specification of function pointer from lambda

The closure type for a non-generic lambda-expression with
no lambda-capture has a public non-virtual non-explicit
const conversion function to pointer to function with C ++
language linkage (10.5 [dcl.link]) having the same
parameter and return types as the closure type's function call
operator. The value returned by this conversion function shall be
the address of a function that, when invoked, has the same effect
as invoking the closure type's function call operator.

This does not mention the object for which the function call
operator would be invoked (although since there is no capture,
presumably the function call operator makes no use of the
object pointer). This could be addressed by relating the
behavior of the function call operator to a notional temporary,
or the function call operator for such closure classes could be
made static.

1973.
Which parameter-declaration-clause in a lambda-expression?

The closure type for a non-generic lambda-expression
has a public inline function call operator
(16.5.4 [over.call]) whose parameters and return
type are described by
the lambda-expression's parameter-declaration-clause
and trailing-return-type respectively.

This is insufficiently precise because the trailing-return-type
might itself contain a parameter-declaration-clause. (The
same problem also occurs for generic lambdas later in the same
paragraph.)

2086.
Reference odr-use vs implicit capture

Whether a reference is odr-used or not has less to do with the
context where it is named and more to do with its initializer. In
particular, 8.1.5 [expr.prim.lambda] bullet 12.2 leads to cases
where references that can never be odr-used are implicitly
captured:

A lambda-expression with an
associated capture-default that does not explicitly
capture this or a variable with automatic storage duration
(this excludes any id-expression that has been found
to refer to an init-capture's associated non-static
data member), is said to implicitly capture the entity
(i.e., this or a variable) if the compound-statement:

odr-uses (6.2 [basic.def.odr]) the entity, or

names the entity in a potentially-evaluated expression
(6.2 [basic.def.odr]) where the enclosing
full-expression depends on a generic lambda parameter
declared within the reaching scope of
the lambda-expression.

If a lambda-expression does not include
a lambda-declarator, it is as if
the lambda-declarator were (). The lambda
return type...

Change 8.1.5 [expr.prim.lambda] paragraph 5 as follows:

The closure type for a non-generic lambda-expression
has a public inline function call operator
(16.5.4 [over.call]) whose parameters and return
type are described by
the lambda-expression's parameter-declaration-clause
and trailing-return-type respectively. For a generic
lambda... This function call operator or operator template is declared
const (12.2.2 [class.mfct.non-static]) if and only if
the lambda-expression's parameter-declaration-clause
is not followed bylambda-declarator does not
contain the keywordmutable. It is neither...

Notes from the October, 2015 meeting:

Additional wording is needed in the proposed resolution
in paragraph 5 to handle the potential absence of the parameter
declaration clause.

the right operand of a comma operator that is the operand of
a decltype-specifier,

a temporary object is not introduced for the prvalue. The
type of the prvalue may be incomplete. [Note: as a
result, storage is not allocated for the prvalue and it is
not destroyed; thus, a class type is not instantiated as a
result of being the type of a function call in this
context. This is true regardless of whether the expression
uses function call notation or operator notation
(16.3.1.2 [over.match.oper]). —end note]
[Note: unlike the rule for
a decltype-specifier that considers whether
an id-expression is parenthesized
(10.1.7.2 [dcl.type.simple]), parentheses have no special
meaning in this context. —end note]

1880.
When are parameter objects destroyed?

The lifetime of a parameter ends when the function in which it is defined
returns. The initialization and destruction of each parameter occurs
within the context of the calling function.

This presumably means that the destruction of the parameter object
occurs before the end of the full-expression, unlike temporaries.
This is not what current implementations do, however. It is not clear
that a change to treat parameter objects like temporaries, to match
existing practice, would be an improvement, however, as it would
result in ABI breakage for implementations that destroy parameters in
the called function.

See also issue 1935 for a related
question regarding the handling of arguments to a placement
allocation function and placement deallocation function.

Notes from the June, 2014 meeting:

WG decided to make it unspecified whether parameter objects are
destroyed immediately following the call or at the end of the
full-expression to which the call belongs. This approach also
resolves issue 1935.

1521.
T{expr} with reference types

Similarly, a simple-type-specifier or typename-specifier
followed by a braced-init-list creates a temporary object of
the specified type direct-list-initialized (11.6.4 [dcl.init.list]) with the specified braced-init-list, and its
value is that temporary object as a prvalue.

This wording does not handle the case where T is a
reference type: it is not possible to create a temporary object of
that type, and presumably the result would be an xvalue, not a prvalue.

1965.
Explicit casts to reference types

The specification of dynamic_cast in
8.2.7 [expr.dynamic.cast] paragraph 2 (and const_cast
in 8.2.11 [expr.const.cast] is the same) says that the operand
of a cast to an lvalue reference type must be an lvalue, so that

(Binding a const lvalue reference to an rvalue is permitted by
8.2.9 [expr.static.cast] paragraph 4 but not by paragraphs 2 and
3.)

There is implementation divergence on the treatment of these examples.

Also, const_cast permits binding an rvalue reference to a
class prvalue but not to any other kind of prvalue, which seems like an
unnecessary restriction.

Finally, 8.2.9 [expr.static.cast] paragraph 3 allows binding an
rvalue reference to a class or array prvalue, but not to other kinds of
prvalues; those are covered in paragraph 4. This would be less confusing
if paragraph 3 only dealt with binding rvalue references to glvalues and
left all discussion of prvalues to paragraph 4, which adequately handles
the class and array cases as well.

Notes from the May, 2015 meeting:

CWG reaffirmed the status quo for dynamic_cast but felt
that const_cast should be changed to permit binding an
rvalue reference to types that have associated memory (class and
array types).

2243.
Incorrect use of implicit conversion sequence

The term “implicit conversion sequence” is now used in
some non-call contexts (e.g., 8.2.9 [expr.static.cast] paragraph 4,
8.16 [expr.cond] paragraph 4, 8.10 [expr.eq]
paragraph 4)) and it is not clear that the current definition is
suited for these additional uses. In particular, passing an argument
in a function call is always copy-initialization, but some of these
contexts require consideration of direct-initialization.

Notes from the December, 2016 teleconference:

The problem is that overload resolution relies on copy initalization
and thus does not describe direct initialization. See also
issue 1781.

232.
Is indirection through a null pointer undefined behavior?

At least a couple of places in the IS state that indirection
through a null pointer produces undefined behavior: 4.6 [intro.execution] paragraph 4 gives "dereferencing the null pointer" as an
example of undefined behavior, and 11.3.2 [dcl.ref]
paragraph 4 (in a note) uses this supposedly undefined behavior as
justification for the nonexistence of "null references."

However, 8.3.1 [expr.unary.op] paragraph 1, which describes
the unary "*" operator, does not say that the behavior is
undefined if the operand is a null pointer, as one might expect.
Furthermore, at least one passage gives dereferencing a null pointer
well-defined behavior: 8.2.8 [expr.typeid] paragraph 2
says

If the lvalue expression is obtained by applying the unary * operator
to a pointer and the pointer is a null pointer value (7.11 [conv.ptr]), the typeid expression throws the
bad_typeid exception (21.7.4 [bad.typeid]).

This is inconsistent and should be cleaned up.

Bill Gibbons:

At one point we agreed that dereferencing a null pointer was
not undefined; only using the resulting value had undefined
behavior.

For example:

char *p = 0;
char *q = &*p;

Similarly, dereferencing a pointer to the end of an array should be
allowed as long as the value is not used:

char a[10];
char *b = &a[10]; // equivalent to "char *b = &*(a+10);"

Both cases come up often enough in real code that they should be
allowed.

Mike Miller:

I can see the value in this, but it doesn't seem to be well
reflected in the wording of the Standard. For instance, presumably
*p above would have to be an lvalue in order to be the
operand of "&", but the definition of "lvalue" in
6.10 [basic.lval] paragraph 2 says that "an lvalue refers to
an object." What's the object in *p? If we were to allow
this, we would need to augment the definition to include the result of
dereferencing null and one-past-the-end-of-array.

Tom Plum:

Just to add one more recollection of the intent: I was very
happy when (I thought) we decided that it was only the attempt to
actually fetch a value that creates undefined behavior. The words
which (I thought) were intended to clarify that are the first three
sentences of the lvalue-to-rvalue conversion, 7.1 [conv.lval]:

An lvalue (6.10 [basic.lval]) of a non-function, non-array
type T can be converted to an rvalue. If T is an
incomplete type, a program that necessitates this conversion is
ill-formed. If the object to which the lvalue refers is not an object
of type T and is not an object of a type derived from
T, or if the object is uninitialized, a program that
necessitates this conversion has undefined behavior.

In other words, it is only the act of "fetching", of
lvalue-to-rvalue conversion, that triggers the ill-formed or undefined
behavior. Simply forming the lvalue expression, and then for example
taking its address, does not trigger either of those errors. I
described this approach to WG14 and it may have been incorporated into
C 1999.

Mike Miller:

If we admit the possibility of null lvalues, as Tom is suggesting
here, that significantly undercuts the rationale for prohibiting "null
references" -- what is a reference, after all, but a named lvalue? If
it's okay to create a null lvalue, as long as I don't invoke the
lvalue-to-rvalue conversion on it, why shouldn't I be able to capture
that null lvalue as a reference, with the same restrictions on its
use?

I am not arguing in favor of null references. I don't want them in
the language. What I am saying is that we need to think carefully
about adopting the permissive approach of saying that it's all right
to create null lvalues, as long as you don't use them in certain ways.
If we do that, it will be very natural for people to question why they
can't pass such an lvalue to a function, as long as the function
doesn't do anything that is not permitted on a null lvalue.

If we want to allow &*(p=0), maybe we should change
the definition of "&" to handle dereferenced null
specially, just as typeid has special handling, rather than
changing the definition of lvalue to include dereferenced nulls, and
similarly for the array_end+1 case. It's not as general, but I think
it might cause us fewer problems in the long run.

Notes from the October 2003 meeting:

See also issue 315, which deals with
the call of a static member function through a null pointer.

We agreed that the approach in the standard seems okay:
p = 0; *p; is not inherently an error. An
lvalue-to-rvalue conversion would give it undefined behavior.

An lvalue refers to an object or function or is an empty lvalue
(8.3.1 [expr.unary.op]).

Add the indicated words to 8.3.1 [expr.unary.op]
paragraph 1:

The unary * operator performs indirection: the
expression to which it is applied shall be a pointer to an object
type, or a pointer to a function type and the result is an lvalue
referring to the object or function to which the expression
points, if any. If the pointer is a null pointer value
(7.11 [conv.ptr]) or points one past the last element
of an array object (8.7 [expr.add]), the result is an
empty lvalue and does not refer to any object or function.
An empty lvalue is not modifiable. If the type of the
expression is “pointer to T,” the type of
the result is “T.” [Note: a pointer to an
incomplete type (other than cv void) can be dereferenced. The
lvalue thus obtained can be used in limited ways (to initialize a
reference, for example); this lvalue must not be converted to an
rvalue, see 7.1 [conv.lval].—end note]

Add the indicated words to 7.1 [conv.lval]
paragraph 1:

If the object to which the lvalue refers is not an object of type
T and is not an object of a type derived from
T, or if the object is uninitialized, or if the
lvalue is an empty lvalue (8.3.1 [expr.unary.op]), a
program that necessitates this conversion has undefined behavior.

Change 4.6 [intro.execution] as indicated:

Certain other operations are described in this International
Standard as undefined (for example, the effect of dereferencing
the null pointerdivision by zero).

Note (March, 2005):

The 10/2004 resolution interacts with the resolution of issue 73. We added wording to 6.9.2 [basic.compound] paragraph 3 to the effect that a pointer containing
the address one past the end of an array is considered to “point
to” another object of the same type that might be located there.
The 10/2004 resolution now says that it would be undefined behavior to
use such a pointer to fetch the value of that object. There is at
least the appearance of conflict here; it may be all right, but it at
needs to be discussed further.

Notes from the April, 2005 meeting:

The CWG agreed that there is no contradiction between this
direction and the resolution of issue 73.
However, “not modifiable” is a compile-time concept, while
in fact this deals with runtime values and thus should produce
undefined behavior instead. Also, there are other contexts in which
lvalues can occur, such as the left operand of .
or .*, which should also be restricted. Additional drafting
is required.

901.
Deleted operator delete

It is not clear from 8.3.4 [expr.new] whether a deleted
operator delete is referenced by a new-expression in
which there is no initialization or in which the initialization cannot
throw an exception, rendering the program ill-formed. (The question
also arises as to whether such a
new-expression constitutes a “use” of the
deallocation function in the sense of 6.2 [basic.def.odr].)

Notes from the July, 2009 meeting:

The rationale for defining a deallocation function as deleted would
presumably be to prevent such objects from being freed. Treating the
new-expression as a use of such a deallocation function would
mean that such objects could not be created in the first place. There
is already an exemption from freeing an object if “a suitable
deallocation function [cannot] be found;” a deleted deallocation
function should be treated similarly.

1935.
Reuse of placement arguments in deallocation

The description in 8.3.4 [expr.new] paragraph
23 regarding calling a deallocation function following an
exception during the initialization of an object resulting
from a placement new-expression says,

If a placement deallocation function is called, it is passed
the same additional arguments as were passed to the
placement allocation function, that is, the same arguments
as those specified with the new-placement syntax. If
the implementation is allowed to make a copy of any argument
as part of the call to the allocation function, it is
allowed to make a copy (of the same original value) as part
of the call to the deallocation function or to reuse the
copy made as part of the call to the allocation function. If
the copy is elided in one place, it need not be elided in
the other.

This seems curious, as it allows reuse of a parameter object
that presumably is destroyed immediately upon the return of the
allocation function (but see issue 1880
for a question about the timing of such destructions).

Notes from the November, 2014 meeting:

The resolution for issue 1880 should
mostly resolve this issue. The resolution should handle the case in
which an object can only be constructed into the parameter object
and neither copied nor moved.

2102.
Constructor checking in new-expression

If the new-expression creates an object or an array
of objects of class type, access and ambiguity control are
done for the allocation function, the deallocation function
(15.5 [class.free]), and the constructor
(15.1 [class.ctor]).

The mention of “the constructor” here is
strange. For the “object of class type” case,
access and ambiguity control are done when we perform
initialization in paragraph 17, and we might not be calling a
constructor anyway (for aggregate initialization). This
seems wrong.

For the “array of objects of class type”
case, it makes slightly more sense (we need to check the
trailing array elements can be default-initialized) but
again (a) we aren't necessarily using a constructor, (b) we
should say which constructor — and we may need
overload resolution to find it, and (c) shouldn't this be
part of initialization, so we can distinguish between the
cases where we should copy-initialize from {} and
the cases where we should default-initialize?

2013.
Pointer subtraction in large array

The common code sequence used by most implementations for
pointer subtraction involves subtracting the pointer values
to determine the number of bytes and then shifting to scale
for the size of the array element. This produces incorrect
results when the difference in bytes is larger than can be
represented by a ptrdiff_t. For example, assuming
a 32-bit ptrdiff_t:

2182.
Pointer arithmetic in array-like containers

The current direction for issue 1776
(see paper P0137) calls into question the validity of doing pointer
arithmetic to address separately-allocated but contiguous objects
in a container like std::vector. A related question is
whether there should be some allowance made for allowing pointer
arithmetic using a pointer to a base class if the derived class is
a standard-layout class with no non-static data members. It is
possible that std::launder could play a part in the
resolution of this issue.

Notes from the February, 2016 meeting:

This issue is expected to be resolved by the resolution of
issue 1776. The major problem is when the
elements of the vector contain constant or reference members;
6.8 [basic.life] paragraph 7 implies that pointer arithmetic
leading to such an object produces undefined behavior, and CWG
expects this to continue. Some changes to the interface of
std::vector may be required, perhaps using
std::launder as part of iterator processing.

1857.
Additional questions about bits

The resolution of issue 1796 addressed
only the relationship of “bits” with the null character
value. The values and arrangements of bits within an object are also
mentioned in other contexts; these should also be considered for
revision. For example, 8.8 [expr.shift] paragraph 2 says,

This appears to place constraints on the bit representation, which
(as noted in issue 1796) is not accessible
to the program. A similar statement appears in paragraph 3 for
>>.

The specification of the bitwise operations in 8.11 [expr.bit.and],
8.12 [expr.xor], and 8.13 [expr.or] uses the undefined
term “bitwise” in describing the operations, without specifying
whether it is the value or object representation that is in view.

Part of the resolution of this might be to define “bit”
(which is otherwise currently undefined in C++) as a value of a given
power of 2.

Notes from the June, 2014 meeting:

CWG decided to reformulate the description of the operations
themselves to avoid references to bits, splitting off the larger
questions of defining “bit” and the like to
issue 1943 for further
consideration.

2321.
Conditional operator and cv-qualified class prvalues

We don't convert from A to T because we can't form an
implicit conversion sequence. We don't convert from T
to A because T is more cv-qualified (even though we could
form an implicit conversion sequence). It would seem reasonable to accept
this case; it seems that we should only be using cv-qualifiers as a
tie-breaker if the class types are otherwise the same.

1542.
Compound assignment of braced-init-list

The specification of 8.18 [expr.ass] paragraph 9 is presumably
intended to allow use of a braced-init-list as the operand of a
compound assignment operator as well as a simple assignment operator,
although the normative wording does not explicitly say so. (The example
in that paragraph does include

complex<double> z;
z += { 1, 2 }; // meaning z.operator+=({1,2})

for instance, which could be read to imply compound assignment
operators for scalar types as well.)

However, the details of how this is to be implemented are not clear.
Paragraph 7 says,

The behavior of an expression of the form E1op=E2 is equivalent to E1 = E1opE2 except that E1 is evaluated only once.

Applying this pattern literally to a braced-init-list yields
invalid code: x += {1} would become
x = x + {1}, which is non-syntactic.

Another problem is how to apply the prohibition against narrowing
conversions to a compound assignment. For example,

char c;
c += {1};

would presumably always be a narrowing error, because after integral
promotions, the type of c+1 is int. The similar
issue 1078 was classified as "NAD" because
the workaround was simply to add a cast to suppress the error; however,
there is no place to put a similar cast in a compound assignment.

Notes from the October, 2012 meeting:

The incorrect description of the meaning of a compound assignment
with a braced-init-list should be fixed by CWG. The question of
whether it makes sense to apply narrowing rules to such assignments
is better addressed by EWG.

1255.
Definition problems with constexpr functions

The current wording of the Standard is not sufficiently clear regarding
the interaction of class scope (which treats the bodies of member functions
as effectively appearing after the class definition is complete) and the
use of constexpr member functions within the class definition in
contexts requiring constant expressions. For example, an array bound
cannot use a constexpr member function that relies on the
completeness of the class or on members that have not yet been declared,
but the current wording does not appear to state that.

Additional note (October, 2013):

This question also affects function return type deduction (the
auto specifier) in member functions. For example, the following
should presumably be prohibited, but the current wording is not clear:

This is ill-formed because the lifetime of the array temporary
did not start within the current evaluation. Perhaps we should
treat all lifetime-extended temporaries of const-qualified literal
type that are initialized by constant expressions as if they are
constexpr objects?

2166.
Unclear meaning of “undefined constexpr function”

According to 8.20 [expr.const] bullet 2.3, an expression
is a constant expression unless (among other reasons) it would
evaluate

an invocation of an undefined constexpr function or an
undefined constexpr constructor;

This does not address the question of the point at which
a constexpr function must be defined. The intent,
in order to allow mutually-recursive constexpr
functions, was that the function must be defined prior to
the outermost evaluation that eventually results in the
invocation, but this is not clearly stated.

2186.
Unclear point that “preceding initialization” must precede

Similar to the concern of issue 2166,
the requirement of 8.20 [expr.const] bullet 2.7.1 for

a non-volatile glvalue of integral or enumeration
type that refers to a complete non-volatile const object
with a preceding initialization, initialized with a constant
expression, or

does not specify the point at which the determination of
“preceding initialization” is made: is it at the
point at which the reference to the variable appears
lexically, or is it the point at which the outermost
constant evaluation occurs? There is implementation
divergence on this point.

1680.
Including <initializer_list> for range-based for

requires that the <initializer_list> header be
included, because the expansion of the range-based for involves
a declaration of the form

auto &&__range = { 1, 2, 3 };

and a braced-init-list causes auto to be deduced
as a specialization of std::initializer_list. This seems
unnecessary and could be eliminated by specifying that __range
has an array type for cases like this.

(It should be noted that EWG is considering a proposal to change
auto deduction for cases involving braced-init-lists,
so resolution of this issue should be coordinated with that effort.)

Notes from the September, 2013 meeting:

CWG felt that this issue should be resolved by using the array
variant of the range-based for implementation.

2115.
Order of implicit destruction vs release of automatic storage

The relative ordering between destruction of automatic variables
on exit from a block and the release of the variables' storage is
not specified by the Standard: are all the destructors executed
first and then the storage released, or are they interleaved?

Notes from the February, 2016 meeting:

CWG agreed that the storage should persist until all destructions
are complete, although the “as-if” rule would allow for
unobservable optimizations of this ordering.

1223.
Syntactic disambiguation and trailing-return-types

Because the restriction that a trailing-return-type can
appear only in a declaration with “the single type-specifierauto” (11.3.5 [dcl.fct] paragraph 2) is a
semantic, not a syntactic, restriction, it does not influence
disambiguation, which is “purely syntactic”
(9.8 [stmt.ambig] paragraph 3). Consequently, some
previously unambiguous expressions are now ambiguous. For example:

1616.
Disambiguation parsing and template parameters

The disambiguation is purely syntactic; that is, the meaning of the names
occurring in such a statement, beyond whether they are type-names or
not, is not generally used in or changed by the disambiguation. Class
templates are instantiated as necessary to determine if a qualified name is
a type-name. Disambiguation precedes parsing, and a statement
disambiguated as a declaration may be an ill-formed declaration. If, during
parsing, a name in a template parameter is bound differently than it would
be bound during a trial parse, the program is ill-formed. No diagnostic is
required. [Note: This can occur only when the name is declared
earlier in the declaration. —end note]

The statement about template parameters is confusing (and not helped by
the fact that the example that follows illustrates the general rule for
declarations and does not involve any template parameters). It is
attempting to say that a program is ill-formed if a template argument of a
class template specialization has a different value in the two parses.
With decltype this can now apply to other kinds of templates as
well, so the wording should be clarified and made more general.

2117.
Explicit specializations and constexpr function templates

If no specialization of the template would satisfy the
requirements for a constexpr function or constexpr
constructor when considered as a non-template function or
constructor, the template is ill-formed; no diagnostic
required.

This should say “instantiated template specialization”
instead of just “specialization” to clarify that
an explicit specialization is not in view here.

2309.
Restrictions on nested statements within constexpr functions

Section 10.1.5 [dcl.constexpr] bullet 3.4 specifies a list of
constructs that that the body of a constexpr function shall
not contain. However, the meaning of the word “contain” is
not clear. For example, are things appearing in the body of a nested
constexpr lambda “contained” in the body of the
constexpr function?

The intent was presumably to avoid breaking existing code,
but the new wording in 10.1.7.2 [dcl.type.simple] paragraph 2
appears to make the expression X(b, e) ill-formed:

A type-specifier of the form
typenameoptnested-name-specifieropt template-name is a
placeholder for a deduced class type
(10.1.7.5 [dcl.type.class.deduct]). The template-name shall
name a class template that is not an injected-class-name.

Suggested resolution:

Deleting the wording in question and replacing it with a
cross-reference to 17.7.1 [temp.local], which makes it
clear that the injected-class-name is a type-name and
not a template-name in this context, would seem to address
the problem adequately.

1670.
auto as conversion-type-id

If it is intended to be permitted, the details of its handling
are not clear. Also, a similar syntax has been discussed as a
possible future extension for dealing with proxy types in deduction
which, if adopted, could cause confusion.

Additional note, November, 2013:

Doubt was expressed during the 2013-11-25 drafting review
teleconference as to the usefulness of this provision. It is therefore
being left open for further consideration after C++14 is finalized.

Notes from the February, 2014 meeting:

CWG continued to express doubt as to the usefulness of this construct
but felt that if it is permitted, the rules need
clarification.

1868.
Meaning of “placeholder type”

10.1.7 [dcl.type] paragraph 2 describes the auto
specifier as “a placeholder for a type to be deduced.”
Elsewhere, the Standard refers to the type represented by the
auto specifier as a “placeholder type.” This
usage has been deemed confusing by some, requiring either a definition
of one or both terms or rewording to avoid them.

2053.
auto in non-generic lambdas

If the autotype-specifier appears as one of
the decl-specifiers in the decl-specifier-seq
of a parameter-declaration of
a lambda-expression, the lambda is a generic lambda
(8.1.5 [expr.prim.lambda]).

and 8.1.5 [expr.prim.lambda] paragraph 5 says,

For a generic lambda, the closure type has a public inline
function call operator member template
(17.6.2 [temp.mem])
whose template-parameter-list consists of one
invented type template-parameter for each occurrence
of auto in the lambda's parameter-declaration-clause,
in order of appearance.

However, an auto that signals a
trailing-return-type should be excluded from these
descriptions.

1485.
Out-of-class definition of member unscoped opaque enumeration

The scope in which the names of enumerators are entered for
a member unscoped opaque enumeration is not clear. According to
10.2 [dcl.enum] paragraph 10,

Each enum-name and each unscoped enumerator is declared in the
scope that immediately contains the enum-specifier.

In the case of a member opaque enumeration defined outside its
containing class, however, it is not clear whether the enumerator
names are declared in the class scope or in the lexical scope
containing the definition. Declaring them in the class scope would
be a violation of 12.2 [class.mem] paragraph 1:

The member-specification in a class definition declares the
full set of members of the class; no member can be added elsewhere.

Declaring the names in the lexical scope containing the
definition would be contrary to the example in
17.6.1.4 [temp.mem.enum] paragraph 1:

1636.
Bits required for negative enumerator values

For an enumeration whose underlying type is fixed, the values of the
enumeration are the values of the underlying type. Otherwise,
for an enumeration where emin is the smallest
enumerator and emax is the largest, the values of
the enumeration are the values in the range bmin to
bmax, defined as follows: Let K be 1 for a
two's complement representation and 0 for a one's complement or
sign-magnitude representation. bmax is the smallest
value greater than or equal to
max(|emin|-K,|emax|) and
equal to 2M-1, where M is a non-negative
integer. bmin is zero if emin is
non-negative and -(bmax+K) otherwise. The
size of the smallest bit-field large enough to hold all the values of
the enumeration type is max(M,1) if bmin is
zero and M+1 otherwise.

The result of these calculations is that the number of bits
required for

enum { N = -1, Z = 0 }

is 1, but the number required for

enum { N = -1 }

is 2. This is surprising. This could be fixed by changing
|emax| to emax.

1917.
decltype-qualified enumeration names

11.3 [dcl.meaning] paragraph 1 and 12 [class]
paragraph 11 prohibit decltype-qualified declarators and class names,
respectively. There is no such prohibition in 10.2 [dcl.enum]
for enumeration names. Presumably that is an oversight that should be
rectified.

2131.
Ambiguity with opaque-enum-declaration

is ambiguous: it could be either a simple-declaration
comprising the elaborated-type-specifierenum E
and no init-declarator-list, or it could be an
opaque-enum-declaration with an omitted enum-base
(both of which are ill-formed, for different reasons).

138.
Friend declaration name lookup

If a friend declaration in a non-local class first declares a
class or function the friend class or function is a member of the
innermost enclosing namespace... When looking for a prior declaration
of a class or a function declared as a friend, scopes outside
the innermost enclosing namespace scope are not considered.

It is not clear from this passage how to determine whether an entity
is "first declared" in a friend declaration. One question is
whether a using-declaration influences this determination.
For instance:

Part of the question involves determining the meaning of
the word "synonym" in
10.3.3 [namespace.udecl]
paragraph 1:

A using-declaration introduces a name into the declarative
region in which the using-declaration appears. That name
is a synonym for the name of some entity declared elsewhere.

Is "using ::foo;" the declaration of a function or not?

More generally, the question is how to describe the lookup of the
name in a friend declaration.

John Spicer:
When a declaration specifies an unqualified name, that
name is declared, not looked up. There is a mechanism in which that
declaration is linked to a prior declaration, but that mechanism is
not, in my opinion, via normal name lookup. So, the friend always
declares a member of the nearest namespace scope regardless of how
that name may or may not already be declared there.

Mike Miller:
6.4.1 [basic.lookup.unqual]
paragraph 7 says:

A name used in the definition of a class X outside of a
member function body or nested class definition shall be declared in
one of the following ways:... [Note: when looking for a
prior declaration of a class or function introduced by a friend
declaration, scopes outside of the innermost enclosing namespace scope
are not considered.]

The presence of this note certainly implies that this paragraph
describes the lookup of names in friend declarations.

John Spicer:
It most certainly does not. If that section described the friend
lookup it would yield the incorrect results for the friend declarations
of f and g below.
I don't know why that note is there, but it can't
be taken to mean that that is how the friend lookup is done.

If the friend declaration is not a reference to
::foo, there is a related but separate question: does the
friend declaration introduce a conflicting (albeit "invisible")
declaration into namespace A, or is it simply a reference
to an as-yet undeclared (and, in this instance, undeclarable)
A::foo? Another part of the example in
6.4.4 [basic.lookup.elab]
paragraph 3 is
related:

John Spicer:
You can't refer to something that has not yet been declared. The friend
is a declaration of Glob,
it just happens to declare it in a such a way that
its name cannot be used until it is redeclared.

(A somewhat similar question has been raised in connection with
issue 36. Consider:

namespace N {
struct S { };
}
using N::S;
struct S; // legal?

According to 12.1 [class.name] paragraph 2,

A declaration consisting solely of class-key identifier ;
is either a redeclaration of the name in the current scope or a
forward declaration of the identifier as a class name.

Should the elaborated type declaration in this example be
considered a redeclaration of N::S or an invalid
forward declaration of a different class?)

I strongly suspect, but don't have standardese to prove, that the friend
declaration in line B is ill-formed. Can someone show me the text that
allows or disallows line B?

Here's my reasoning: Writing "using" to pull the name into namespace N2
merely allows code in N2 to use the name in a call without qualification
(per 10.3.3 [namespace.udecl]).
But just as declaring a specialization must be done in the
namespace where the template really lives (hence line A is ill-formed), I
suspect that declaring a specialization as a friend must likewise be done
using the original namespace name, not obliquely through a "using". I see
nothing in 10.3.3 [namespace.udecl]
that would permit this use. Is there?

Andrey Tarasevich:
17.6.4 [temp.friend] paragraph 2 seems to get pretty close:
"A friend declaration that is not a
template declaration and in which the name of the friend is an unqualified
'template-id' shall refer to a specialization of a function template
declared in the nearest enclosing namespace scope".

Herb Sutter:
OK, thanks. Then the question in this is the word "declared" -- in
particular, we already know we cannot declare a specialization of a template
in any other namespace but the original one.

John Spicer:
This seems like a simple question, but it isn't.

First of all, I don't think the standard comments on this usage one way
or the other.

A similar example using a namespace qualified name is ill-formed based
on 11.3 [dcl.meaning] paragraph 1:

The proposed resolution (not yet approved) for
issue 138 is that the
friend declares a new
foo that conflicts with the using-declaration and results in an error.

Your example is different than this though because the presence of the
explicit argument list
means that this is not declaring a new f but is instead using a
previously declared f.

One reservation I have about allowing the example is the desire to have
consistent rules for all of the "declaration like" uses of template
functions. Issue 275 (in DR status) addresses the
issue of unqualified names in explicit instantiation and explicit
specialization declarations.
It requires that such declarations refer to templates from the namespace
containing the
explicit instantiation or explicit specialization. I believe this rule
is necessary for those directives but is not really required for friend
declarations -- but there is the consistency issue.

Notes from April 2003 meeting:

This is related to issue 138. John Spicer
is supposed to update his paper on this topic. This is a new case
not covered in that paper. We agreed that the B line should be
allowed.

In resolving dependent names, names from the following sources are
considered:

Declarations that are visible at the point of definition of the
template.

...

If this is to be interpreted as meaning that only the declarations
that are visible at the point of definition can be used in overload
resolution for dependent calls, the call g(0) is ill-formed.
If, however, it is the names, not the declarations, that are captured,
then presumably the second declaration of f should be
considered, making the call well-formed. There is implementation
divergence for this example.

The resolution of issue 1551 recently
clarified the requirements in similar cases
involving using-declarations:

The note added to 10.3.3 [namespace.udecl] paragraph 11
makes clear that the call g(0) is well-formed in this
example.

This outcome results in an unfortunate discrepancy between how default
arguments and overloaded functions are treated, even though default
arguments could conceptually be viewed as simply adding extra overloads for
the additional arguments.

Notes from the June, 2014 meeting:

CWG was unable to come to consensus regarding the desired outcome,
with an approximately equal split between desiring the first example
to be well-formed or ill-formed. It was noted that the resolution of
issue 1850 makes the corresponding case
for non-dependent references ill-formed, with no diagnostic required.
Similar questions also apply to completing an array type, which also
involves a modification to an existing entity declaration in a given
scope.

Notes from the February, 2016 meeting:

CWG determined that the case should be ill-formed, no diagnostic
required, to allow implementations to continue to use either
strategy.

1713.
Linkage of variable template specializations

should T<const int> have internal linkage by virtue
of its const-qualified type? Or should it inherit the linkage of the
template?

Notes from the February, 2014 meeting:

CWG noted that linkage is by name, and a specialization of a variable
template does not have a name separate from that of the variable
template, thus the specialization will have the linkage of the template.

1817.
Linkage specifications and nested scopes

Unless otherwise stated, utterances in Clause
10 [dcl.dcl] about components in, of, or contained
by a declaration or subcomponent thereof refer only to those
components of the declaration that are not nested within
scopes nested within the declaration.

This contradicts the intent of 10.5 [dcl.link]
paragraph 4, which says,

In a linkage-specification, the specified language
linkage applies to the function types of all function
declarators, function names with external linkage, and
variable names with external linkage declared within
the linkage-specification.

Also, one of the comments in the example in paragraph 4
is inconsistent with the intent:

The language linkage for the block-scope declaration of
f4 is presumably determined by the fact that it
appears in a C-linkage function, not by the previous
declaration.

Proposed resolution (February, 2014):

Change 10.5 [dcl.link] paragraph 4 as follows:

Linkage specifications nest. When linkage specifications nest, the
innermost one determines the language linkage. A linkage specification does
not establish a scope. A linkage-specification shall occur only in
namespace scope (6.3 [basic.scope]). In
a linkage-specification, the specified language linkage applies to
the function types of all function declarators, function names with
external linkage, and variable names with external linkage declared within
the linkage-specification, including those appearing in scopes
nested inside the linkage specification and not inside a nested
linkage-specification. [Example:

The issue has been returned to "drafting" status to clarify the
circumstances under which a preceding declaration supplies the
language linkage for a declaration (for example, not when the
declaration uses a typedef, which carries the language linkage,
but only when the declaration uses a function declarator).

CWG decided to change the pack expansion of alignas so that
the type-id or assignment-expression is repeated inside
the parentheses and to change the definition of alignas to
accept multiple arguments with the same meaning as multiple alignas
specifiers.

2223.
Multiple alignas specifiers

The alignment requirement of an entity is the strictest non-zero alignment
specified by its alignment-specifiers, if any; otherwise,
the alignment-specifiers have no effect.

It is not clear whether this applies to specifiers within a single
declaration, or if it is intended to apply to the union of all
declarations.

Similarly, paragraph 6 says,

If the defining declaration of an entity has an alignment-specifier,
any non-defining declaration of that entity shall either specify equivalent
alignment or have no alignment-specifier. Conversely, if any
declaration of an entity has an alignment-specifier, every defining
declaration of that entity shall specify an equivalent alignment. No
diagnostic is required if declarations of an entity have
different alignment-specifiers in different translation units.

This only talks about agreement between definitions and non-defining
declarations. What about an example where an entity is not defined but
is declared with different alignment-specifiers?

struct alignas(16) A;
struct alignas(32) A;

If A is not defined, is this, or should it be, ill-formed?

Notes from the February, 2017 meeting:

CWG agreed that the intent of the wording is that the
“strictest” requirement is intended to apply to a single
declaration, and the requirement for compatibility should apply to all
declarations, whether the entity is defined or not.

1488.
abstract-pack-declarators in type-ids

The grammar for type-id in 12.1 [class.name] paragraph
1 has two problems. First, the fact that we allow an
abstract-pack-declarator makes some uses of type-id
(template arguments, alignment specifiers, exception-specifications)
ambiguous: T... could be parsed either as a type-id,
including the ellipsis, or as the type-idT with a
following ellipsis. There does not appear to be any rule to
disambiguate these parses.

The other problem is that we do not allow parentheses in an
abstract-pack-declarator, which makes

template<typename...Ts> void f(Ts (&...)[4]);

ill-formed because (&...)() is not an
abstract-pack-declarator. There is implementation variance
on this point.

1900.
Do friend declarations count as “previous declarations”?

Issue 1477 assumes that a name
declared only in a friend declaration can be defined outside
its namespace using a qualified-id, but the normative
passages in 11.3 [dcl.meaning] paragraph 1 and
10.3.1.2 [namespace.memdef] paragraph 2 do not settle the question
definitively, and there is implementation variance. A clearer
statement of intent is needed.

453.
References may only bind to “valid” objects

A reference shall be initialized to refer to a valid object or
function. [Note: in particular, a null reference cannot exist
in a well-defined program, because the only way to create such
a reference would be to bind it to the "object" obtained by
dereferencing a null pointer, which causes undefined behavior
...]

What is a "valid" object? In particular the expression "valid object"
seems to exclude uninitialized objects, but the response to Core Issue
363 clearly says that's not the intent. This is an example
(overloading construction on constness of *this) by John Potter, which
I think is supposed to be legal C++ though it binds references to
objects that are not initialized yet:

Suggested resolution: Changing the final part of
11.3.2 [dcl.ref] paragraph 4 to:

A reference shall be initialized to refer to an object or function.
From its point of declaration on (see 6.3.2 [basic.scope.pdecl])
its name is an lvalue
which refers to that object or function. The reference may be
initialized to refer to an uninitialized object but, in that case,
it is usable in limited ways (6.8 [basic.life], paragraph 6)
[Note: On the other hand, a declaration like this:

int & ref = *(int*)0;

is ill-formed because ref will not refer to any object or function
]

I also think a "No diagnostic is required." would better be added
(what about something like int& r = r; ?)

Proposed Resolution (October, 2004):

(Note: the following wording depends on the proposed
resolution for issue 232.)

Change 11.3.2 [dcl.ref] paragraph 4 as follows:

A reference shall be initialized to refer to a valid object
or function.If an lvalue to which a reference is directly
bound designates neither an existing object or function of an
appropriate type (11.6.3 [dcl.init.ref]), nor a region of
memory of suitable size and alignment to contain an object of the
reference's type (4.5 [intro.object], 6.8 [basic.life], 6.9 [basic.types]), the behavior is
undefined. [Note: in particular, a null reference cannot
exist in a well-defined program, because the only way to create
such a reference would be to bind it to the
“object”empty lvalue obtained by
dereferencing a null pointer, which causes undefined behavior.
Asdoes not designate an object or function. Also, as
described in 12.2.4 [class.bit],
a reference cannot be bound directly to a
bit-field. ]

The name of a reference shall not be used in its own
initializer. Any other use of a reference before it is
initialized results in undefined behavior. [Example:

Rationale: The proposed wording goes beyond the specific
concerns of the issue. It was noted that, while the current
wording makes cases like int& r = r; ill-formed (because
r in the initializer does not "refer to a valid object"), an
inappropriate initialization can only be detected, if at all, at
runtime and thus "undefined behavior" is a more appropriate treatment.
Nevertheless, it was deemed desirable to continue to require a
diagnostic for obvious compile-time cases.

It was also noted that the current Standard does not say anything
about using a reference before it is initialized. It seemed
reasonable to address both of these concerns in the same wording
proposed to resolve this issue.

Notes from the April, 2005 meeting:

The CWG decided that whether to require an implementation to
diagnose initialization of a reference to itself should be handled as
a separate issue (504) and also suggested referring
to “storage” instead of “memory” (because
4.5 [intro.object] defines an object as a “region of
storage”).

Proposed Resolution (April, 2005):

(Note: the following wording depends on the proposed
resolution for issue 232.)

Change 11.3.2 [dcl.ref] paragraph 4 as follows:

A reference shall be initialized to refer to a valid object
or function.If an lvalue to which a reference is directly
bound designates neither an existing object or function of an
appropriate type (11.6.3 [dcl.init.ref]), nor a region of
storage of suitable size and alignment to contain an object of the
reference's type (4.5 [intro.object], 6.8 [basic.life], 6.9 [basic.types]), the behavior is
undefined. [Note: in particular, a null reference cannot
exist in a well-defined program, because the only way to create
such a reference would be to bind it to the
“object”empty lvalue obtained by
dereferencing a null pointer, which causes undefined behavior.
Asdoes not designate an object or function. Also, as
described in 12.2.4 [class.bit],
a reference cannot be bound directly to a
bit-field. ]

Any use of a reference before it is initialized results in
undefined behavior. [Example:

The word “use” in the last
paragraph of the proposed resolution was intended to refer to the
description in 6.2 [basic.def.odr] paragraph 2. However, that
section does not define what it means for a reference to be
“used,” dealing only with objects and functions. Additional
drafting is required to extend 6.2 [basic.def.odr] paragraph 2
to apply to references.

Additional note (May, 2008):

The proposed resolution for issue 570
adds wording to define “use” for references.

Note, January, 2012:

The resolution should also probably deal with the fact that
the “one-past-the-end” address of an array does not
designate a valid object (even if such a pointer might
“point to” an object of the correct type, per
6.9.2 [basic.compound]) and thus is not suuitable for the
lvalue-to-rvalue conversion.

1640.
Array of abstract instance of class template

According to 11.3.4 [dcl.array] paragraph 1, an array
declarator whose element type is an abstract class is ill-formed.
However, if the element type is a class template specialization, it
may not be known that the class is abstract; because forming an array
of an incomplete type is permitted (6.9 [basic.types] paragraphs
5-6), the class template is not required to be instantiated in order
to use it as an element type. The expected handling if the class
template is later instantiated is unclear; should the compiler issue
an error about the earlier array array type at the point at which the
class template is instantiated?

1001.
Parameter type adjustment in dependent parameter types

According to 11.3.5 [dcl.fct] paragraph 5,
top-level cv-qualifiers on parameter types are deleted when
determining the function type. It is not clear how or whether
this adjustment should be applied to parameters of function
templates when the parameter has a dependent type, however. For
example:

If the const in #1 is dropped, f<int> has
a parameter type of A* rather than the const A*
specified in the explicit instantiation. If the const in
#2 is not dropped, we fail to match the definition of
B::g to its declaration.

Rationale (November, 2010):

The CWG agreed that this behavior is intrinsic to the different
ways cv-qualification applies to array types and non-array types.

Notes, January, 2012:

Additional discussion of this issue arose regarding the following
example:

The question is whether the member function in
B<int> has the same type as that in
A<int>: is the parameter-type-list instantiated
directly (i.e., using the adjusted types) or regenerated from the
individual parameter types?

1668.
Parameter type determination still not clear enough

The type of a function is determined using the following rules. The type of
each parameter (including function parameter packs) is determined from its
own decl-specifier-seq and declarator. After determining the
type of each parameter, any parameter of type “array
of T” or “function returning T” is
adjusted to be “pointer to T” or “pointer to
function returning T,” respectively. After producing the
list of parameter types, any top-level cv-qualifiers modifying a
parameter type are deleted when forming the function type. The resulting
list of transformed parameter types and the presence or absence of the
ellipsis or a function parameter pack is the function's
parameter-type-list. [Note: This transformation does not
affect the types of the parameters. For example, int(*)(const int p,
decltype(p)*) and int(*)(int, const int*) are identical
types. —end note]

This is not sufficiently clear to specify the intended handling of an
example like

void f(int a[10], decltype(a) *p );

Should the type of p be int(*)[10]
or int**? The latter is the intended result, but the phrase
“after determining the type of each parameter” makes it
sound as if the adjustments are performed after all the parameter
types have been determined from the decl-specifier-seq and
declarator instead of for each parameter individually.

325.
When are default arguments parsed?

The standard is not precise enough about when the default arguments of
member functions are parsed. This leads to confusion over whether certain
constructs are legal or not, and the validity of certain compiler
implementation algorithms.

11.3.6 [dcl.fct.default] paragraph 5 says "names in the
expression are bound, and
the semantic constraints are checked, at the point where the default
argument expression appears"

However, further on at paragraph 9 in the same section there is an example,
where the salient parts are

which appears to contradict the former constraint. At the point the default
argument expression appears in the definition of X, X::b has not been
declared, so one would expect ::b to be bound. This of course appears to
violate 6.3.7 [basic.scope.class] paragraph 1(2) "A name N used in
a class S shall
refer to the same declaration in its context and when reevaluated in the
complete scope of S. No diagnostic is required."

Furthermore 6.3.7 [basic.scope.class] paragraph 1(1) gives the
scope of names declared
in class to "consist not only of the declarative region following
the name's declarator, but also of .. default arguments ...". Thus implying
that X::b is in scope in the default argument of X::mem2 previously.

That previous paragraph hints at an implementation technique of saving the
token stream of a default argument expression and parsing it at the end of
the class definition (much like the bodies of functions defined in the
class). This is a technique employed by GCC and, from its behaviour, in
the EDG front end. The standard leaves two things unspecified.
Firstly, is a default argument expression permitted to call a static member
function declared later in the class in such a way as to require evaluation of
that function's default arguments? I.e. is the following well formed?

become detected? Is it when B is complete? Is it when B::Foo or B::Baz is
called in such a way to require default argument expansion? Or is no
diagnostic required?

The other problem is with collecting the tokens that form the default
argument expression. Default arguments which contain template-ids with
more than one parameter present a difficulty in determining when the
default argument finishes. Consider,

The default argument contains a non-parenthesized comma. Is it required
that this comma is seen as part of the default argument expression and not
the beginning of another of argument declaration? To accept this as
part of the default argument would require name lookup of T (to determine
that the '<' was part of a template argument list and not a less-than
operator) before C is complete. Furthermore, the more pathological

would be very hard to accept. Even though T is declared after Foo, T is
in scope within Foo's default argument expression.

Suggested resolution:

Append the following text to 11.3.6 [dcl.fct.default] paragraph 8.

The default argument expression of a member function declared in
the class definition consists of the sequence of tokens up until
the next non-parenthesized, non-bracketed comma or close
parenthesis. Furthermore such default argument expressions shall
not require evaluation of a default argument of a function
declared later in the class.

This would make the above A, B, C and D ill formed and is in line with the
existing compiler practice that I am aware of.

Notes from the October, 2005 meeting:

The CWG agreed that the first example (A) is currently
well-formed and that it is not unreasonable to expect implementations
to handle it by processing default arguments recursively.

Additional notes, May, 2009:

Presumably the following is ill-formed:

int f(int = f());

However, it is not clear what in the Standard makes it so. Perhaps
there needs to be a statement to the effect that a default argument
only becomes usable after the complete declarator of which it is a
part.

Notes from the August, 2011 meeting:

In addition to default arguments, commas in template argument lists
also cause problems in initializers for nonstatic data members:

It was decided to handle the question of parsing an initializer
like T<a,b>(c) (a template-id or two
declarators) in this issue and the remaining questions in issue 361. For this issue, a template-id will
only be recognized if there is a preceding declaration of a template.

1962.
Type of __func__

Two questions have arisen regarding the treatment of the type of the
__func__ built-in variable. First, some implementations
accept

void f() {
typedef decltype(__func__) T;
T x = __func__;
}

even though T is specified to be an array type.

In a related question, it was noted that __func__
is implicitly required to be unique in each function, and that
not only the value but the type of __func__ are
implementation-defined; e.g., in something like

inline auto f() { return &__func__; }

the function type is implementation-specific. These concerns could be
addressed by making the value a prvalue of type const char*
instead of an array lvalue.

Notes from the May, 2015 meeting:

CWG agreed with the suggested direction.

2144.
Function/variable declaration ambiguity

is syntactically ambiguous. It could be either a
function-definition followed by an empty-declaration,
or it could be a simple-declaration whose
init-declarator has the brace-or-equal-initializer{}. The same is true of a variable declaration

int a {};

since function-definition simply uses the
term declarator in its production.

1733.
Return type and value for operator= with ref-qualifier

have the same declared function type (except for possibly
differing ref-qualifiers and except that in the case of a copy
constructor or copy assignment operator, the parameter type may be
“reference to non-const T”, where T is the
name of the member function's class) as if it had been implicitly
declared...

This allows an example like

struct A {
A& operator=(A const&) && = default;
};

but forbids

struct B {
B&& operator=(B const&) && = default;
};

which seems backward.

In addition, 15.8 [class.copy] paragraph 22 only specifies the
return value for implicitly-declared copy/move assignment operators,
not for explicitly-defaulted ones.

1854.
Disallowing use of implicitly-deleted functions

The resolution of issue 1778 means that
whether an explicitly-defaulted function is deleted or not cannot be
known until the end of the class definition. As a result, new rules
are required to disallow references (in, e.g., decltype) to
explicitly-defaulted functions that might later become deleted.

Notes from the June, 2014 meeting:

The approach favored by CWG was to make any reference to an
explicitly-defaulted function ill-formed if it occurs prior to the
end of the class definition.

According to 11.5 [dcl.struct.bind] paragraph 4, the type of
a is const int, since the implicitly-declared variable
is const. This seems obviously wrong: the member n is
mutable, so the member access expression e.n has
type int, which should also be the type
of a. (mutable should presumably be taken into account
when forming the referenced type too, so that decltype(a)
is int as would presumably be expected, rather than const
int.)

2339.
Underspecified template arguments in structured bindings

Otherwise, if
the qualified-idstd::tuple_size<E> names a
complete type, the
expression std::tuple_size<E>::value shall be a
well-formed integral constant expression and the number of
elements in the identifier-list shall be equal to the
value of that expression. The unqualified-idget
is looked up in the scope of E by class member access
lookup (6.4.5 [basic.lookup.classref]), and if that finds at least
one declaration, the initializer is e.get<i>().
Otherwise, the initializer is get<i>(e),
where get is looked up in the associated namespaces
(6.4.2 [basic.lookup.argdep]). In either
case, get<i> is interpreted as
a template-id.

It is not clear what i is in this description, and in
particular, its type is not specified.

Should the preceding initializsation of the buffer carry over to
the value of *ip? According to 11.6 [dcl.init]
paragraph 12,

When storage for an object with automatic or dynamic storage
duration is obtained, the object has an indeterminate value,
and if no initialization is performed for the object, that
object retains an indeterminate value until that value is
replaced (8.18 [expr.ass]).

In this case, no new storage is being obtained for the
int object created by the new-expression.

2327.
Copy elision for direct-initialization with a conversion function

Otherwise, if the initialization is direct-initialization, or if
it is copy-initialization where the cv-unqualified version of the
source type is the same class as, or a derived class of, the
class of the destination, constructors are considered. The
applicable constructors are enumerated
(16.3.1.3 [over.match.ctor]), and the best one is chosen
through overload resolution (16.3 [over.match]). The
constructor so selected is called to initialize the object, with
the initializer expression or expression-list as its
argument(s). If no constructor applies, or the overload
resolution is ambiguous, the initialization is ill-formed.

Overload resolution selects the move constructor of Cat.
Initializing the Cat&& parameter of the constructor
results in a temporary, per 11.6.3 [dcl.init.ref] bullet
5.2.1.2. This precludes the possitiblity of copy elision for this
case.

This seems to be an oversight in the wording change for
guaranteed copy elision. We should presumably be simultaneously
considering both constructors and conversion functions in this
case, as we would for copy-initialization, but we'll need to make
sure that doesn't introduce any novel problems or ambiguities.

The Standard does not specify whether the initialization from
{} that is done for omitted initializers in aggregate
initialization is direct or copy initialization. There is divergence
among implementations.

The rule is intended to apply only if an actual
initialization results in such a binding, but it could be
read as applying to the declaration of A::v itself.
It would be clearer if the restriction were moved into
bullet 9.1, e.g.,

if the entity is a non-static data member that has
a brace-or-equal-initializer and either

the constructor's class is a union
(12.3 [class.union]), and no other variant member of
that union is designated by a mem-initializer-id or

the constructor's class is not a union, and, if the entity
is a member of an anonymous union, no other member of that
union is designated by a mem-initializer-id,

the entity is initialized as specified in
11.6 [dcl.init], and the program is ill-formed
if the entity is a reference member and this initialization
binds it to a temporary;

1414.
Binding an rvalue reference to a reference-unrelated lvalue

Currently an attempt to bind an rvalue reference to a
reference-unrelated lvalue succeeds, binding the reference to a
temporary initialized from the lvalue by copy-initialization. This
appears to be intentional, as the accompanying example contains the
lines

This violates the expectations of some who expect that rvalue
references can be initialized only with rvalues. On the other
hand, it is parallel with the handling of an lvalue
reference-to-const (and is handled by the same wording). It also
can add efficiency without requiring existing code to be rewritten:
the implicitly-created temporary can be moved from, just as if the
call had been rewritten to create a prvalue temporary from the
lvalue explicitly.

On a related note, assuming the binding is permitted, the intent of
the overload tiebreaker found in 16.3.3.2 [over.ics.rank]
paragraph 3 is not clear:

S1 and S2 are reference bindings
(11.6.3 [dcl.init.ref]) and neither refers to an implicit
object parameter of a non-static member function declared without
a ref-qualifier, and S1 binds an rvalue reference
to an rvalue and S2 binds an lvalue reference.

At question is what “to an rvalue” means here. If it
is referring to the value category of the initializer itself,
before conversions, then the supposed performance advantage of
the binding under discussion does not occur because the competing
rvalue and lvalue reference overloads will be ambiguous:

On the other hand, if “to an rvalue” refers to the
actual object to which the reference is bound, i.e., to the temporary
in the case under discussion, the phrase would seem to be vacuous because
an rvalue reference can never bind directly to an lvalue.

Notes from the February, 2012 meeting:

CWG agreed that the binding rules are correct, allowing creation of
a temporary when binding an rvalue reference to a non-reference-related
lvalue. The phrase “to an rvalue” in
16.3.3.2 [over.ics.rank] paragraph 3 is a leftover from before
binding an rvalue reference to an lvalue was prohibited and should be
removed. A change is also needed to handle the following case:

Removing “to an rvalue,” as suggested, would have the
effect of negating the preference for binding a function lvalue to an
lvalue reference instead of an rvalue reference because the case would
now fall under the preceding bullet of 16.3.3.2 [over.ics.rank]
paragraph 3 bullet 1, sub-bullets 4 and 5:

Two implicit conversion sequences of the same form are
indistinguishable conversion sequences unless one of the following
rules applies:

S1 and S2 are reference bindings
(11.6.3 [dcl.init.ref]) and neither refers to an implicit object
parameter of a non-static member function declared without a
ref-qualifier, and S1 binds an rvalue reference to an
rvalue and S2 binds an lvalue reference... or, if not that,

S1 and S2 are reference bindings
(11.6.3 [dcl.init.ref]) and S1 binds an lvalue reference
to a function lvalue and S2 binds an rvalue reference to a
function lvalue.

Presumably if the suggested resolution is adopted, the order of these
two bullets should be inverted.

1996.
Reference list-initialization ignores conversion functions

The specification for list-initialization of a reference does not
consider the existence of conversion functions. Consequently, the
following example is ill-formed:

struct S { operator struct D &(); } s;
D &d{s};

2293.
Requirements for simple-template-id used as a class-name

Section: 12 [class]
Status: drafting
Submitter: CWG
Date: 2016-06-22

There is currently no requirement that a simple-template-id
used as a class-name (12 [class] paragraph 1) must
have template arguments for every template parameter that does not have
a default template argument.

1803.
opaque-enum-declaration as member-declaration

A member shall not be declared twice in
the member-specification, except that a nested class
or member class template can be declared and then later
defined, and except that an enumeration can be introduced
with an opaque-enum-declaration and later redeclared
with an enum-specifier.

However, the grammar for member-declaration does not
have a production that allows an opaque-enum-declaration.

There is no such restriction on member functions, and there is
no rationale for this difference, given that both static data members
and member functions can be defined outside a unnamed class with a
typedef name for linkage purposes. (Issue 406
acknowledged the lack of rationale by removing the specious note in
12.2.3.2 [class.static.data] that attempted to explain the restriction
but left the normative prohibition in place.)

It would be more consistent to remove the restriction for classes
with a typedef name for linkage purposes.

Additional note (August, 2012):

It was observed that, since no definition of a const
static data member is required if it is not odr-used, there is no
reason to prohibit such members in an unnamed class even without a
typedef name for linkage purposes.

The member shall still be defined in a namespace scope if it is odr-used
(6.2 [basic.def.odr]) in the program and the namespace scope
definition shall not contain an initializer.

The word “shall” implies a required diagnostic, but this
is describing an ODR violation (the static data member might be defined
in a different translation unit) and thus should be “no diagnostic
required.”

1404.
Object reallocation in unions

[Note: In general, one must use explicit destructor
calls and placement new operators to change the active member of
a union. —end note] [Example: Consider an
object u of a union type U having non-static
data members m of type M and n of type
N. If M has a non-trivial destructor and
N has a non-trivial constructor (for instance, if they
declare or inherit virtual functions), the active member of
u can be safely switched from m to n
using the destructor and placement new operator as follows:

u.m.~M();
new (&u.n) N;

—end example]

This pattern is only “safe” if the original object
that is being destroyed does not involve any const-qualified or
reference types, i.e., satisfies the requirements of 6.8 [basic.life]
paragraph 7, bullet 3:

the type of the original object is not
const-qualified, and, if a class type, does not contain any
non-static data member whose type is const-qualified or a
reference type

Although paragraph 4 of 12.3 [class.union] is a note and an
example, it should at least refer to the lifetime issues described
in 6.8 [basic.life].

Additional note (October, 2013):

See also issue 1776, which suggests
possibly changing the restriction in 6.8 [basic.life]. If
such a change is made, this issue may become moot.

is called an anonymous union; it defines an unnamed object of unnamed type.

It is obviously intended that a declaration like

static union { int i; float f; };

is a declaration of that form (cf paragraph 6, which requires the
static keyword for anonymous unions declared in namespace
scope). However, it would be clearer if the definition were recast
in more descriptive terms, e.g.,

An anonymous union is an unnamed class that is defined with
the class-keyunion in a simple-declaration in
which the init-declarator-list is omitted. Such a
simple-declaration is treated as if it contained a single
declarator declaring an unnamed variable of the union's type.

(Note that this definition would require some additional tweaking to
apply to class member anonymous union declarations, since
simple-declarations are not included
as member-declarations.)

As a related point, it is not clear how the following examples
are to be treated, and there is implementation variance on some:

The empty anonymous union appears to be a violation of the
requirement in 12.2 [class.mem] paragraph 1,

Except when used to declare friends
(14.3 [class.friend]), to declare an unnamed bit-field
(12.2.4 [class.bit]), or to introduce the name of a
member of a base class into a derived class
(10.3.3 [namespace.udecl]), or when the declaration is
an empty-declaration, member-declarations
declare members of the class, and each
such member-declaration shall declare at least one
member name of the class.

The reason for this discrepancy is that the naming class in
the reference to I is different in these cases. According
to 14.2 [class.access.base] paragraph 5,

The access to a member is affected by the class in which the member is
named. This naming class is the class in which the member name was
looked up and found.

In the case of i1, the reference to I is subject
to the transformation described in 12.2.2 [class.mfct.non-static]
paragraph 3:

Similarly during name lookup, when an unqualified-id
(8.1 [expr.prim]) used in the definition of a member function
for class X resolves to a static member, an
enumerator or a nested type of class X or of a base class of X, the
unqualified-id is transformed into a
qualified-id (8.1 [expr.prim]) in which the
nested-name-specifier names the class of the member function.

As a result, the reference to I in the declaration of
i1 is transformed to C::I, so that the naming class
is C, and I is inacessible in C. In the
remaining cases, however, the transformation does not apply. Thus,
the naming class of I in these references is A, and
I is publicly accessible in A.

Presumably either the definition of “naming class”
must be changed or the transformation of unqualified-ids must
be broadened to include all uses within the scope of a class and not
just within nonstatic member functions (and following the
declarator-id in the definition of a static member, per
12.2.3 [class.static] paragraph 4).

1699.
Does befriending a class befriend its friends?

Declaring a class to be a friend implies that the names of private and
protected members from the class granting friendship can be accessed in
the base-specifiers and member declarations of the befriended class.

A friend declaration is a member-declaration, but it
is not clear how far the granting of friendship goes in a friend
declaration. For example:

In particular, if a friend function is defined inside the class
definition, as in #3, does its definition have access to the private
and protected members of the befriending class? Implementations vary
on this point.

I think the rationale for the 14.4 [class.protected]
restriction applies equally well here — you don't know whether
ip points to a D object or not, so D::f can't be trusted to treat
the protected B subobject consistently with the policies of its
actual complete object type.

The current treatment of “accessible base class”
in 14.2 [class.access.base] paragraph 4
clearly makes the conversion from I* to B* well-formed. I
think that's wrong and needs to be fixed. The rationale for
the accessibility of a base class is whether “an invented
public member” of the base would be accessible at the point of
reference, although we obscured that a bit in the
reformulation; it seems to me that the invented member ought to
be considered a non-static member for this purpose and thus
subject to 14.4 [class.protected].

The CWG tentatively agreed that casting across protective
inheritance should be subject to the additional restriction in
14.4 [class.protected].

Proposed resolution (April, 2011)

Change 14.2 [class.access.base] paragraph 4 as follows:

A base class B of N is accessible at R, if

an invented public member of B would be a public
member of N, or

R occurs in a member or friend of class N, and
an invented public member of B would be a private or
protected member of N, or

R occurs in a member or friend of a class P
derived from N, and an invented public member of B
would be a private or(but not a protected
[Footnote: A protected invented member is disallowed here
for the same reason the additional check of 14.4 [class.protected]
is applied to member access: it would allow casting a pointer to a
derived class to a protected base class that might be a subobject of
an object of a class that is different from the class context in which
the reference occurs. —end footnote]) member of
P, or

there exists a class S such that B is a base
class of S accessible at R and S is a base
class of N accessible at R.

1360.
constexpr defaulted default constructors

According to 15.1 [class.ctor] paragraph 6, a defaulted
default constructor is constexpr if the corresponding
user-written constructor would satisfy the constexpr
requirements. However, the requirements apply to the definition of
a constructor, and a defaulted constructor is defined only if it is
odr-used, leaving it indeterminate at declaration time whether the
defaulted constructor is constexpr or not.

You can't determine the value of the initializer, and thus whether the
initializer is a constant expression, until the class is complete, but you
can't complete the class without declaring the default constructor, and
whether that constructor is constexpr or not depends on whether
the member initializer is a constant expression.

This introduces an order dependency that is not specified in the
current text: determining whether the default constructor of A
is constexpr requires first determining the characteristics of
the initializer of B::x and whether B::B() is
constexpr or not.

The problem is exacerbated with class templates, since the current
direction of CWG is to instantiate member initializers only when they
are needed (see issue 1396). For a specific
example:

This also affects determining whether a class template specialization
is a literal type or not; presumably getting the right answer to that
requires instantiating the class and all its nonstatic data member
initializers.

any potentially constructed subobject has a type with a destructor
that is deleted or inaccessible from the defaulted default
constructor.

An implicitly-declared default constructor is constexpr
if:

X has no virtual bases; and

for each non-variant non-static data member or base class
subobject M, either M is initialized via
brace-or-equal-initializer or default-initialization of
M uses a constexpr constructor; and

if X is a union having variant members, or, if
X is a non-union-class, for each anonymous union member having
variant members, exactly one non-static data member is initialized via
brace-or-equal-initializer.

A default constructor is trivial if it is not user-provided and if:

...

for all the non-static data members of its class that are of class
type (or array thereof), each such class has a trivial default
constructor.

Otherwise, the default constructor is non-trivial.

A default constructor that is defaulted and not defined as deleted is
implicitly defined when it is odr-used (6.2 [basic.def.odr]) to
create an object of its class type (4.5 [intro.object]) or when it is
explicitly defaulted after its first declaration. The implicitly-defined
default constructor performs the set of initializations of the class that
would be performed by a user-written default constructor for that class
with no ctor-initializer (15.6.2 [class.base.init]) and an
empty compound-statement. If that user-written default constructor
would be ill-formed, the program is ill-formed. If that user-written
default constructor would satisfy the requirements of a constexpr
constructor (10.1.5 [dcl.constexpr]), the implicitly-defined default
constructor is constexpr. Before the defaulted default
constructor for a class is implicitly defined, all the non-user-provided
default constructors for its base classes and its non-static data members
shall have been implicitly defined. [Note:...

Additional notes, May, 2014:

The proposed resolution inadvertently allows a defaulted default
constructor of a class with virtual bases to be constexpr.
It has been updated with a change addressing that oversight and
returned to "review" status.

1623.
Deleted default union constructor and member initializers

X is a union-like class that has a variant member with
a non-trivial default constructor,

...

X is a union and all of its variant members are of
const-qualified type (or array thereof),

X is a non-union class and all members of any anonymous
union member are of const-qualified type (or array thereof),

...

Because the presence of a non-static data member initializer is the
moral equivalent of a mem-initializer, these rules should
probably be modified not to define the generated constructor as
deleted when a union member has a non-static data member initializer.
(Note the non-normative references in 12.3 [class.union]
paragraphs 2-3 and 10.1.7.1 [dcl.type.cv] paragraph 2 that
would also need to be updated if this restriction is changed.)

It would also be helpful to add a requirement to 12.3 [class.union]
requiring either a non-static data member initializer or a user-provided
constructor if all the members of the union have const-qualified types.

On a more general note, why is the default constructor defined as
deleted just because a member has a non-trivial default constructor? The
union itself doesn't know which member is the active one, and default
construction won't initialize any members (assuming
no brace-or-equal-initializer). It is up to the “owner”
of the union to control the lifetime of the active member (if any), and
requiring a user-provided constructor is forcing a design pattern that
doesn't make sense. Along the same lines, why is the default destructor
defined as deleted just because a member has a non-trivial destructor? I
would agree with this restriction if it only applied when the union also
has a user-provided constructor.

According to 11.6.4 [dcl.init.list] paragraph 3, A
will be value-initialized if it has a default constructor, and
there is implementation divergence whether this example calls #1
or #2.

Similarly, for an example like

struct B {
template<typename T=int> B(T = 0);
};

it is not completely clear whether a default constructor should
be implicitly declared or not.

More generally, do utterances in the Standard concerning
“constructors” also apply to constructor templates?

Notes from the February, 2014 meeting:

One possibility discussed was that we may need to change places that
explicitly refer to a default constructor to use overload resolution,
similar to the change that was made a few years ago with regard to copy
construction vs “copy constructor.” One additional use of
“default constructor” is in determining the triviality of a
class, but it might be a good idea to remove the concept of a trivial
class altogether. This possibility will be explored.

Notes from the February, 2016 meeting:

CWG reaffirmed the direction from the preceding note and also
determined that the presence of a constructor template should suppress
implicit declaration of a default constructor.

1651.
Lifetime extension of temporary via reference to subobject

The resolution of issues 616 and
1213, making the result of a member access or
subscript expression applied to a prvalue an xvalue, means that binding a
reference to such a subobject of a temporary does not extend the
temporary's lifetime. 15.2 [class.temporary] should be revised to ensure
that it does.

The copy to t in g is not elided. X(const
X&) is called, then ~S() is called, then f() is
called.

The copy to t in g is elided, so the temporary
and t are the same object. Thus, the S object's lifetime
is extended to the lifetime of the reference t.s, so
first f() is called, then ~S() is called (and X(const
X&) is not called).

However, EDG and g++ produce a third behavior: they do not call
X(const X&), but they destroy the S() temporary at
the end of its full-expression. The current wording does not appear to
permit this behavior, but it seems preferable that lifetime extension does
not depend on whether copy elision is done.

When parsing the template definition, what checks can be done on "~B"?

Sandor Mathe adds
:

The standard correction for issue 244
(now in DR status) is still incomplete.

Paragraph 5 of 6.4.3 [basic.lookup.qual] is
not applicable for p->T::~T since there is no nested-name-specifier.
Section 6.4.5 [basic.lookup.classref]
describes the lookup of p->~T but p->T::~T is still not
described. There are examples (which are non-normative) that illustrate
this sort of lookup but they still leave questions unanswered. The
examples imply that the name after ~ should be looked up in the same
scope as the name before the :: but it is not stated. The problem is
that the name to the left of the :: can be found in two
different scopes. Consider the following:

Should the destructor call be valid? If there were a nested name
specifier, then D should be looked for in the same scope as C. But
here, C is looked for in 2 different ways. First, it is searched for in
the type of the left hand side of -> and it is also looked for in the
lexical context. It is found in one or if both, they must match. So, C
is found in the scope of what p points at. Do you only look for D there?
If so, this is invalid. If not, you would then look for D in the context
of the expression and find it. They refer to the same underlying
destructor so this is valid. The intended resolution of the original
defect report of the standard was that the name before the :: did not
imply a scope and you did not look for D inside of C. However, it was
not made clear whether this was to be resolved by using the same lookup
mechanism or by introducing a new form of lookup which is to look in the
left hand side if that is where C was found, or in the context of the
expression if that is where C was found. Of course, this begs the
question of what should happen when it is found in both? Consider
the modification to the above case when C is also found in the context
of the expression. If you only look where you found C, is this now
valid because it is in 1 of the two scopes or is it invalid because C
was in both and D is only in 1?

I agree that the intention of the committee is that the original test
case in this defect is broken. The standard committee clearly thinks
that the last name before the last :: does not induce a new scope which
is our current interpretation. However, how this is supposed to work
is not defined. This needs clarification of the standard.

Martin Sebor adds this example (September 2003), along
with errors produced by the EDG front end:

John Spicer:
The issue here is that we're unhappy with the destructor names when doing
semantic analysis of the template definitions (not during an
instantiation).

My personal feeling is that this is reasonable. After all, why
would you call p->~NB for a class that you just named
as N::B<T> and you could just say p->~B?

Additional note (September, 2004)

The resolution for issue 244 removed
the discussion of p->N::~S, where N is a
namespace-name. However, the resolution did not make this
construct ill-formed; it simply left the semantics undefined.
The meaning should either be defined or the construct made
ill-formed.

1977.
Contradictory results of failed destructor lookup

At the point of definition of a virtual destructor (including an implicit
definition (15.8 [class.copy])), the non-array deallocation
function is looked up in the scope of the destructor's class
(13.2 [class.member.lookup]), and, if no declaration is found, the function
is looked up in the global scope. If the result of this lookup is ambiguous
or inaccessible, or if the lookup selects a placement deallocation function
or a function with a deleted definition (11.4 [dcl.fct.def]), the
program is ill-formed. [Note: This assures that a deallocation
function corresponding to the dynamic type of an object is available for
the delete-expression (15.5 [class.free]). —end
note]

However, bullet 5.3 of that section says that such a lookup failure
causes the destructor to be defined as deleted, rather than making the
program ill-formed. It appears that paragraph 12 was overlooked when
deleted functions were added to the language. See also
15.5 [class.free] paragraph 7.

Should this have defined behavior? On the one hand, the
Derived object is in its period of destruction, so
the behavior of the p->f() call in
the Base destructor should be to
call Base::f(). On the other hand, p is a
pointer to a Derived object whose lifetime has
ended, and the rules in 6.8 [basic.life] don't
appear to allow the call. (Calling this->f()
from the Base destructor would be OK — the
question is whether you can do that for a pointer that used
to point to the derived object, or if you can only do it for
a pointer that was “created” after the dynamic
type of the object changed to be Base.)

If the above is valid, it has severe implications for
devirtualization. The purpose of 6.8 [basic.life]
paragraph 7 appears to be to allow an implementation to
assume that if it will perform two loads of a constant field
(for instance, a const member, the implicit pointer for a
reference member, or a vptr), and the two loads are
performed on the “same pointer value”, then
they load the same value.

Should there be a rule for destructors similar to that
of 15.1 [class.ctor] paragraph 12?

During the construction of a const object, if the value of
the object or any of its subobjects is accessed through a
glvalue that is not obtained, directly or indirectly, from
the constructor's this pointer, the value of the object or
subobject thus obtained is unspecified.

255.
Placement deallocation functions and lookup ambiguity

Paragraph 4 of 15.5 [class.free] speaks of looking up a
deallocation function. While it is an error if a placement
deallocation function alone is found by this lookup, there seems to be
an assumption that a placement deallocation function and a usual
deallocation function can both be declared in a given class scope
without creating an ambiguity. The normal mechanism by which
ambiguity is avoided when functions of the same name are declared in
the same scope is overload resolution; however, there is no mention of
overload resolution in the description of the lookup. In fact, there
appears to be nothing in the current wording that handles this case.
That is, the following example appears to be ill-formed, according to
the current wording:

I think you might get the right effect by replacing
the last sentence of 15.5 [class.free] paragraph 4
with something like:

After removing all placement deallocation functions,
the result of the lookup shall contain an unambiguous
and accessible deallocation function.

Additional notes (October, 2012):

This issue should be reconsidered in list of paper N3396, as it would
add additional overloads for allocation and deallocation functions.

The term “usual deallocation function” is defined in
6.7.4.2 [basic.stc.dynamic.deallocation] paragraph 2; perhaps it could be used to
good effect in 8.3.5 [expr.delete] paragraph 7. The specifications
in 15.5 [class.free] paragraphs 4 and 5 should probably also be
moved into 8.3.5 [expr.delete].

Does an anonymous union have a constructor that applies a non-static
data member initializer? Or is the initialization performed by the
constructor of the class in which the anonymous union appears? In
particular, is the reference to x in the initializer for
y well-formed or not? If the initialization of y
is performed by B's constructor, there is no problem because
B::x is a member of the object being initialized. If an anonymous
union has its own constructor, B::x is just a member of the
containing class and is a reference to a non-static data member without an
object, which is ill-formed. Implementations currently appear to take the
latter interpretation and report an error for that initializer.

As a further example, consider:

union { // #1
union { // #2
union { // #3
int y = 32;
};
};
} a { } ;

One interpretation might be that union #3 has a non-trivial default
constructor because of the initializer of y, which would give
union #2 a deleted default constructor, which would make the example
ill-formed.

2056.
Member function calls in partially-initialized class objects

Member functions (including virtual member functions,
13.3 [class.virtual]) can be called for an object under
construction. Similarly, an object under construction can
be the operand of the typeid operator
(8.2.8 [expr.typeid]) or of a dynamic_cast
(8.2.7 [expr.dynamic.cast]). However, if these operations
are performed in a ctor-initializer (or in a function
called directly or indirectly from
a ctor-initializer) before all
the mem-initializers for base classes have completed,
the result of the operation is undefined.

The current wording of 15.7 [class.cdtor] paragraph 4 does
not describe the behavior of calling a virtual function in a
mem-initializer for a base class, only for a non-static data
member. Also, the changes for issue 1202
should have been, but were not, applied to the description of the
behavior of typeid and dynamic_cast in paragraphs 5
and 6.

In addition, the resolution of issue 597
allowing the out-of-lifetime conversion of pointers/lvalues to
non-virtual base classes, should have been, but were not, applied to
paragraph 3.

For an object with a non-trivial constructor, referring to any
non-static member or virtual base class of the object
before the constructor begins execution results in undefined behavior.
For an object with a non-trivial destructor, referring to any
non-static member or virtual base class of the object after
the destructor finishes execution results in undefined
behavior. [Example:

To explicitly or implicitly convert a pointer (a glvalue) referring to
an object of class X to a pointer (reference) to a direct or
indirect virtual base class B of X, the
construction of X and the construction of all of its direct or
indirect bases that directly or indirectly derive fromfor whichBis a direct or indirect virtual
base shall have started and the destruction of these classes
shall not have completed, otherwise the conversion results in
undefined behavior. To form a pointer to (or access the value of) a
direct non-static member...

Member functions, including virtual functions
(13.3 [class.virtual]), can be called during construction or
destruction (15.6.2 [class.base.init]). When a virtual function is
called directly or indirectly from a constructor or from a destructor,
including during the construction or destruction of the class's non-static
data members, and the object to which the call applies is the object (call
it x) under construction or destruction, the function called is
the final overrider in the constructor's or destructor's class and not one
overriding it in a more-derived class. If the virtual function call uses
an explicit class member access (8.2.5 [expr.ref]) and the object
expression refers to the complete object of x or one of that object's base
class subobjects but not to x or one of its base class subobjects,
the behavior is undefined.The period of construction of an object or subobject whose type
is a class type C begins immediately after the construction of all
its base class subobjects is complete and concludes when the last
constructor of class C exits. The period of destruction of
an object or subobject whose type is a class type C begins when
the destructor for C begins execution and concludes immediately
before beginning the destruction of its base class
subobjects. A polymorphic operation is a virtual function call
(8.2.2 [expr.call]), the typeid operator
(8.2.8 [expr.typeid]) when applied to a glvalue of polymorphic type,
or the dynamic_cast operator (8.2.7 [expr.dynamic.cast]) when
applied to a pointer to or glvalue of a polymorphic type. A polymorphic
operand is the object expression in a virtual function call or the
operand of a polymorphic typeid
or dynamic_cast.

During the period of construction or period of destruction of
an object or subobject whose type is a class type C (call
it x), the effect of performing a polymorphic operation in
which the polymorphic operand designates x or a base class
subobject thereof is as if the dynamic type of the object were
class C. [Footnote: This is true even if C
is an abstract class, which cannot be the type of a most-derived
object. —end footnote] If a polymorphic operand refers to
an object or subobject having class type C before its period
of construction begins or after its period of destruction is complete,
the behavior is undefined. [Note: This includes the evaluation
of an expression appearing in a mem-initializer of C
in which the mem-initializer-id designates C or one of
its base classes. —end note] [Example:

The typeid operator (8.2.8 [expr.typeid]) can be
used during construction or destruction
(15.6.2 [class.base.init]). When typeid is used in a
constructor (including the mem-initializer or
brace-or-equal-initializer for a non-static data member) or in a
destructor, or used in a function called (directly or indirectly) from a
constructor or destructor, if the operand of typeid refers to the
object under construction or destruction,
typeid yields the std::type_info object representing
the constructor or destructor's class. If the operand of
typeid refers to the object under construction or destruction
and the static type of the operand is neither the constructor or
destructor's class nor one of its bases, the result of typeid
is undefined.

dynamic_casts (8.2.7 [expr.dynamic.cast]) can be used
during construction or destruction (15.6.2 [class.base.init]). When
a dynamic_cast is used in a constructor (including
the mem-initializer or brace-or-equal-initializer for a
non-static data member) or in a destructor, or used in a function called
(directly or indirectly) from a constructor or destructor, if the operand
of the dynamic_cast refers to the object under construction or
destruction, this object is considered to be a most derived object that has
the type of the constructor or destructor's class. If the operand of
the dynamic_cast refers to the object under construction or
destruction and the static type of the operand is not a pointer to or
object of the constructor or destructor's own class or one of its bases,
the dynamic_cast results in undefined behavior.
[Example:

If declaring the copy constructor for
A<D<E>> is part of instantiating the
class, then we need to do overload resolution on
D<E>, and thus C<B<E>>.
We consider C(const B<E>&), and therefore
look to see if there's a conversion from
C<B<E>> to B<E>, which
instantiates B<E>, which fails because it has
a field of type A<D<E>> which is
already being instantiated.

Even if we wait until A<D<E>> is
considered complete before finalizing the copy constructor
declaration, declaring the copy constructor for
B<E> will want to look at the copy
constructor for A<D<E>>, so we still
have the cycle.

I think that to avoid this cycle we need to short-circuit
consideration of C(const T&) somehow. But I
don't see how we can do that without breaking

Here, since G's move constructor suppresses the
implicit copy constructor, the defaulted H copy
constructor calls G(const G2&) instead. If the
move constructor did not suppress the implicit copy
constructor, I believe the implicit copy constructor would
always be viable, and therefore a better match than a
constructor taking a reference to another type.

So perhaps the answer is to reconsider that suppression
and then disqualify any constructor taking (a reference to)
a type other than the constructor's class from consideration
when looking up a subobject constructor in an implicitly
defined constructor. (Or assignment operator,
presumably.)

Another possibility would be that when we're looking for
a conversion from C<B<E>> to
B<E> we could somehow avoid considering, or
even declaring, the B<E> copy constructor.
But that seems a bit dodgy.

Additional note (October, 2010):

An explicitly declared move constructor/op= should not suppress the
implicitly declared copy constructor/op=; it should cause it to be
deleted instead. This should prevent a member function taking a
(reference to) an un-reference-related type from being chosen by
overload resolution in a defaulted member function.

And we should clarify that member functions taking
un-reference-related types are not even considered during overload
resolution in a defaulted member function, to avoid requiring their
parameter types to be complete.

1499.
Missing case for deleted move assignment operator

Bullet 4 of 15.8 [class.copy] paragraph 23 says that a
defaulted copy/move assignment operator is defined as deleted if the class
has

a non-static data member of class type M (or array thereof) that
cannot be copied/moved because overload resolution (16.3 [over.match]), as applied to M's corresponding assignment operator,
results in an ambiguity or a function that is deleted or inaccessible
from the defaulted assignment operator

The intent of this is that if overload resolution fails to find a
corresponding copy/move assignment operator that can validly be called
to copy/move a member, the class's assignment operator will be defined
as deleted. However, this wording does not cover an example like the
following:

Here, the problem is simply that overload resolution failed to find
a callable function, which is not one of the cases listed in the current
wording. A similar problem exists for base classes in the fifth bullet.

Additional note (January, 2013):

A similar omission exists in paragraph 11 for copy constructors.

1548.
Copy/move construction and conversion functions

The current wording of 15.8 [class.copy] paragraph 31
refers only to constructors and destructors:

When certain criteria are met, an implementation is allowed to omit
the copy/move construction of a class object, even if the constructor
selected for the copy/move operation and/or the destructor for the
object have side effects.

However, in some cases (e.g., auto_ptr) a conversion function
is also involved in the copying, and it could presumably also have visible
side effects that would be eliminated by copy elision. (Some additional
contexts that may also require changes in this regard are mentioned in the
resolution of issue 535.)

Additional note (September, 2012):

The default arguments of an elided constructor can also have side
effects and should be mentioned, as well; however, the elision should
not change the odr-use status of functions and variables appearing in
those default arguments.

1590.
Bypassing non-copy/move constructor copying

Copy initialization in some cases uses constructors that are not
copy/move constructors (e.g., a specialization of a constructor
template might be selected by overload resolution, or in
copy-list-initialization, any constructor could be selected). Some
ABIs require that an object of certain class types be passed in a
register (effectively using the trivial copy/move constructor), even
if the class has a non-trivial constructor that would be selected to
do the copy. The Standard should be changed to permit this usage.

Proposed resolution (April, 2013):

Add the following as a new paragraph following 15.8 [class.copy]
paragraph 1:

When an object of class type X is passed to or returned from
a function, if X has a trivial, accessible copy or move
constructor that is not deleted, and X has no non-trivial copy
constructors, move constructors, or destructors, implementations are
permitted to perform an additional copy or move of the object using the
trivial constructor (even if it would not be selected by overload
resolution to perform a copy or move of the object). [Note: This
latitude is granted to allow objects of class type to be passed to or
returned from functions in registers. —end note]

Questions have been raised regarding this resolution. In
particular, the interaction of the “extra copy” with copy
elision, lifetime, and access checking context are not specified. In
addition, some concern has also been expressed regarding the requirement
that the trivial copy/move constructor be accessible. The issue is being
returned to "review" status for discussion of these points.

Notes from the June, 2014 meeting:

CWG felt that the requirements for accessibility should be
removed, in line with the idea making all access public
in a program should not change its semantics. Similarly, the
prohibition of non-trivial functions was not desirable. The
approach should be to recognize the extra copy as a temporary
object and deal explicitly with its lifetime.

1594.
Lazy declaration of special members vs overload errors

The implicit declaration of a special member function sometimes
requires overload resolution, in order to select a special member to
use for base classes and non-static data members. This can be required
to determine whether the member is or would be deleted, and whether
the member is trivial, for instance. The standard appears to require
such overload resolution be performed at the end of the definition of
the class, but in practice, implementations perform it lazily. This
optimization appears to be non-conforming, in the case where overload
resolution would hit an error. In order to enable this optimization,
such errors should be “no diagnostic required.”

The problem with this approach is that hard errors (not in the
immediate context) can occur, affecting portability. There are some
cases, such as a virtual assignment operator in the base class, where
lazy evaluation cannot be done, so it cannot be mandated.

is presumably well-formed, even though the copy assignment
operator of A is inaccessible in C, because
15.8.2 [class.copy.assign] paragraph 12 says that only direct,
not virtual, base class object assignment operators are invoked
by the generated assignment operator (although there is
implementation divergence on this question).

Should the example also be well-formed if A were a
direct virtual base of C? That is, if a direct virtual
base also has an indirect derivation path, its direct derivation
can be ignored for generated assignment operators.

Possibly relevant to this question is the permission for an
implementation to assign virtual base class objects more than
once:

It is unspecified whether subobjects representing virtual base
classes are assigned more than once by the implicitly-defined
copy/move assignment operator.

1252.
Overloading member function templates based on dependent return type

1898.
Use of “equivalent” in overload resolution

The normative text of 16.2 [over.dcl] relies on the
term “equivalent,” for which it refers to
16.1 [over.load], but the term appears there only in
non-normative text. The resolution of this issue should be coordinated
with that of issue 1668.

1278.
Incorrect treatment of contrived object

An implied object argument must be contrived to correspond to the
implicit object parameter attributed to member functions during
overload resolution. It is not used in the call to the selected
function. Since the member functions all have the same implicit
object parameter, the contrived object will not be the cause to select
or reject a function.

It is not true that “the member functions all have the same
implicit object parameter.” This statement does not take into
account member functions brought into the class by using-declarations
or cv-qualifiers and ref-qualifiers on the non-static
member functions:

The value category of a contrived object expression is not
specified by the rules and, probably, cannot be properly specified in
presence of ref-qualifiers, so the statement “the
contrived object will not be the cause to select or reject a
function” should be normative rather than informative:

If the assignment operator performs argument-dependent lookup,
A<void> will be an associated class and will be
instantiated, producing an error. Similar questions apply to
the other member-only overloaded operators, operator->
and operator[]. Bullet 3.2 of 16.3.1.2 [over.match.oper]
should be changed not to perform unqualified lookup for these
operators.

2089.
Restricting selection of builtin overloaded operators

The candidates selected by 16.3.1.2 [over.match.oper] include
built-in candidates that will result in an error if chosen; this
was affirmed by issue 1687. As a result,
t+u is ill-formed because it is resolved to the built-in
operator+(int*,std::ptrdiff_t), although most implementations
do not (yet) agree:

Because there are two possible conversions from S to
T, one by conversion function and the other by converting
constructor, one might expect that the initialization at #1 would
be ambiguous. However, 16.3.1.6 [over.match.ref] (used in the
relevant bullet of 11.6.3 [dcl.init.ref], paragraph 5.2.1.2)
only deals with conversion functions and ignores converting
constructors.

Notes from the November, 2014 meeting:

CWG agreed that 11.6.3 [dcl.init.ref] should be changed
to consider converting constructors in this case.

I intuitively thought that the second pair should prevent overloading from
triggering partial ordering since both arguments are non-deduced and has
different types - (char*, char**). Just like in the following:

In this case all the compilers I checked found #5 to be ambiguous.
The standard and DR 214 is not clear
about how partial ordering handle such
cases.

I think that overloading should not trigger partial ordering (in step
16.3.3 [over.match.best]/1/5) if some candidates have
non-deduced pairs with different
(specialized) types. In this stage the arguments are already adjusted so no
need to mention it (i.e. array to pointer). In case that one of the
arguments is non-deuced then partial ordering should only consider the type
from the specialization:

According to my reasoning #9 should yield ambiguity since second pair is (T,
long*). The second type (i.e. long*) was taken from the specialization
candidate of #8.
EDG and GCC accepted the code. VC and BCC found an ambiguity.

John Spicer:
There may (or may not) be an issue concerning whether nondeduced
contexts are handled properly in the partial ordering rules. In
general, I think nondeduced contexts work, but we should walk through
some examples to make sure we think they work properly.

Rani's description of the problem suggests that he believes that
partial ordering is done on the specialized types. This is not
correct. Partial ordering is done on the templates themselves,
independent of type information from the specialization.

Notes from October 2004 meeting:

John Spicer will investigate further to see if any action is
required.

1536.
Overload resolution with temporary from initializer list

In determining the implicit conversion sequence for an initializer list
argument passed to a reference parameter, the intent is that a temporary
of the appropriate type will be created and bound to the reference, as
reflected in 16.3.3.1.5 [over.ics.list] paragraph 5:

Otherwise, if the parameter is a reference, see 16.3.3.1.4 [over.ics.ref]. [Note: The rules in this section will
apply for initializing the underlying temporary for the reference.
—end note]

However, 16.3.3.1.4 [over.ics.ref] deals only with expression
arguments, not initializer lists:

When a parameter of reference type binds directly (11.6.3 [dcl.init.ref]) to an argument expression, the implicit conversion
sequence is the identity conversion, unless the argument expression
has a type that is a derived class of the parameter type, in which
case the implicit conversion sequence is a derived-to-base Conversion
(16.3.3.1 [over.best.ics])... If the parameter binds directly to
the result of applying a conversion function to the argument
expression, the implicit conversion sequence is a user-defined
conversion sequence (16.3.3.1.2 [over.ics.user]), with the second
standard conversion sequence either an identity conversion or, if the
conversion function returns an entity of a type that is a derived
class of the parameter type, a derived-to-base Conversion.

When a parameter of reference type is not bound directly to an
argument expression, the conversion sequence is the one required to
convert the argument expression to the underlying type of the
reference according to 16.3.3.1 [over.best.ics]. Conceptually,
this conversion sequence corresponds to copy-initializing a temporary
of the underlying type with the argument expression. Any difference
in top-level cv-qualification is subsumed by the initialization itself
and does not constitute a conversion.

(Note in particular that the reference binding refers to
11.6.3 [dcl.init.ref], which also does not handle initializer
lists, and not to 11.6.4 [dcl.init.list].)

Either 16.3.3.1.4 [over.ics.ref] needs to be revised to
handle binding references to initializer list arguments or
16.3.3.1.5 [over.ics.list] paragraph 5 needs to be clearer on how
the expression specification is intended to be applied to
initializer lists.

1989.
Insufficient restrictions on parameters of postfix operators

The user-defined function called operator++ implements the
prefix and postfix ++ operator. If this function is a
non-static member function with no parameters, or a
non-member function with one parameter, it defines the
prefix increment operator ++ for objects of that type. If
the function is a non-static member function with one
parameter (which shall be of type int) or a non-member
function with two parameters (the second of which shall be
of type int), it defines the postfix increment operator ++
for objects of that type.

According to 16.5 [over.oper] paragraph 8,

Operator functions cannot have more or fewer parameters than
the number required for the corresponding operator, as
described in the rest of this subclause.

This does not rule out an operator++ with more than two
parameters, however, since there is no corresponding operator.

One possibility might be to add a sentence like,

A function named operator++ shall declare either a prefix
or postfix increment operator.

205.
Templates and static data members

Static data members of template classes and of nested classes of
template classes are not themselves templates but receive much the
same treatment as template. For instance,
17 [temp]
paragraph 1 says that templates
are only "classes or functions" but implies that "a static data member
of a class template or of a class nested within a class template" is
defined using the template-declaration syntax.

There are many places in the clause, however, where static data
members of one sort or another are overlooked. For instance,
17 [temp]
paragraph 6 allows static data
members of class templates to be declared with the export
keyword. I would expect that static data members of (non-template)
classes nested within class templates could also be exported, but they
are not mentioned here.

Paragraph 8, however, overlooks static data members altogether and
deals only with "templates" in defining the effect of the
export keyword; there is no description of the semantics of
defining a static data member of a template to be exported.

These are just two instances of a systematic problem. The entire
clause needs to be examined to determine which statements about
"templates" apply to static data members, and which statements about
"static data members of class templates" also apply to static data
members of non-template classes nested within class templates.

(The question also applies to member functions of template classes;
see issue 217, where the phrase
"non-template function" in 11.3.6 [dcl.fct.default] paragraph 4
is apparently intended not to include non-template member
functions of template classes. See also issue 108, which would benefit from understanding nested classes of
class templates as templates. Also, see issue 249, in which the usage of the phrase "member function
template" is questioned.)

1478.
template keyword for dependent template template arguments

When the name of a member template specialization appears after . or
-> in a postfix-expression or after a
nested-name-specifier in a qualified-id, and the object
expression of the postfix-expression is type-dependent or the
nested-name-specifier in the qualified-id refers to a
dependent type, but the name is not a member of the current
instantiation (17.7.2.1 [temp.dep.type]), the member template
name must be prefixed by the keyword template.

In other words, the template keyword is only required when
forming a template-id. However, current compilers reject an
example like:

template<typename T, template<typename> class U = T::X> struct A;

and require the template keyword before X.
Should the rule be amended to require the template keyword in
cases like this?

2292.
simple-template-id is ambiguous between class-name and type-name

The grammar term simple-template-id is used in the definition
of both class-name (12 [class] paragraph 1) and
type-name (10.1.7.2 [dcl.type.simple] paragraph 1). The latter
case is intended to apply to alias template specializations. It would be
helpful to have separate grammar terms for these uses.

Issue 184 dealt with a similar question
but did so in the era before variadic templates. This usage should
be permitted in modern C++.

Notes from the February, 2016 meeting:

CWG felt that this usage should be permitted, but only
for template template parameters with a parameter pack..
Furthermore, if the template template parameter has a
default argument followed by a parameter pack, the
parameter's default argument would be used, followed by any
remaining default arguments from the template template
argument.

There is implementation variance as to whether there is one
f or two. As with previously-discussed cases, these
have different SFINAE effects, perhaps equivalent but not
functionally equivalent. Should the argument to #1 be treated
as something like A<(int)(short)N> and not just
A<N>.

1432.
Newly-ambiguous variadic template expansions

With the new core rules in regard to variadic pack expansions
the library specification of the traits template
common_type is now broken, the reason is that it is
defined as a series of specializations of the primary template

Such a friend definition is permitted by
17.6.4 [temp.friend] paragraph 2:

A friend function template may be defined within a class or class
template...

Paragraph 4 appears to be related, but deals only with friend functions,
not friend function templates:

When a function is defined in a friend function declaration in a class
template, the function is instantiated when the function is
odr-used. The same restrictions on multiple declarations and
definitions that apply to non-template function declarations and
definitions also apply to these implicit definitions.

The Standard appears to be silent on whether the types of
non-type template arguments in a partial specialization must be
the same as those of the primary template or whether conversions
are permitted. For example,

The closest the current wording comes to dealing with this
question is 17.6.5 [temp.class.spec] paragraph 8 bullet 1:

A partially specialized non-type argument expression shall
not involve a template parameter of the partial
specialization except when the argument expression is a
simple identifier.

In this example, one might think of the first template argument
in the partial specialization as (char)C1, which would
violate the requirement, but that reasoning is tenuous.

It would be reasonable to require the types to match in
cases like this. If this kind of usage is allowed it could
get messy if the primary template were int... and
the partial specialization had a parameter that
was char because not all of the possible values
from the primary template could be represented in the
parameter of the partial specialization. A similar issue
exists if the primary template takes signed char
and the partial specialization takes unsigned
int.

It appears that partial specializations of variable templates are
intended to be supported, as 17.3.3 [temp.arg.template] paragraph 2
says,

Any partial specializations (17.6.5 [temp.class.spec]) associated with
the primary class template or primary variable template are considered when
a specialization based on the template template-parameter is
instantiated.

However, there is no explicit specification for how they are to be
handled, and the wording in 17.6.5 [temp.class.spec] and its
subsections explicitly applies only to partial specializations of
class templates.

Additional note, July, 2017:

The term “primary template” appears not to be defined
in the current wording; the resolution of this issue might be a good
opportunity to add such a definition.

2179.
Required diagnostic for partial specialization after first use

A partial specialization shall be declared before the first
use of a class template specialization that would make use
of the partial specialization as the result of an implicit
or explicit instantiation in every translation unit in which
such a use occurs; no diagnostic is required.

There are two problems with this wording. First, the
“no diagnostic required” provision is presumably
to avoid mandating cross-translation-unit analysis, but there
is no reason not to require the diagnostic if the rule is
violated within a single translation unit. Also, “would
make use” is imprecise; it could be interpreted as
applying only when the partial specialization would have been
selected by a previous specialization, but it should also apply to
cases where the partial specialization would have made a
previous specialization ambiguous.

Making these two changes would guarantee that a diagnostic is
issued for the following example:

It is unspecified whether the reference to
A<char, void> at #1 is the “first
use” or not. If so, A<char, void>
is bound to the first partial specialization and, under the
current wording, an implementation is not required to
diagnose the ambiguity resulting from the second partial
specialization. If #2 is the “first use,” it is
clearly ambiguous and must result in a diagnostic. There is
implementation divergence on the handling of this example
that would be addressed by the suggested changes.

Several compilers issue errors for this case, but there appears
to be nothing in the Standard that would make this ill-formed; it
simply seems that the partial specialization will never be matched,
so the primary template will be used for all specializations.
Should it be ill-formed?

1755.
Out-of-class partial specializations of member templates

If a member template of a class template is partially specialized, the
member template partial specializations are member templates of the
enclosing class template; if the enclosing class template is instantiated
(17.8.1 [temp.inst], 17.8.2 [temp.explicit]), a declaration
for every member template partial specialization is also instantiated as
part of creating the members of the class template specialization.

Does this imply that only partial specializations of member templates
that are declared before the enclosing class is instantiated are
considered? For example, in

2045.
“Identical” template parameter lists

The requirement of 17.6.6.1 [temp.over.link] paragraph 6
that equivalent function templates must have “identical”
template parameter lists is confusing, since the names of template
parameters are not considered (17.6.6.1 [temp.over.link]
paragraph 3).

In fact, the original intent was that the example should have been
correct as written; however, the normative wording to make it so was
missing. The current wording of 17.6.7 [temp.alias] deals
only with the equivalence of a specialization of an alias template
with the type-id after substitution. Wording needs to be added
specifying under what circumstances an alias template itself is
equivalent to a class template.

Proposed resolution (September, 2012):

Add the following as a new paragraph following 17.6.7 [temp.alias] paragraph 2:

When the type-id in the declaration of alias template (call
it A) consists of a simple-template-id in which the
template-argument-list consists of a list of identifiers
naming each template-parameter of A exactly once in
the same order in which they appear in A's
template-parameter-list, the alias template is equivalent to
the template named in the simple-template-id (call it
T) if A and T have the same number of
template-parameters. [Footnote: This rule is transitive:
if an alias template A is equivalent to another alias
template B that is equivalent to a class template C,
then A is also equivalent to C, and A and
B are also equivalent to each other. —end
footnote] [Example:

See also issue 1979, which CWG
is suggesting to be resolved by defining a
“simple” alias, one in which the SFINAE
conditions are the same as the referenced template and that
uses all template parameters.

1430.
Pack expansion into fixed alias template parameter list

Originally, a pack expansion could not expand into a
fixed-length template parameter list, but this was changed in
N2555. This works fine for most templates, but causes issues
with alias templates.

In most cases, an alias template is transparent; when it's
used in a template we can just substitute in the dependent
template arguments. But this doesn't work if the
template-id uses a pack expansion for non-variadic
parameters. For example:

There is no way to express A<Ts...> in terms of
S, so we need to hold onto the A until we have
the Ts to substitute in, and therefore it needs to be
handled in mangling.

Currently, EDG and Clang reject this testcase, complaining
about too few template arguments for A. G++ did as well, but I
thought that was a bug. However, on the ABI list John Spicer
argued that it should be rejected.

Is the substitution of B::foo for foo<B>
done in the context of the befriended class C, making the
reference well-formed, or is the access determined independently of
the context in which the alias template specialization appears?

If the answer to this question is that the access is determined
independently from the context, care must be taken to ensure that an
access failure is still considered to be “in the immediate
context of the function type” (17.9.2 [temp.deduct]
paragraph 8) so that it results in a deduction failure rather than
a hard error.

Notes from the October, 2012 meeting:

The consensus of CWG was that instantiation (lookup and access)
for alias templates should be as for other templates, in the definition
context rather than in the context where they are used. They should
still be expanded immediately, however.

Additional note (February, 2014):

A related problem is raised by the definition of
std::enable_if_t (23.15.2 [meta.type.synop]):

If b is false, there will be no type
member. The intent is that such a substitution failure is to be
considered as being “in the immediate context” where the
alias template specialization is used, but the existing wording does
not seem to accomplish that goal.

Additional note, November, 2014:

Concern has been expressed that the intent to analyze
access in the context of the alias template definition is at odds
with the fact that friendship cannot be granted to alias
templates; if it could, the access violation in the original example
could be avoided by making foo a friend of class B,
but that is not possible.

Additional node, February, 2016:

The issue has been returned to "open" status to facilitate further
discussion by CWG as to whether the direction in the October, 2012 note is
still desirable.

Notes from the February, 2016 meeting:

CWG reaffirmed the direction described in the October,
2012 note above. With regard to the November, 2014 note
regarding granting of friendship, it was observed that the
same problem occurs with enumerators, which might refer to
inaccessible names in the enumerator volue. The solution in
both cases is to embed the declaration in a class and grant
the class friendship. See issue 1844, dealing with the definition of
“immediate context.”

1896.
Repeated alias templates

The current wording of the Standard does not permit repeated
alias template declarations within a scope, but some current
implementations allow it, presumably by analogy with typedef
declarations. Should the Standard be changed to permit this usage?

Notes from the November, 2014 meeting:

CWG agreed that the usage should be permitted, provided that
the dependent types are equivalent. Note that this is a weaker
requirement than the token-for-token identity of the ODR, since
alias templates are not definitions per 17 [temp]
paragraph 1.

Analogy with alias-declarations would suggest that
it should, but alias template specializations involve issues
like SFINAE on unused template parameters (see
issue 1558) and possibly other
complications.

CWG felt that this kind of usage should be permitted only via
a “simple” alias, in which the SFINAE is the same
as the template to which it refers and all the template parameters
are used. See also issue 1286.

According to 17.7 [temp.res] paragraph 3 (before the
salient wording was inadvertently removed, see
issue 559),

A qualified-id that refers to a type and in which the
nested-name-specifier depends on a template-parameter
(17.7.2 [temp.dep]) but does not refer to a member of the
current instantiation (17.7.2.1 [temp.dep.type]) shall be
prefixed by the keyword typename to indicate that
the qualified-id denotes a type, forming
a typename-specifier.

Because Outer<T>::Inner is a member of the current
instantiation, the Standard does not currently require that it be
prefixed with typename when it is used in the return type of
the definition of the self() member function. However, it is
difficult to parse this definition correctly without knowing that the
return type is, in fact, a type, which is what the typename
keyword is for. Should the Standard be changed to require
typename in such contexts?

1271.
Imprecise wording regarding dependent types

When a qualified-id is intended to refer to a type that is not
a member of the current instantiation (17.7.2.1 [temp.dep.type])
and its nested-name-specifier refers to a dependent type, it
shall be prefixed by the keyword typename, forming a
typename-specifier. If the qualified-id in a
typename-specifier does not denote a type, the program is ill-
formed.

The intent of the programmer cannot form the basis for a compiler
determining whether to issue a diagnostic or not.

Suggested resolution:

Let N be a qualified-id with a
nested-name-specifier that denotes a dependent type. If
N is not prefixed by the keyword typename, N
shall refer to a member of the current instantiation or it shall not
refer to a type.

1841.
< following template injected-class-name

Like normal (non-template) classes, class templates have an
injected-class-name (Clause 12 [class]). The
injected-class-name can be used as a template-name or
a type-name. When it is used with a template-argument-list,
as a template-argument for a template template-parameter, or
as the final identifier in the elaborated-type-specifier of a friend
class template declaration, it refers to the class template
itself. Otherwise, it is equivalent to the template-name followed by
the template-parameters of the class template enclosed in <>.

The intent is that a < following such an
injected-class-name is to be interpreted as the start of a
template-argument-list (and an error if the following tokens
do not constitute a valid template-argument-list), but that
is not said explicitly.

1936.
Dependent qualified-ids

The resolution of issue 1321 changed
the term “dependent name” to apply only to
unqualified-ids, presumably on the basis that only
unqualified-ids affect the lookup set. However, the
rule from 17.6.6.1 [temp.over.link] paragraph 5,

For determining whether two dependent names (17.7.2 [temp.dep])
are equivalent, only the name itself is considered, not the result of name
lookup in the context of the template. If multiple declarations of the same
function template differ in the result of this name lookup, the result for
the first declaration is used.

should apply to non-dependent qualified-ids naming
functions called with dependent arguments, as well.

There should also be a statement that the name of a member
of an unknown specialization is a dependent name and so should
fall under the rules of 17.7.4 [temp.dep.res] and not
17.7.3 [temp.nondep].

A type used as a base must be complete (13 [class.derived]
paragraph 2). The fact that the base class in this example is the
current instantiation could be interpreted as indicating that it
should be available for lookup, and thus the normal rule should apply,
as members declared after the nested class would not be visible.

On the other hand, 17.7.2 [temp.dep] paragraph 3
says,

In the definition of a class or class template, if a base class
depends on a template-parameter, the base class scope is not
examined during unqualified name lookup either at the point of
definition of the class template or member or during an instantiation
of the class template or member.

This wording refers not to a dependent type, which would permit
lookup in the current instantiation, but simply to a type that
“depends on a template-parameter,” and the current
instantiation is such a type.

Implementations vary on the handling of this example.

(See also issue 1526 for another case
related to the distinction between a “dependent type” and
a “type that depends on a template-parameter.”)

Notes from the October, 2012 meeting:

CWG determined that the example should be ill-formed.

2065.
Current instantiation of a partial specialization

According to 17.7.2.1 [temp.dep.type] paragraph 1, a name
refers to the current instantiation if it is

in the definition of a partial specialization or a member of
a partial specialization, the name of the class template
followed by the template argument list of the partial
specialization enclosed in <> (or an equivalent
template alias specialization).

I don't think this works. How are the argument lists
compared? If it's using the “equivalent” rules,
this doesn't work because we make no provision for
“functionally equivalent but not equivalent” here.
If it's using 17.5 [temp.type] paragraph 1, that
fails because it doesn't handle dependent template arguments
at all.

The same issue would come up when defining members of a
partial specialization out-of-line.

2294.
Dependent auto static data members

The list of type-dependent id-expressions in
17.7.2.2 [temp.dep.expr] paragraph 3 should include the case when a
static data member is declared with the auto type specifier and
the initializer is dependent.

2090.
Dependency via non-dependent base class

a non-type template-argument is dependent if the
corresponding non-type template-parameter is of
reference or pointer type and the template-argument
designates or points to a member of the current
instantiation or a member of a dependent type.

Members of non-dependent base classes are members of the
current instantiation, but using one as a non-type template
argument should not be considered dependent.

2.
How can dependent names be used in member declarations that appear outside of the class template definition?

In the class template definition, the declaration of the member function
is interpreted as:

int Foo<T>::f();

In the definition of the member function that appears outside of the class
template, the return type is not known until the member function
is instantiated.
Must the return type of the member function be known when this out-of-line
definition is seen (in which case the definition above is ill-formed)?
Or is it OK to wait until the member function is instantiated to see if
the type of the return type matches the return type in the class template
definition (in which case the definition above is well-formed)?

Suggested resolution: (John Spicer)

My opinion (which I think matches several posted on the reflector recently)
is that the out-of-class definition must match the
declaration in the template.
In your example they do match, so it is well formed.

I've added some additional cases that illustrate cases that I think
either are allowed or should be allowed, and some cases that I don't think
are allowed.

In general, if you can match the declarations up using only information
from the template, then the declaration is valid.

Declarations like Foo::i and Foo::j are invalid because
for a given instance of A<T>, A<T>::X may not actually
be int if the class is specialized.

This is not a problem for Foo::g1 and Foo::g2 because
for any instance of Foo<T> that is generated from the template
you know that Bar will always be int. If an instance of Foo is
specialized, the template member definitions are not used so it doesn't
matter whether a specialization defines Bar as int or not.

Some implementations accept it. At least one rejects it
because the instantiation of A<B<int> >
requires that B<int> be complete, and it is
not at the point at which A<B<int> >
is being instantiated.

Erwin Unruh:

In my view the programm is ill-formed. My reasoning:

you need a complete type B<int> because you declare
a variable in main

B<int> contains a member of type
A<B<int> >, so you need that complete.

A<B<int> > tries to access
B<int>::X, which in turn needs B<int>
being complete.

So each class needs the other to be complete.

The problem can be seen much easier if you replace the typedef with

typedef T (*X) [sizeof(B::a)];

Now you have a true recursion. The compiler cannot easily distinguish
between a true recursion and a potential recursion.

John Spicer:

Using a class to form a qualified name does not require the class to be
complete, it only requires that the named member already have been declared.
In other words, this kind of usage is permitted:

class A {
typedef int B;
A::B ab;
};

In the same way, once B has been declared in A,
it is also visible to any template that uses A through a
template parameter.

The standard could be more clear in this regard, but there are two
notes that make this point. Both 6.4.3.1 [class.qual] and
_N4567_.5.1.1 [expr.prim.general] paragraph 7 contain a note that says "a
class member can be referred to using a qualified-id at any point in
its potential scope (6.3.7 [basic.scope.class])." A member's
potential scope begins at its point of declaration.

In other words, a class has three states: incomplete, being
completed, and complete. The standard permits a qualified name to be
used once a name has been declared. The quotation of the notes about
the potential scope was intended to support that.

So, in the original example, class A does not require the
type of T to be complete, only that it have already declared
a member X.

Bill Gibbons:

The template and non-template cases are different. In the non-template
case the order in which the members become declared is clear. In the
template case the members of the instantiation are conceptually all
created at the same time. The standard does not say anything about
trying to mimic the non-template case during the instantiation of a class
template.

Mike Miller:

I think the relevant specification is 17.7.4.1 [temp.point] paragraph 3, dealing with the point of
instantiation:

For a class template specialization... if the specialization is
implicitly instantiated because it is referenced from within
another template specialization, if the context from which the
specialization is referenced depends on a template parameter, and
if the specialization is not instantiated previous to the
instantiation of the enclosing template, the point of
instantiation is immediately before the point of instantiation
of the enclosing template. Otherwise, the point of instantiation
for such a specialization immediately precedes the namespace scope
declaration or definition that refers to the specialization.

That means that the point of instantiation of A<B<int>
> is before that of B<int>, not in the middle
of B<int> after the declaration of B::X, and
consequently a reference to B<int>::X from
A<B<int> > is ill-formed.

To put it another way, I believe John's approach requires that there
be an instantiation stack, with the results of partially-instantiated
templates on the stack being available to instantiations above them.
I don't think the Standard mandates that approach; as far as I can
see, simply determining the implicit instantiations that need to be
done, rewriting the definitions at their respective points of
instantiation with parameters substituted (with appropriate "forward
declarations" to allow for non-instantiating references), and
compiling the result normally should be an acceptable implementation
technique as well. That is, the implicit instantiation of the
example (using, e.g., B_int to represent the generated name of the
B<int> specialization) could be something like

This was discussed at length. The consensus was that the template case
should be treated the same as the non-template class case it terms of
the order in which members get declared/defined and classes get completed.

Proposed resolution:

In 17.7.4.1 [temp.point] paragraph 3 change:

the point of instantiation is immediately before the point of
instantiation of the enclosing template. Otherwise, the point of
instantiation for such a specialization immediately precedes the
namespace scope declaration or definition that refers to the
specialization.

To:

the point of instantiation is the same as the point of
instantiation of the enclosing template. Otherwise, the point of
instantiation for such a specialization immediately precedes the
nearest enclosing declaration.
[Note: The point of instantiation is still at namespace scope but
any declarations preceding the point of instantiation, even if not
at namespace scope, are considered to have been seen.]

Add following paragraph 3:

If an implicitly instantiated class template specialization, class
member specialization, or specialization of a class template references
a class, class template specialization, class member specialization, or
specialization of a class template containing a specialization reference
that directly or indirectly caused the instantiation, the requirements
of completeness and ordering of the class reference are applied in the
context of the specialization reference.

The instantiation context of an expression that depends on the
template arguments is the set of declarations with external linkage
declared prior to the point of instantiation of the template
specialization in the same translation unit.

Presumably this wording was overlooked and should be harmonized with
the new specification.

1845.
Point of instantiation of a variable template specialization

The current wording of 17.7.4.1 [temp.point] does not
define the point of instantiation of a variable template
specialization. Presumably replacing the references to “static
data member of a class template” with “variable
template” in paragraphs 1 and 8 would be sufficient.

Additional note, July, 2017:

It has also been observed that there is no definition of the
point of instantiation for an alias template. It is not clear that
there is a need for normative wording for the point of instantiation
of an alias template, but if not, a note explaining its absence
would be helpful.

1253.
Generic non-template members

Many statements in the Standard apply only to templates, for example,
17.7 [temp.res] paragraph 8:

If no valid specialization can be generated for a template definition,
and that template is not instantiated, the template definition is
ill-formed, no diagnostic required.

This clearly should apply to non-template member functions of class
templates, not just to templates per se. Terminology should be established
to refer to these generic entities that are not actually templates.

Additional notes (August, 2012):

Among the generic entities that should be covered by such a term
are default function arguments, as they can be instantiated independently.
If issue 1330 is resolved as expected,
exception-specifications should also be covered by the same term.

2072.
Default argument instantiation for member functions of templates

Default argument instantiation is described in
17.8.1 [temp.inst] paragraph 13, and although instantiation
of default arguments for member functions of class templates is
mentioned elsewhere a number of times, this paragraph only describes
default argument instantiation for function templates.

2222.
Additional contexts where instantiation is not required

If the function selected by overload resolution (16.3 [over.match])
can be determined without instantiating a class template definition, it is
unspecified whether that instantiation actually takes place.

There are other contexts in which a smart implementation could
presumably avoid instantiations, such as when doing argument-dependent
lookup involving a class template specialization when the template
definition contains no friend declarations or checking
base/derived relationships involving incomplete class template
definitions. It would be helpful to enumerate such contexts.

Presumably in both these cases the explicit instantiation should
refer to the template and not to the non-template; however,
17.6.2 [temp.mem] paragraph 2 says,

A normal (non-template) member function with a given name and type and a
member function template of the same name, which could be used to generate
a specialization of the same type, can both be declared in a class. When
both exist, a use of that name and type refers to the non-template member
unless an explicit template argument list is supplied.

This would appear to give the wrong answer for the first example.
It's not clearly stated, but consistency would suggest a similar wrong
answer for the second. Presumably a statement is needed somewhere that
an explicit instantiation directive applies to a template and not a
non-template function if both are visible.

529.
Use of template<> with “explicitly-specialized” class templates

A member or a member template may be nested within many enclosing
class templates. In an explicit specialization for such a member, the
member declaration shall be preceded by a template<>
for each enclosing class template that is explicitly specialized.

This is curious, because paragraph 3 only allows explicit
specialization of members of implicitly-instantiated class
specializations, not explicit specializations. Furthermore,
paragraph 4 says,

Definitions of members of an explicitly specialized class are defined
in the same manner as members of normal classes, and not using the
explicit specialization syntax.

Paragraph 18 provides a clue for resolving the apparent
contradiction:

In an explicit specialization declaration for a member of a class
template or a member template that appears in namespace scope, the
member template and some of its enclosing class templates may remain
unspecialized, except that the declaration shall not explicitly
specialize a class member template if its enclosing class templates
are not explicitly specialized as well. In such explicit
specialization declaration, the keyword template followed by
a template-parameter-list shall be provided instead of
the template<> preceding the explicit specialization
declaration of the member.

It appears from this and the following example that the phrase
“explicitly specialized” in paragraphs 17 and 18, when
referring to enclosing class templates, does not mean that explicit
specializations have been declared for them but that their names in
the qualified-id are followed by template argument lists. This
terminology is confusing and should be changed.

Proposed resolution (October, 2005):

Change 17.8.3 [temp.expl.spec] paragraph 17 as
indicated:

A member or a member template may be nested within many enclosing
class templates. In an explicit specialization for such a member, the
member declaration shall be preceded by a template<>
for each enclosing class template that is explicitly specializedspecialization. [Example:...

Change 17.8.3 [temp.expl.spec] paragraph 18 as
indicated:

In an explicit specialization declaration for a member of a class
template or a member template that appears in namespace scope, the
member template and some of its enclosing class templates may remain
unspecialized, except that the declaration shall not explicitly
specialize a class member template if its enclosing class templates
are not explicitly specialized as wellthat is, the
template-id naming the template may be composed of template
parameter names rather than template-arguments. InFor each unspecialized template in such an explicit
specialization declaration, the keyword template followed by
a template-parameter-list shall be provided instead of
the template<> preceding the explicit
specialization declaration of the member. The types of
the template-parameters in the template-parameter-list
shall be the same as those specified in the primary template
definition. In such declarations, an unspecialized template-id
shall not precede the name of a template specialization in the
qualified-id naming the member. [Example:...

Notes from the April, 2006 meeting:

The revised wording describing “unspecialized” templates
needs more work to ensure that the parameter names in the
template-id are in the correct order; the distinction between
template arguments and parameters is also probably not clear enough. It
might be better to replace this paragraph completely and avoid the
“unspecialized” wording altogether.

Proposed resolution (February, 2010):

Change 17.8.3 [temp.expl.spec] paragraph 17 as follows:

A member or a member template may be nested within many enclosing
class templates. In an explicit specialization for such a
member, the member declaration shall be preceded by a
template<> for each enclosing class template
that is explicitly specializedspecialization. [Example:...

Change 17.8.3 [temp.expl.spec] paragraph 18 as follows:

In an explicit specialization declaration for a member of a
class template or a member template that appears in namespace
scope, the member template and some of its enclosing class
templates may remain unspecialized, except that the declaration
shall not explicitly specialize a class member template if its
enclosing class templates are not explicitly specialized as well.
In such explicit specialization declaration, the keyword
template followed by a template-parameter-list
shall be provided instead of the template<>
preceding the explicit specialization declaration of the member.
The types of the template-parameters in the
template-parameter-list shall be the same as those
specified in the primary template definition.that is,
the corresponding template prefix may specify a
template-parameter-list instead of template<>
and the template-id naming the template be written using
those template-parameters as template-arguments.
In such a declaration, the number, kinds, and types of the
template-parameters shall be the same as those specified in
the primary template definition, and the template-parameters
shall be named in the template-id in the same order that they
appear in the template-parameter-list. An unspecialized
template-id shall not precede the name of a template
specialization in the qualified-id naming the member.
[Example:...

However, the existing normative wording is not adequate to handle
this usage. For one thing, =delete is formally, at least,
a function definition, and an implementation is not permitted to
instantiate a function definition unless it is used; presumably, then,
an implementation could not reject the decltype above as
a reference to a deleted specialization. Furthermore, there should
be a requirement that a non-deleted explicit specialization of a
deleted function template must precede any reference to that
specialization. (I.e., the example should be ill-formed as written
but well-formed if the last two lines were interchanged.)

1993.
Use of template<> defining member of explicit specialization

Issue 531 surveyed existing practice at
the time and determined that the most common syntax for defining a member
of an explicit specialization used the template<>
prefix. This approach, however, does not seem consistent, since such
a definition is not itself an explicit specialization.

2055.
Explicitly-specified non-deduced parameter packs

Trailing template arguments that can be deduced
(17.9.2 [temp.deduct]) or obtained from
default template-arguments may be omitted from the
list of explicit template-arguments. A trailing
template parameter pack (17.6.3 [temp.variadic]) not
otherwise deduced will be deduced to an empty sequence of
template arguments. If all of the template arguments can be
deduced, they may all be omitted; in this case, the empty
template argument list <> itself may also be
omitted. In contexts where deduction is done and fails, or
in contexts where deduction is not done, if a template
argument list is specified and it, along with any default
template arguments, identifies a single function template
specialization, then the template-id is an lvalue for
the function template specialization.

1172.
“instantiation-dependent” constructs

There are certain constructs that are not covered by the existing
categories of “type dependent” and “value
dependent.” For example, the expression
sizeof(sizeof(T())) is neither type-dependent nor
value-dependent, but its validity depends on whether T
can be value-constructed. We should be able to overload on
such characteristics and select via deduction failure, but we
need a term like “instantiation-dependent” to
describe these cases in the Standard. The phrase “expression
involving a template parameter” seems to come pretty close to
capturing this idea.

Notes from the November, 2010 meeting:

The CWG favored extending the concepts of “type-dependent”
and “value-dependent” to cover these additional cases,
rather than adding a new concept.

Notes from the March, 2011 meeting:

The CWG reconsidered the direction from the November, 2010 meeting,
as it would make more constructs dependent, thus requiring more
template and typename keywords, resulting in worse
error messages, etc.

Notes from the August, 2011 meeting:

The following example (from issue 1273)
was deemed relevant for this issue:

1322.
Function parameter type decay in templates

The discussion of issue 1001 seemed to have
settled on the approach of doing the 11.3.5 [dcl.fct]
transformations immediately to the function template declaration, so
that the original form need not be remembered. However, the example
in 17.9.2 [temp.deduct] paragraph 8 suggests otherwise:

One way that might be addressed would be to separate the concepts
of the type of the template that participates in overload resolution and
function matching from the type of the template that is the source for
template argument substitution. (See also the example in paragraph 3 of
the same section.)

Notes, January, 2012:

1582.
Template default arguments and deduction failure

The resulting substituted and adjusted function type is used as the
type of the function template for template argument deduction. If a
template argument has not been deduced and its corresponding template
parameter has a default argument, the template argument is determined
by substituting the template arguments determined for preceding
template parameters into the default argument. If the substitution
results in an invalid type, as described above, type deduction fails.

This leaves the impression that default arguments are used after
deduction failure leaves an argument undeduced. For example,

1724.
Unclear rules for deduction failure

If a substitution results in an invalid type or expression, type deduction
fails. An invalid type or expression is one that would be ill-formed, with
a diagnostic required, if written using the substituted arguments.

Presumably the phrase “if written” refers to rewriting the
template declaration in situ with the substituted arguments, rather
than writing that type or expression at some arbitrary location, e.g.,

2322.
Substitution failure and lexical order

The substitution occurs in all types and expressions that are used in the
function type and in template parameter declarations. The expressions
include not only constant expressions such as those that appear in array
bounds or as nontype template arguments but also general expressions (i.e.,
non-constant expressions) inside sizeof, decltype, and
other contexts that allow non-constant expressions. The substitution
proceeds in lexical order and stops when a condition that causes deduction
to fail is encountered.

However, the same type can be represented in different lexical orders.
For example, there is implementation variance on the following example,
presumably because of preferring different declarations:

1513.
initializer_list deduction failure

If removing references and cv-qualifiers from P gives
std::initializer_list<P'> for some
P' and the argument is an initializer list
(11.6.4 [dcl.init.list]), then deduction is performed instead for
each element of the initializer list, taking P' as a
function template parameter type and the initializer element as its
argument. Otherwise, an initializer list argument causes the parameter
to be considered a non-deduced context (17.9.2.5 [temp.deduct.type]).

It is not entirely clear whether the deduction for an initializer
list meeting a std::initializer_list<T> is a recursive
subcase, or part of the primary deduction. A relevant question is:
if the deduction on that part fails, does the entire deduction fail,
or is the parameter to be considered non-deduced?

A template-argument can be deduced from a function, pointer to
function, or pointer to member function type. [Note:
cv-qualification of a deduced function type is ignored; see
11.3.5 [dcl.fct]. —end note]
[Example:

1939.
Argument conversions to nondeduced parameter types revisited

The intent of the resolution of issue 1184 appears not to have been completely realized. In
particular, the phrase, “contains
no template-parameters that participate in template
argument deduction” in both the note in
17.9.2.1 [temp.deduct.call] paragraph 4 and the normative
wording in 17.9.1 [temp.arg.explicit] paragraph 6 is potentially
misleading and probably should say something like,
“contains no template-parameters outside non-deduced
contexts.” Also, the normative wording should be moved to
17.9.2.1 [temp.deduct.call] paragraph 4, since it applies when
there are no explicitly-specified template arguments. For
example,

template<typename T>
void f(T, typename identity<T>::type*);

Presumably the second parameter should allow pointer conversions,
even though it does contain a template-parameter that
participates in deduction (via the first function parameter).

1610.
Cv-qualification in deduction of reference to array

it is intuitive that the second template is more specialized than
the first. However, the current rules make them unordered.
In 17.9.2.4 [temp.deduct.partial] paragraph 4, we have P as
const C* and A as const char (&)[N]. Paragraph 5
transforms A to const char[N]. Finally, paragraph 7 removes
top-level cv-qualification; since a cv-qualified array element type is
considered to be cv-qualification of the array (6.9.3 [basic.type.qualifier]
paragraph 5, cf issue 1059), A
becomes char[N]. P remains const C*, so deduction fails
because of the missing const in A.

The problem is the interpretation of 17.9.2.5 [temp.deduct.type]
paragraph 4:

In most cases, the types, templates, and non-type values that are used to
compose P participate in template argument deduction. That is,
they may be used to determine the value of a template argument, and the
value so determined must be consistent with the values determined
elsewhere. In certain contexts, however, the value does not participate in
type deduction, but instead uses the values of template arguments that were
either deduced elsewhere or explicitly specified. If a template parameter
is used only in non-deduced contexts and is not explicitly specified,
template argument deduction fails.

According to 17.9.2.1 [temp.deduct.call] paragraph 1, deduction is
performed independently for each element of the initializer list:

Template argument deduction is done by comparing each function template
parameter type (call it P) that
contains template-parameters that participate in template argument
deduction with the type of the corresponding argument of the call (call it
A) as described below. If removing references and cv-qualifiers
from P gives std::initializer_list<P'>
or P'[N] for some P' and N and the argument is a
non-empty initializer list (11.6.4 [dcl.init.list]), then deduction is
performed instead for each element of the initializer list,
taking P' as a function template parameter type and the
initializer element as its argument, and in the P'[N] case,
if N is a non-type template parameter, N is deduced from
the length of the initializer list. Otherwise, an initializer list argument
causes the parameter to be considered a non-deduced context
(17.9.2.5 [temp.deduct.type]).

Deduction fails for the second element of the list, &f4,
because of ambiguity. Does this mean that deduction fails for the entire
call, or does the successful deduction of T from the first
element and N from the length of the list result in successful
deduction for the call?

Notes from the July, 2017 meeting:

CWG determined that the call is well-formed.

2172.
Multiple exceptions with one exception object

During the discussion of issue 2098 it
was observed that multiple exceptions may share a single exception
object via std::exception_ptr. It is not clear that the
current wording handles that case correctly.

The exception specification for an implicitly-declared
destructor, or a destructor without a noexcept-specifier,
is potentially-throwing if and only if any of the destructors for
any of its potentially constructed subojects is potentially
throwing.

For a class, its non-static data members, its non-virtual direct
base classes, and, if the class is not abstract
(13.4 [class.abstract]), its virtual base classes are called
its potentially constructed subobjects.

It appears that some of the recent changes to the description of
constant expressions have allowed constructs into preprocessor
expressions that do not belong there. Some changes are required to
restrict the current capabilities of constant expressions to what
is intended to be allowed in preprocessor expressions.

Proposed resolution (February, 2012):

Change 19.1 [cpp.cond] paragraph 2 as follows:

Each preprocessing token that remains (in the list of preprocessing
tokens that will become the controlling expression) after all macro
replacements have occurred shall be in the lexical form of a token
(5.6 [lex.token]). Any such token that is a literal
(5.13.1 [lex.literal.kinds]) shall be an integer-literal, a
character-literal, or a boolean-literal.

1718.
Macro invocation spanning end-of-file

Although it seems to be common implementation practice to reject
a macro invocation that begins in a header file and whose closing
right parenthesis appears in the file that included it, there does
not seem to be a prohibition of this case in the specification of
function-style macros. Should this be accepted?

Notes from the February, 2014 meeting:

CWG agreed that macro invocations spanning file boundaries should be
prohibited. Resolution of this issue should be coordinated with WG14.

2003.
Zero-argument macros incorrectly specified

If the identifier-list in the macro definition does not end
with an ellipsis, the number of arguments (including those
arguments consisting of no preprocessing tokens) in an
invocation of a function-like macro shall equal the number
of parameters in the macro definition.

That is, a sequence of no preprocessing tokens counts as an
argument. That phrasing has problems with zero-argument
function-like macros, e.g.,

#define M()
M();

M is defined as having no parameters but the invocation
has one (empty) argument, which does not match the number of
parameters in the definition.

1335.
Stringizing, extended characters, and universal-character-names

When a string literal containing an extended character is
stringized (19.3.2 [cpp.stringize]), the result contains a
universal-character-name instead of the original extended character.
The reason is that the extended character is translated to a
universal-character-name in translation phase 1 (5.2 [lex.phases]), so that the string literal "@" (where @
represents an extended character) becomes "\uXXXX". Because
the preprocessing token is a string literal, when the stringizing
occurs in translation phase 4, the \ is doubled, and the
resulting string literal is "\"\\uXXXX\"". As a result, the
universal-character-name is not recognized as such when the translation
to the execution character set occurs in translation phase 5. (Note
that phase 5 translation does occur if the stringized extended character
does not appear in a string literal.) Existing practice appears to
ignore these rules and preserve extended characters in stringized
string literals, however.

(An implementation may use any internal encoding, so long as an actual
extended character encountered in the source file, and the same extended
character expressed in the source file as a universal-character-name (i.e.,
using the \uXXXX notation), are handled equivalently except where
this replacement is reverted in a raw string literal.)

However, this freedom is mostly nullified by the requirements of
stringizing in 19.3.2 [cpp.stringize] paragraph 2:

If, in the replacement list, a parameter is immediately preceded by
a # preprocessing token, both are replaced by a single character
string literal preprocessing token that contains the spelling of the
preprocessing token sequence for the corresponding argument.

an implementation must recall the original spelling, including
the form of UCN and the capitalization of any non-numeric hexadecimal
digits, rather than simply translating the characters into a convenient
internal representation.

To effect the freedom asserted in 5.2 [lex.phases], the
description of stringizing should make the spelling of a
universal-character-name implementation-defined.

1709.
Stringizing raw string literals containing newline

Stringizing a raw string literal containing a newline produces an
invalid (unterminated) string literal and hence results in undefined
behavior. It should be specified that a newline in a string literal is
transformed to the two characters '\' 'n' in the resulting string
literal.

A slightly related case involves stringizing a bare backslash
character: because backslashes are only escaped within a string or
character literal, a stringized bare backslash becomes "\",
which is invalid and hence results in undefined behavior.

1279.
Additional differences between C++ 2003 and C++ 2011

A number of differences between C++03 and C++11 were omitted from
C.2 [diff.cpp03]:

New keywords. Although these are said in C.2.1 [diff.cpp03.lex] only to invalidate C++03 code, they can also change
the meaning, e.g., thread_local x(y), which would declare
a variable thread_local initialized with y in
C++03 and a thread-local variable y in C++11.

New deduction rules.

Removal of the deprecated string literal conversion.

When a friend function defined in a class template
is actually defined (i.e., with each instantiation or only when
odr-used).

Removal of access declarations.

Use of the injected-class-name of a class template as a
template template-argument.

Additional note (January, 2012):

In addition to the items previously mentioned, access declarations
were removed from C++11 but are not mentioned in C.2 [diff.cpp03].

Proposed (partial) resolution (February, 2012):

Add the following as a new section in C.2 [diff.cpp03]:

C.2.5 Clause 14 [class.access]: member access control

pdiff.cpp03.class.access

Change: Remove access declarations.

Rationale: Removal of feature deprecated since C++ 1998.

Effect on original feature: Valid C++ 2003 code that uses
access declarations is ill-formed in this International Standard.
Instead, using-declarations (10.3.3 [namespace.udecl]) can
be used.

According to _N2914_.14.10.2.1 [concept.map.fct] paragraph 4, the
destructor requirement in the concept map results in an expression
x.~X(), where X is the type int&.
According to 8.2.4 [expr.pseudo], this expression is ill-formed
because the object type and the type-name must be the same type,
but the object type cannot be a reference type (references are dropped
from types used in expressions, 8 [expr] paragraph 5).

It is not clear whether this should be addressed by changing
8.2.4 [expr.pseudo] or _N2914_.14.10.2.1 [concept.map.fct].

783.
Definition of “argument”

The definition of an argument does not seem to cover
many assumed use cases, and we believe that is not
intentional. There should be answers to
questions such as: Are lambda-captures
arguments? Are type names in a throw-spec
arguments? “Argument” to casts, typeid, alignof,
alignas, decltype and sizeof? why in x[arg] arg is
not an argument, but the value forwarded to
operator[]() is? Does not apply to operators as
call-points not bounded by parentheses? Similar
for copy initialization and conversion? What are
deduced template “arguments?” what are “default
arguments?” can attributes have arguments? What
about concepts, requires clauses and
concept_map instantiations? What about user-defined
literals where parens are not used?

949.
Requirements for freestanding implementations

A freestanding implementation is one in which execution may take place
without the benefit of an operating system, and has an
implementation-defined set of libraries that includes certain
language-support libraries (20.5.1.3 [compliance]).

This definition links two relatively separate topics: the lack
of an operating system and the minimal set of libraries.
Furthermore, 6.6.1 [basic.start.main] paragraph 1 says:

[Note: in a freestanding environment, start-up and termination
is implementation-defined; start-up contains the execution of
constructors for objects of namespace scope with static storage
duration; termination contains the execution of destructors for
objects with static storage duration. —end note]

It would be helpful if the two characteristics (lack of an
operating system and restricted set of libraries) were named
separately and if these statements were clarified to identify exactly
what is implementation-defined.

Notes from the October, 2009 meeting:

The CWG felt that it needed a specific proposal in a paper before
attempting to resolve this issue.

1953.
Data races and common initial sequence

A memory location is either an object of scalar type or a
maximal sequence of adjacent bit-fields all having non-zero
width. [Note: Various features of the language, such
as references and virtual functions, might involve
additional memory locations that are not accessible to
programs but are managed by the
implementation. —end note] Two or more threads
of execution (4.7 [intro.multithread]) can update and
access separate memory locations without interfering with
each other.

It is not clear how this relates to the permission
granted in 12.2 [class.mem] paragraph 18 to inspect
the common initial sequence of standard-layout structs that
are members of a standard-layout union. If one thread is
writing to the common initial sequence and another is
reading from it via a different struct, that should
constitute a data race, but the current wording does not
clearly state that.

2334.
Creation of objects by typeid

The list of ways that an object may be created in
4.5 [intro.object] paragraph 1 does not include creation
of type_info objects by typeid expressions, but
8.2.8 [expr.typeid] does not appear to require that such
objects exist before they are referenced. Should the list in
4.5 [intro.object] be extended to include this case?

698.
The definition of “sequenced before” is too narrow

According to 4.6 [intro.execution] paragraph 14, “sequenced
before” is a relation between “evaluations.” However,
6.6.3 [basic.start.dynamic] paragraph 3 says,

If the completion of the initialization of a non-local object with
static storage duration is sequenced before a call to
std::atexit (see <cstdlib>, 21.5 [support.start.term]), the call to the function passed to std::atexit
is sequenced before the call to the destructor for the object. If a
call to std::atexit is sequenced before the completion of the
initialization of a non-local object with static storage duration, the
call to the destructor for the object is sequenced before the call to
the function passed to std::atexit. If a call to
std::atexit is sequenced before another call to
std::atexit, the call to the function passed to the second
std::atexit call is sequenced before the call to the function
passed to the first std::atexit call.

Except for the calls to std::atexit, these events do not
correspond to “evaluation” of expressions that appear in
the program. If the “sequenced before” relation is to be
applied to them, a more comprehensive definition is needed.

578.
Phase 1 replacement of characters with universal-character-names

Any source file character not in the basic source character set
(5.3 [lex.charset]) is replaced by the
universal-character-name that designates that character.

If a character that is not in the basic character set is preceded
by a backslash character, for example

"\á"

the result is equivalent to

"\\u00e1"

that is, a backslash character followed by the spelling of the
universal-character-name. This is different from the result in C99,
which accepts characters from the extended source character set without
replacing them with universal-character-names.

1698.
Files ending in \

The description of how to handle file not ending in a newline in
5.2 [lex.phases] paragraph 1, phase 2, is:

Each instance of a backslash character (\)
immediately followed by a new-line character is deleted, splicing physical
source lines to form logical source lines. Only the last backslash on any
physical source line shall be eligible for being part of such a splice. If,
as a result, a character sequence that matches the syntax of a
universal-character-name is produced, the behavior is undefined. A source
file that is not empty and that does not end in a new-line character, or
that ends in a new-line character immediately preceded by a backslash
character before any such splicing takes place, shall be processed as if an
additional new-line character were appended to the file.

This is not clear regarding what happens if the last character in the
file is a backslash. In such a case, presumably the result of adding the
newline should not be a line splice but rather a
backslash preprocessing-token (that will be diagnosed as an invalid
token in phase 7), but that should be spelled out.

1403.
Universal-character-names in comments

If the hexadecimal value for a universal-character-name
corresponds to a surrogate code point (in the range
0xD800-0xDFFF, inclusive), the program is
ill-formed. Additionally, if the hexadecimal value for a
universal-character-name outside the c-char-sequence,
s-char-sequence, or r-char-sequence of a character
or string literal corresponds to a control character (in either
of the ranges 0x00-0x1F or 0x7F-0x9F, both inclusive) or to a
character in the basic source character set, the program is
ill-formed.

These restrictions should not apply to comment text. Arguably
the prohibitions of control characters and characters in the basic
character set already do not apply, as they require that the
preprocessing tokens for literals have already been recognized; this
occurs in phase 3, which also replaces comments with single spaces.
However, the prohibition of surrogate code points is not so limited
and might conceivably be applied within comments.

Probably the most straightforward way of addressing this problem
would be simply to state in 5.7 [lex.comment] that
character sequences that resemble universal-character-names are not
recognized as such within comment text.

411.
Use of universal-character-name in character versus string literals

Escape sequences and
universal-character-names in string literals have the same meaning as in
character literals, except that the single quote ' is representable
either by itself or by the escape sequence \', and the double quote "
shall be preceded by a \. In a narrow string literal, a
universal-character-name may map to more than one char element due to
multibyte encoding.

The first sentence refers us to 5.13.3 [lex.ccon],
where we read in the
first paragraph that "An ordinary character literal that contains a
single c-char has type char [...]." Since the grammar shows that a
universal-character-name is a c-char, something like '\u1234' must have
type char (and thus be a single char element); in paragraph 5, we read
that "A universal-character-name is translated to the encoding, in the
execution character set, of the character named. If there is no such
encoding, the universal-character-name is translated to an
implemenation-defined encoding."

This is in obvious contradiction with the second sentence. In addition,
I'm not really clear what is supposed to happen in the case where the
execution (narrow-)character set is UTF-8. Consider the character
\u0153 (the oe in the French word oeuvre). Should '\u0153' be a char,
with an "error" value, say '?' (in conformance with the requirement that
it be a single char), or an int, with the two char values 0xC5, 0x93, in
an implementation defined order (in conformance with the requirement
that a character representable in the execution character set be
represented). Supposing the former, should "\u0153" be the equivalent of
"?" (in conformance with the first sentence), or "\xC5\x93" (in
conformance with the second).

Notes from October 2003 meeting:

We decided we should forward this to the C committee and let them
resolve it. Sent via e-mail to John Benito on November 14, 2003.

Reply from John Benito:

I talked this over with the C project editor, we believe this was
handled by the C committee before publication of the current standard.

WG14 decided there needed to be a more restrictive rule
for one-to-one mappings: rather than saying "a single c-char"
as C++ does, the C standard says "a single character that
maps to a single-byte execution character"; WG14 fully expect
some (if not many or even most) UCNs to map to multiple characters.

Because of the fundamental differences between C and C++ character
types, I am not sure the C committee is qualified to answer this
satisfactorily for WG21. WG14 is willing to review any decision reached
for compatibility.

1266.
user-defined-integer-literal overflow

The decimal-literal in a user-defined-integer-literal
might be too large for an unsigned long long to represent (in
implementations with extended integer types). In such cases, the
original intent appears to have been to call a raw literal operator or
a literal operator template; however, the existing wording of
5.13.8 [lex.ext] paragraph 3 always calls the
unsigned long long literal operator if it exists, regardless
of the value of the decimal-literal.

1209.
Is a potentially-evaluated expression in a template definition a “use?”

Must f() be defined to make this program well-formed? The
current wording of 6.2 [basic.def.odr] does not make any special
provision for expressions that appear only in uninstantiated template
definitions.

2240.
this is not odr-used in a constant expression

this is odr-used if it appears as a potentially-evaluated
expression (including as the result of the implicit transformation in the
body of a non-static member function (12.2.2 [class.mfct.non-static])).

This wording does not distinguish between constant and non-constant
expressions in determining whether this is odr-used or not.

2353.
Potential results of a member access expression for a static data member

2009.
Unclear specification of class scope

Point 2 of the rules of class scope in 6.3.7 [basic.scope.class]
paragraph 1 says,

A name N used in a class S shall refer to
the same declaration in its context and when re-evaluated in
the completed scope of S. No diagnostic is required
for a violation of this rule.

It is not clear that this provision does not apply to
names appearing in function bodies, default arguments,
exception-specifications, and
brace-or-equal-initializers. It is also not clear
what it means to “re-evaluate” a name.

One possible approach to this problem would be to say
that all names declared in a class are visible throughout
the class and simply make it ill-formed to refer to a
name that has not been declared yet in the contexts in
which that is problematic, such as types and template
arguments.

In addition, the fourth point says,

A name declared within a member function hides a declaration
of the same name whose scope extends to or past the end of
the member function's class.

This rule is unneeded, as it simply restates the normal
hiding rule in 6.3.1 [basic.scope.declarative] paragraph 1:

The scope of a declaration is the same as its potential
scope unless the potential scope contains another
declaration of the same name. In that case, the potential
scope of the declaration in the inner (contained)
declarative region is excluded from the scope of the
declaration

191.
Name lookup does not handle complex nesting

The current description of unqualified name lookup in
6.4.1 [basic.lookup.unqual]
paragraph 8 does
not correctly handle complex cases of nesting. The Standard
currently reads,

A name used in the definition of a function that is a member function
(9.3) of a class X shall be declared in one of the following
ways:

before its use in the block in which it is used or in an enclosing
block (6.3), or

shall be a member of class X or be a member of a base
class of X (10.2), or

if X is a nested class of class Y (9.7), shall
be a member of Y, or shall be a member of a base class of
Y (this lookup applies in turn to Y's enclosing
classes, starting with the innermost enclosing class), or

if X is a local class (9.8) or is a nested class of a
local class, before the definition of class X in a block
enclosing the definition of class X, or

if X is a member of namespace N, or is a nested
class of a class that is a member of N, or is a local class
or nested class within a local class of a function that is a member of
N, before the member function definition, in namespace
N or in one of N's enclosing namespaces.

In particular, this formulation does not handle the following example:

Here the reference to i is from a member function of a local
class of a member function of a nested class. Nothing in the rules
allows outer::i to be found, although intuitively it should
be found.

A more comprehensive formulation is needed that allows traversal of
any combination of blocks, local classes, and nested classes.
Similarly, the final bullet needs to be augmented so that a function
need not be a (direct) member of a namespace to allow searching that
namespace when the reference is from a member function of a class
local to that function. That is, the current rules do not allow the
following example:

405.
Unqualified function name lookup

There seems to be some confusion in the Standard regarding the
relationship between 6.4.1 [basic.lookup.unqual] (Unqualified name
lookup) and 6.4.2 [basic.lookup.argdep]
(Argument-dependent lookup). For example,
6.4.1 [basic.lookup.unqual] paragraph 3 says,

The lookup for an unqualified name used as the
postfix-expression of a function call is described in
6.4.2 [basic.lookup.argdep].

In other words, nothing in 6.4.1 [basic.lookup.unqual]
applies to function names; the entire lookup is described in
6.4.2 [basic.lookup.argdep].

6.4.2 [basic.lookup.argdep] does not appear to share this
view of its responsibility.
The closest it comes is in 6.4.2 [basic.lookup.argdep] paragraph 2a:

...the set of declarations found by the lookup of the function
name is the union of the set of declarations found using ordinary
unqualified lookup and the set of declarations found in the namespaces
and classes associated with the argument types.

Presumably, "ordinary unqualified lookup" is a reference
to the processing described in
6.4.1 [basic.lookup.unqual], but, as noted above,
6.4.1 [basic.lookup.unqual]
explicitly precludes applying that processing to function names. The
details of "ordinary unqualified lookup" of function names
are not described anywhere.

The other clauses that reference
6.4.2 [basic.lookup.argdep], clauses
16 [over] and 17 [temp], are
split over the question of the relationship between
6.4.1 [basic.lookup.unqual] and 6.4.2 [basic.lookup.argdep].
16.3.1.1.1 [over.call.func] paragraph 3, for instance, says

The name is looked up in the context of the function call
following the normal rules for name lookup in function calls
(6.4.2 [basic.lookup.argdep]).

I.e., this reference assumes that
6.4.2 [basic.lookup.argdep] is self-contained. The
same is true of 16.3.1.2 [over.match.oper] paragraph 3,
second bullet:

The set of non-member candidates is the result of the
unqualified lookup of operator@ in the context of the expression
according to the usual rules for name lookup in unqualified function
calls (6.4.2 [basic.lookup.argdep]), except that all member
functions are ignored.

On the other hand, however, 17.7.4.2 [temp.dep.candidate]
paragraph 1 explicitly assumes that
6.4.1 [basic.lookup.unqual] and 6.4.2 [basic.lookup.argdep] are
both involved in function name lookup and do different things:

For a function call that depends on a template parameter, if
the function name is an unqualified-id but not a
template-id, the candidate functions are found using the usual
lookup rules (6.4.1 [basic.lookup.unqual],
6.4.2 [basic.lookup.argdep]) except that:

For the part of the lookup using unqualified name lookup
(6.4.1 [basic.lookup.unqual]),
only function declarations with external linkage from the template
definition context are found.

For the part of the lookup using associated
namespaces (6.4.2 [basic.lookup.argdep]),
only function declarations with external linkage found in either the
template definition context or the template instantiation context are
found.

Suggested resolution:

Change 6.4.1 [basic.lookup.unqual] paragraph 1 from

...name lookup ends as soon as a declaration is found for the
name.

to

...name lookup ends with the first scope containing one or more
declarations of the name.

Change the first sentence of 6.4.1 [basic.lookup.unqual]
paragraph 3 from

The lookup for an unqualified name used as the
postfix-expression of a function call is described in
6.4.2 [basic.lookup.argdep].

to

An unqualified name used as the postfix-expression of a
function call is looked up as described below. In addition,
argument-dependent lookup (6.4.2 [basic.lookup.argdep]) is
performed on this name to
complete the resulting set of declarations.

1200.
Lookup rules for template parameters

Although 6.3.9 [basic.scope.temp] now describes the scope of a
template parameter, the description of unqualified name lookup in
6.4.1 [basic.lookup.unqual] do not cover uses of template parameter
names. The note in 6.4.1 [basic.lookup.unqual] paragraph 16 says,

the rules for name lookup in template definitions are described in
17.7 [temp.res].

but the rules there cover dependent and non-dependent names, not
template parameters themselves.

Which A is referenced in the last line? According to
6.4.3 [basic.lookup.qual] paragraph 1,

If a :: scope resolution operator in
a nested-name-specifier is not preceded by
a decltype-specifier, lookup of the name preceding that
:: considers only namespaces, types, and templates whose
specializations are types.

It is not clear whether this applies to the example or not,
and the interpretation of the < token depends on the
result of the lookup.

Notes from the September, 2013 meeting:

The restricted lookup mentioned in 6.4.3 [basic.lookup.qual]
paragraph 1 is based on a one-token lookahead; because the next
token following A in the example is not ::,
the restricted lookup does not apply, and the result is ambiguous.
Uncommenting the template keyword in the example does not
affect the lookup.

562.
qualified-ids in non-expression contexts

Both 6.4.3.1 [class.qual] and 6.4.3.2 [namespace.qual]
specify that some lookups are to be performed “in the context of the
entire postfix-expression,” ignoring the fact that
qualified-ids can appear outside of expressions.

It was suggested in document J16/05-0156 = WG21 N1896 that these
uses be changed to “the context in which the qualified-id
occurs,” but it isn't clear that this formulation adequately
covers all the places a qualified-id can occur.

James Kanze: S::p cannot be defined, because to
do so requires a type specifier and the type cannot be named.
::y is valid C because C only requires compatible, not
identical, types. In C++, it appears that there is a new type in
each declaration, so it would not be valid. This differs from
S::x because the unnamed type is part of a named type
— but I don't know where or if the Standard says that.

John Max Skaller:
It's not valid C++, because the type is a synthesised, unique name
for the enumeration type which differs across translation units, as if:

extern enum _synth1 { d,e,f} y;
..
extern enum _synth2 { d,e,f} y;

had been written.

However, within a class, the ODR implies the types are the same:

class X { enum { d } y; };

in two translation units ensures that the type of member y
is the same: the two X's obey the ODR and so denote the same class,
and it follows that there's only one member y and one type that it
has.

338.
Enumerator name with linkage used as class name in other translation unit

However, 6.5 [basic.link] paragraph 9 seems to say
these two declarations
cannot appear in two different translation units. That also
would mean that the inclusion of a header containing the above
in two different translation units is not valid C++.

I suspect this is an oversight and that users should be allowed
to have the declarations above appear in different translation
units. (It is a fairly common thing to do, I think.)

I don't remember why enumerators were given linkage; I don't
think it's necessary for mangling non-type template arguments.
In any event, I can't think why cross-TU name collisions between
enumerators and other entities would cause a problem, so I guess
a change here would be okay. I can think of three changes that
would have that effect:

Saying that enumerators do not have linkage.

Removing enumerators from the list of entities in the first
sentence of 6.5 [basic.link] paragraph 9.

Saying that it's okay for an enumerator in one TU to have the
same name as a class type in another TU only if the enumerator
hides that same class type in both TUs (the example you gave).

Daveed Vandevoorde:
I don't think any of these are sufficient in the sense that the problem
isn't limited to enumerators. E.g.:

struct X;
extern void X();

shouldn't create cross-TU collisions either.

Mike Miller:
So you're saying that cross-TU collisions should only be
prohibited if both names denote entities of the same kind (both
functions, both objects, both types, etc.), or if they are both
references (regardless of what they refer to, presumably)?

Daveed Vandevoorde:
Not exactly. Instead, I'm saying that if two entities (with
external linkage) can coexist when they're both declared in the
same translation unit (TU), then they should also be allowed to
coexist when they're declared in two different translation units.

For example:

int i;
void i(); // Error

This is an error within a TU, so I don't see a reason to make it
valid across TUs.

However, "tag names" (class/struct/union/enum) can sometimes
coexist with identically named entities (variables, functions &
enumerators, but not namespaces, templates or type names).

371.
Interleaving of constructor calls

Is a compiler allowed to interleave constructor calls when
performing dynamic initialization of nonlocal objects?
What I mean by interleaving is: beginning to execute a
particular constructor, then going off and doing
something else, then going back to the original constructor.
I can't find anything explicit about this in clause
6.6.2 [basic.start.static].

I'll present a few different examples, some of which get a
bit wild. But a lot of what this comes down to is exactly
what the standard means when it talks about the order
of initialization. If it says that some object x must be
initialized before a particular event takes place, does that
mean that x's constructor must be entered before that
event, or does it mean that it must be exited before that
event? If object x must be initialized before object y,
does that mean that x's constructor must exit before y's
constructor is entered?

(The answer to that question might just be common sense,
but I couldn't find an answer in clause 6.6.2 [basic.start.static].
Actually, when I read 6.6.2 [basic.start.static]
carefully, I find there are a lot of things I took
for granted that aren't there.)

OK, so a few specific scenerios.

We have a translation unit with nonlocal objects A and B,
both of which require dynamic initialization. A comes before
B. A must be initialized before B. May the compiler start
to construct A, get partway through the constructor, then
construct B, and then go back to finishing A?

We have a translation unit with nonlocal object A and
function f. Construction of A is deferred until after the
first statement of main. A must be constructed before the
first use of f. Is the compiler permitted to start constructing
A, then execute f, then go back to constructing A?

We have nonlocal objects A and B, in two different
translation units. The order in which A and B are constructed
is unspecified by the Standard. Is the compiler permitted to
begin constructing A, then construct B, then finish A's
constructor? Note the implications of a 'yes' answer. If A's
and B's constructor both call some function f, then the call
stack might look like this:

The implication of a 'yes' answer for users is that any function
called by a constructor, directly or indirectly, must be reentrant.

This last example is to show why a 'no' answer to #3 might
be a problem too. New scenerio: we've got one translation
unit containing a nonlocal object A and a function f1, and another
translation unit containing a nonlocal object B and a function f2.
A's constructor calls f2. Initialization of A and B is deferred until
after the first statement of main(). Someone in main calls f1.
Question: is the compiler permitted to start constructing A, then
go off and construct B at some point before f2 gets called, then
go back and finish constructing A? In fact, is the compiler
required to do that? We've got an unpleasant tension here between
the bad implications of a 'yes' answer to #3, and the explicit
requirement in 6.6.2 [basic.start.static] paragraph 3.

At this point, you might be thinking we could avoid all of this
nonsense by removing compilers' freedom to defer initialization
until after the beginning of main(). I'd resist that, for two reasons.
First, it would be a huge change to make after the standard has
been out. Second, that freedom is necessary if we want to have
support for dynamic libraries. I realize we don't yet say anything
about dynamic libraries, but I'd hate to make decisions that would
make such support even harder.

1659.
Initialization order of thread_local template static data members

It is implementation-defined whether the dynamic initialization of a
non-local variable with static or thread storage duration is done before
the first statement of the initial function of the thread. If the
initialization is deferred to some point in time after the first statement
of the initial function of the thread, it shall occur before the first
odr-use (6.2 [basic.def.odr]) of any variable with thread storage
duration defined in the same translation unit as the variable to be
initialized.

This doesn't consider that initialization of instantiations of static
data members of class templates (which can be thread_local) are
unordered. Presumably odr-use of such a static data member should not
trigger the initialization of any thread_local variable other than
that one?

640.
Accessing destroyed local objects of static storage duration

If a function contains a local object of static storage duration
that has been destroyed and the function is called during the
destruction of an object with static storage duration, the
program has undefined behavior if the flow of control passes
through the definition of the previously destroyed local object.

I would like to turn this behavior from undefined to
well-defined behavior for the purpose of achieving a graceful
shutdown, especially in a multi-threaded world.

Background: Alexandrescu describes the “phoenix
singleton” in Modern C++ Design. This is a class
used as a function local static, that will reconstruct itself,
and reapply itself to the atexit chain, if the program
attempts to use it after it is destructed in the atexit
chain. It achieves this by setting a “destructed
flag” in its own state in its destructor. If the object is
later accessed (and a member function is called on it), the
member function notes the state of the “destructed
flag” and does the reconstruction dance. The phoenix
singleton pattern was designed to address issues only in
single-threaded code where accesses among static objects can have
a non-scoped pattern. When we throw in multi-threading, and the
possibility that threads can be running after main
returns, the chances of accessing a destroyed static
significantly increase.

The very least that I would like to see happen is to standardize what
I believe is existing practice: When an object is destroyed in the
atexit chain, the memory the object occupied is left in
whatever state the destructor put it in. If this can only be
reliably done for objects with standard layout, that would be an
acceptable compromise. This would allow objects to set “I'm
destructed” flags in their state and then do something
well-defined if accessed, such as throw an exception.

A possible refinement of this idea is to have the compiler set
up a 3-state flag around function-local statics instead of the
current 2-state flag:

Not constructed yet

Constructed but not destroyed yet

Destroyed

We have the first two states today. We might choose to add
the third state, and if execution passes over a function-local
static with “destroyed” state, an exception could be
thrown. This would mean that we would not have to guarantee
memory stability in destroyed objects of static duration.

This refinement would break phoenix singletons, and is not
required for the ~mutex()/~condition() I've
described and prototyped. But it might make it easier for Joe
Coder to apply this kind of guarantee to his own types.

365.
Storage duration and temporaries

6.7 [basic.stc] paragraph 2 says that "Static and automatic
storage durations are associated with objects introduced by
declarations (6.1 [basic.def]) and implicitly created
by the implementation (15.2 [class.temporary])."

In fact, objects "implicitly created by the implementation" are the
temporaries described in (15.2 [class.temporary]), and have neither
static nor automatic storage duration, but a totally different duration,
described in 15.2 [class.temporary].

6.7 [basic.stc] uses the expression "local object" in several
places, without ever defining it. Presumably, what is meant is "an
object declared at block scope", but this should be said explicitly.

In a recent discussion in comp.lang.c++.moderated, on poster
interpreted "local objects" as including temporaries. This would require them
to live until the end of the block in which they are created, which
contradicts 15.2 [class.temporary]. If temporaries are covered by
this section, and the statement in 6.7 [basic.stc]
seems to suggest, and they aren't local objects, then they must have
static storage duration, which isn't right either.

I propose adding a fourth storage duration to the list after
6.7 [basic.stc] paragraph 1:

temporary storage duration

And rewriting the second paragraph of this section as follows:

Temporary storage duration is associated with objects implicitly
created by the implementation, and is described in 15.2 [class.temporary].
Static and automatic storage durations are associated with objects defined
by declarations; in the following, an object defined by a declaration
with block scope is a local object. The dynamic storage duration is
associated with objects created by the operator new.

Steve Adamczyk:
There may well be an issue here, but one should bear in mind the
difference between storage duration and object lifetime. As far
as I can see, there is no particular problem with temporaries having
automatic or static storage duration, as appropriate. The point
of 15.2 [class.temporary] is that they have an unusual object
lifetime.

Notes from Ocrober 2002 meeting:

It might be desirable to shorten the storage duration of temporaries
to allow reuse of them. The as-if rule allows some reuse, but such
reuse requires analysis, including noting whether the addresses of
such temporaries have been taken.

Notes from the August, 2011 meeting:

The CWG decided that further consideration of this issue would be
deferred until someone produces a paper explaining the need for action
and proposing specific changes.

Requirements for allocation functions are given in
6.7.4.1 [basic.stc.dynamic.allocation] paragraph 1:

An allocation function can be a function template. Such a template shall
declare its return type and first parameter as specified above (that is,
template parameter types shall not be used in the return type and first
parameter type). Template allocation functions shall have two or more
parameters.

There are a couple of problems with this description. First, it is
instances of function templates that can be allocation functions, not
the templates themselves (cf 6.7.4.2 [basic.stc.dynamic.deallocation] paragraph 2,
which uses the correct terminology regarding deallocation functions).

More importantly, this specification was written before template
metaprogramming was understood and hence prevents use of SFINAE on the
return type or parameter type to select among function template
specializations. (The parallel passage for deallocation functions in
6.7.4.2 [basic.stc.dynamic.deallocation] paragraph 2 shares this deficit.)

523.
Can a one-past-the-end pointer be invalidated by deleting an adjacent object?

When an object is deleted, 6.7.4.2 [basic.stc.dynamic.deallocation] says
that the deallocation “[renders] invalid all pointers referring
to any part of the deallocated storage.” According to
6.9.2 [basic.compound] paragraph 3, a pointer whose address is
one past the end of an array is considered to point to an unrelated
object that happens to reside at that address. Does this need to be
clarified to specify that the one-past-the-end pointer of an array is
not invalidated by deleting the following object? (See also
8.3.5 [expr.delete] paragraph 4, which also mentions that
the system deallocation function renders a pointer invalid.)

419.
Can cast to virtual base class be done on partially-constructed object?

Core issue 52 almost, but not quite,
says that in evaluating "this->x"
you do a cast to the virtual base class A, which would be an error
according to 15.7 [class.cdtor] paragraph 2 because the base
class B constructor hasn't started yet.
8.2.5 [expr.ref] should be clarified to say that
the cast does need to get done.

James Kanze submitted the same issue via comp.std.c++
on 11 July 2003:

Richard Smith:
Nonsense. You can use "this" perfectly happily in a constructor, just
be careful that (a) you're not using any members that are not fully
initialised, and (b) if you're calling virtual functions you know
exactly what you're doing.

In practice, and I think in intent, you are right. However, the
standard makes some pretty stringent restrictions in
6.8 [basic.life]. To start
with, it says (in paragraph 1):

The lifetime of an object is a runtime property of the object. The
lifetime of an object of type T begins when:

storage with the proper alignment and size for type T is
obtained, and

if T is a class type with a non-trivial constructor, the
constructor calls has COMPLETED.

The lifetime of an object of type T ends when:

if T is a class type with a non-trivial destructor, the
destructor call STARTS, or

the storage which the object occupies is reused or released.

(Emphasis added.) Then when we get down to paragraph 5, it says:

Before the lifetime of an object has started but after the storage
which the object will occupy has been allocated [which sounds to me
like it would include in the constructor, given the text above] or,
after the lifetime of an object has ended and before the storage
which the object occupied is reused or released, any pointer that
refers to the storage location where the object will be or was
located may be used but only in limited ways. [...] If the object
will be or was of a non-POD class type, the program has undefined
behavior if:

[...]

the pointer is implicitly converted to a pointer to a base class
type, or [...]

I can't find any exceptions for the this pointer.

Note that calling a non-static function in the base class, or even
constructing the base class in initializer list, involves an implicit
conversion of this to a pointer to the base class. Thus undefined
behavior. I'm sure that this wasn't the intent, but it would seem to be
what this paragraph is saying.

350.
signed char underlying representation for objects

Yes, and to add to this tangent, 6.9.1 [basic.fundamental]
paragraph 1 states "Plain char, signed char, and unsigned char are
three distinct types." Strangely, 6.9 [basic.types]
paragraph 2 talks about how "... the underlying bytes making up
the object can be copied into an array of char or unsigned char.
If the content of the array of char or unsigned char is copied back
into the object, the object shall subsequently hold its original
value." I guess there's no requirement that this copying
work properly with signed chars!

Notes from October 2002 meeting:

We should do whatever C99 does. 6.5p6 of the C99 standard says
"array of character type", and "character type" includes signed
char (6.2.5p15), and 6.5p7 says "character type".
But see also 6.2.6.1p4, which mentions (only) an array of unsigned char.

Proposed resolution (April 2003):

Change 6.8 [basic.life] paragraph 5 bullet 3 from

the pointer is used as the operand of a
static_cast
(8.2.9 [expr.static.cast])
(except when the conversion is to
void*,
or to
void*
and subsequently to
char*,
or
unsignedchar*).

to

the pointer is used as the operand of a
static_cast
(8.2.9 [expr.static.cast])
(except when the conversion is to
void*,
or to
void*
and subsequently to a pointer to byte-character type).

Change 6.8 [basic.life] paragraph 6 bullet 3 from

the lvalue is used as the operand of a
static_cast
(8.2.9 [expr.static.cast])
(except when the conversion is ultimately to
char&
or
unsignedchar&),
or

to

the lvalue is used as the operand of a
static_cast
(8.2.9 [expr.static.cast])
(except when the conversion is ultimately to a reference to
byte-character type),
or

Change the beginning of 6.9 [basic.types] paragraph 2 from

For any object (other than a base-class subobject) of POD type
T,
whether or not the object holds a valid value of type
T,
the underlying bytes (4.4 [intro.memory])
making up the object can be copied
into an array of
char
or
unsignedchar.

to

For any object (other than a base-class subobject) of POD type
T,
whether or not the object holds a valid value of type
T,
the underlying bytes (4.4 [intro.memory])
making up the object can be copied
into an array of byte-character type.

Add the indicated text to 6.9.1 [basic.fundamental] paragraph 1:

Objects declared as characters
(char)
shall be large enough to store any member of
the implementation's basic character set.
If a character from this set is stored in a character object,
the integral value of that character object
is equal to
the value of the single character literal form of that character.
It is implementation-defined whether a
char
object can hold negative values.
Characters can be explicitly declared
unsigned
or
signed.
Plain
char,
signed char,
and
unsigned char
are three distinct types, called the byte-character types.
A
char,
a
signed char,
and an
unsigned char
occupy the same amount of storage and have the same alignment requirements
(6.9 [basic.types]); that is, they have the
same object representation.
For byte-character types, all bits of the object representation participate in
the value representation.
For unsigned byte-character types, all possible bit
patterns of the value representation represent numbers.
These requirements
do not hold for other types.
In any particular implementation, a plain
char
object can take on either the same values as a
signed char
or an
unsigned char;
which one is implementation-defined.

Change 6.10 [basic.lval] paragraph 15 last bullet from

a
char
or
unsignedchar
type.

to

a byte-character type.

Notes from October 2003 meeting:

It appears that in C99 signed char may have padding bits but no trap
representation, whereas in C++ signed char has no padding bits but
may have -0. A memcpy in C++ would have to copy the array preserving
the actual representation and not just the value.

March 2004: The liaisons to the C committee have been asked to tell us
whether this change would introduce any unnecessary incompatibilities
with C.

Notes from October 2004 meeting:

The C99 Standard appears to be inconsistent in its
requirements. For example, 6.2.6.1 paragraph 4 says:

The value may be copied into an object of type
unsigned char [n] (e.g., by
memcpy); the resulting set of bytes is called the
object representation of the value.

On the other hand, 6.2 paragraph 6 says,

If a value is copied into an object having no declared type using
memcpy or memmove, or is copied as an array of
character type, then the effective type of the modified object
for that access and for subsequent accesses that do not modify
the value is the effective type of the object from which the
value is copied, if it has one.

Mike Miller will investigate further.

Proposed resolution (February, 2010):

Change 6.8 [basic.life] paragraph 5 bullet 4 as
follows:

...The program has undefined behavior if:

...

the pointer is used as the operand of a
static_cast (8.2.9 [expr.static.cast]) (except when
the conversion is to cvvoid*, or to
cvvoid* and subsequently to
char*, or unsigned char*a
pointer to a cv-qualified or cv-unqualified byte-character type
(6.9.1 [basic.fundamental])), or

...

Change 6.8 [basic.life] paragraph 6 bullet 4 as
follows:

...The program has undefined behavior if:

...

the lvalue is used as the operand of a
static_cast (8.2.9 [expr.static.cast]) except when the
conversion is ultimately to cvchar& or
cvunsigned char&a reference to a
cv-qualified or cv-unqualified byte-character type (6.9.1 [basic.fundamental]) or an array thereof, or

...

Change 6.9 [basic.types] paragraph 2 as follows:

For any object (other than a base-class subobject) of trivially
copyable type T, whether or not the object holds a valid
value of type T, the underlying bytes (4.4 [intro.memory]) making up the object can be copied into an array of
char or unsigned chara
byte-character type (6.9.1 [basic.fundamental]).39 If the content of
thethat array of char or
unsigned char is copied back into the object, the
object shall subsequently hold its original
value. [Example:...

Change 6.9.1 [basic.fundamental] paragraph 1 as follows:

...Characters can be explicitly declared unsigned or
signed. Plain char, signed char, and
unsigned char are three distinct types, called the
byte-character types. A char, a signed
char, and an unsigned char occupy the same amount
of storage and have the same alignment requirements (6.11 [basic.align]); that is, they have the same object
representation. For byte-character types, all bits of
the object representation participate in the value
representation. For unsigned character typesunsigned char, all possible bit patterns of
the value representation represent numbers...

Change 6.10 [basic.lval] paragraph 15 final bullet
as follows:

If a program attempts to access the stored value of an object
through an lvalue of other than one of the following types the
behavior is undefined 52

The alignment requirement of a complete type can be queried using
an alignof expression (8.3.6 [expr.alignof]).
Furthermore, the byte-character types
(6.9.1 [basic.fundamental])char,
signed char, and unsigned char shall have
the weakest alignment requirement. [Note: this enables
the byte-character types to be used as the underlying
type for an aligned memory area (10.6.2 [dcl.align]). —end note]

Change 8.3.4 [expr.new] paragraph 10 as follows:

...For arrays of char and unsigned
chara byte-character type (6.9.1 [basic.fundamental]), the difference between the result of the
new-expression and the address returned by the allocation
function shall be an integral multiple of the strictest
fundamental alignment requirement (6.11 [basic.align]) of
any object type whose size is no greater than the size of the
array being created. [Note: Because allocation functions
are assumed to return pointers to storage that is appropriately
aligned for objects of any type with fundamental alignment, this
constraint on array allocation overhead permits the common idiom
of allocating byte-character arrays into which objects
of other types will later be placed. —end note]

Notes from the March, 2010 meeting:

The CWG was not convinced that there was a need to change the
existing specification at this time. Some were concerned that there
might be implementation difficulties with giving signed char
the requisite semantics; implementations for which that is true can
currently make char equivalent to unsigned char and
avoid those problems, but the suggested change would undermine that
strategy.

Additional note, November, 2014:

There is now the term “narrow character type” that
should be used instead of “byte-character type”.

146.
Floating-point zero

6.9.1 [basic.fundamental]
does not impose
a requirement on the floating point types that there be an exact
representation of the value zero. This omission is significant in
7.13 [conv.fctptr]
paragraph 1, in which any
non-zero value converts to the bool value true.

Suggested resolution: require that all floating point types have an
exact representation of the value zero.

689.
Maximum values of signed and unsigned integers

The relationship between the values representable by corresponding
signed and unsigned integer types is not completely described, but
6.9 [basic.types] paragraph 4 says,

The value representation of an object is the set of bits that
hold the value of type T.

and 6.9.1 [basic.fundamental] paragraph 3 says,

The range of nonnegative values of a signed integer type is a
subrange of the corresponding unsigned integer type, and the
value representation of each corresponding signed/unsigned type
shall be the same.

I.e., the maximum value of each unsigned type must be larger
than the maximum value of the corresponding signed type.

For signed integer types, the bits of the object representation
shall be divided into three groups: value bits, padding bits, and
the sign bit. There need not be any padding bits; there shall be
exactly one sign bit. Each bit that is a value bit shall have the
same value as the same bit in the object representation of the
corresponding unsigned type (if there are M value bits in the
signed type and N in the unsigned type, then M <= N).

Unlike C++, the sign bit is not part of the value, and on an
architecture that does not have native support of unsigned types,
an implementation can emulate unsigned integers by simply
ignoring what would be the sign bit in the signed type and be
conforming.

The question is whether we intend to make a conforming
implementation on such an architecture impossible. More
generally, what range of architectures do we intend to
support? And to what degree do we want to follow C99 in
its evolution since C89?

2354.
Extended alignment and object representation

The Standard does not appear to indicate whether padding bits are added
to the object representation for an enumeration or not, affecting the
result of sizeof and the alignment of the array elements.

If the extended alignment does not affect the object representation of
the type, it would be useful to specify that the array declaration is
ill-formed because it requires violating the alignment requirement (and
similarly for an array new-expression where the bound is known at
compile time).

2133.
Converting std::nullptr_t to bool

For direct-initialization (11.6 [dcl.init]), a
prvalue of type std::nullptr_t can be converted to a prvalue
of type bool; the resulting value is false.

The mention of direct-initialization in this context (added by
issue 1423) seems odd; standard
conversions are on a level below initialization. Should this
wording be moved to 11.6 [dcl.init], perhaps as a
bullet in paragraph 1?

1642.
Missing requirements for prvalue operands

The discussion of each built-in operator in Clause
8 [expr] indicates the category of the value
it yields and the value categories of the operands it
expects

in fact, many of the operators that take prvalue operands
do not make that requirement explicit. Possible approaches
to address this failure could be a blanket statement that an
operand whose value category is not stated is assumed to be
a prvalue; adding prvalue requirements to each operand
description for which it is missing; or changing the
description of the usual arithmetic conversions to state
that they imply the lvalue-to-rvalue conversion, which would
cover the majority of the omissions.

(See also issue 1685, which deals with
an inaccurately-specified value category.)

1632.
Lambda capture in member initializers

A lambda-expression whose smallest enclosing scope is a block scope
(6.3.3 [basic.scope.block]) is a local lambda expression; any
other lambda-expression shall not have a capture-list in
its lambda-introducer. The reaching scope of a local lambda
expression is the set of enclosing scopes up to and including the innermost
enclosing function and its parameters.

Consequently, lambdas appearing in mem-initializers and
brace-or-equal-initializers cannot have a capture-list.
However, these expressions are evaluated in the context of the
constructor and are permitted to access this and
non-static data members.

Should the definition of a local lambda be modified to permit
capturing lambdas within these contexts?

Notes from the April, 2013 meeting:

CWG agreed with the intent of this issue.

1822.
Lookup of parameter names in lambda-expressions

According to 8.1.5 [expr.prim.lambda] paragraph 7, names
appearing in the compound-statement of a
lambda-expression are looked up in the context of the
lambda-expression, ignoring the fact that the
compound-statement will be transformed into the body of
the closure type's function operator. This leaves unspecified
how the lambda-expression's parameters are found by
name lookup. Presumably the parameters hide the corresponding
names from the surrounding scope, but this needs to be specified.

2347.
Passing short scoped enumerations to ellipsis

If the argument has integral or enumeration type that is subject to the
integral promotions (7.6 [conv.prom]), or a floating-point type
that is subject to the floating-point promotion (7.7 [conv.fpprom]),
the value of the argument is converted to the promoted type before the
call. These promotions are referred to as the default argument promotions.

A scoped enumeration with an underlying type that is shorter than
int will not be widened when passed to an ellipsis. Should it
be?

2351.
void{}

If the initializer is a parenthesized single expression, the type
conversion expression is equivalent to the corresponding cast expression
(8.4 [expr.cast]). Otherwise, if the type is cvvoid and the initializer is () , the expression is a
prvalue of the specified type that performs no initialization. Otherwise,
the expression is a prvalue of the specified type whose result object is
direct-initialized (11.6 [dcl.init]) with the initializer. For an
expression of the form T(), T shall not be an array type.

It seems an oversight that void{} is not treated like
void().

742.
Postfix increment/decrement with long bit-field operands

the expressions s.sll-- < 0u and s.sll < 0u
have different results. The reason for this is that s.sll--
is an rvalue of type signed long long (8.2.6 [expr.post.incr]), which means that the usual arithmetic conversions
(8 [expr] paragraph 10) convert 0u to
signed long long and the result is true.
s.sll, on the other hand, is a bit-field lvalue, which is
promoted (7.6 [conv.prom] paragraph 3) to int; both
operands of < have the same rank, so s.sll is
converted to unsigned int to match the type of 0u
and the result is false. This disparity seems
undesirable.

282.
Namespace for extended_type_info

The original proposed resolution for issue 160
included changing extended_type_info
(8.2.8 [expr.typeid] paragraph 1, footnote 61) to
std::extended_type_info. There was no consensus on whether
this name ought to be part of namespace std or in a
vendor-specific namespace, so the question was moved into a
separate issue.

528.
Why are incomplete class types not allowed with typeid?

When typeid is applied to a type-id, the result refers
to a std::type_info object representing the type of
the type-id. If the type of the type-id is a reference
type, the result of the typeid expression refers to
a std::type_info object representing the referenced type. If
the type of the type-id is a class type or a reference to a
class type, the class shall be completely-defined.

I'm wondering whether this is not overly restrictive. I can't
think of a reason to require that T be completely-defined
in typeid(T) when T is a class type. In fact,
several popular compilers enforce that restriction
for typeid(T), but not for typeid(T&). Can
anyone explain this?

Nathan Sidwell: I think this restriction is so that whenever
the compiler has to emit a typeid object of a class type, it knows
what the base classes are, and can therefore emit an array of
pointers-to-base-class typeids. Such a tree is necessary to implement
dynamic_cast and exception catching (in a commonly
implemented and obvious manner). If the class could be incomplete,
the compiler might have to emit a typeid for incomplete Foo
in one object file and a typeid for complete Foo in another
object file. The compilation system will then have to make sure that
(a) those compare equal and (b) the complete Foo gets
priority, if that is applicable.

Unfortunately, there is a problem with exceptions that means there
still can be a need to emit typeids for incomplete class. Namely one
can throw a pointer-to-pointer-to-incomplete. To implement the
matching of pointer-to-derived being caught by pointer-to-base, it is
necessary for the typeid of a pointer type to contain a pointer to the
typeid of the pointed-to type. In order to do the qualification
matching on a multi-level pointer type, one has a chain of pointer
typeids that can terminate in the typeid of an incomplete type. You
cannot simply NULL-terminate the chain, because one must distinguish
between different incomplete types.

Dave Abrahams: So if implementations are still required to
be able to do it, for all practical purposes, why aren't we letting
the user have the benefits?

Notes from the April, 2006 meeting:

There was some concern expressed that this might be difficult under
the IA64 ABI. It was also observed that while it is necessary to
handle exceptions involving incomplete types, there is no requirement
that the RTTI data structures be used for exception handling.

1954.
typeid null dereference check in subexpressions

If the glvalue expression is obtained by applying the
unary * operator to a pointer69 and the
pointer is a null pointer value (7.11 [conv.ptr]),
the typeid expression throws an exception
(18.1 [except.throw]) of a type that would match a
handler of type
std::bad_typeid exception (21.7.4 [bad.typeid]).

The footnote makes clear that this requirement applies without
regard to parentheses, but it is unspecified whether it applies when
the dereference occurs in a subexpression of the operand (e.g., in
the second operand of the comma operator or the second or third
operand of a conditional operator). There is implementation
divergence on this question.

However, this phrasing is problematic in the context of a
C-style cast like the following:

const void *p;
int *q = (int*)p;

The intent of 8.4 [expr.cast] is that this should be
interpreted as a static_cast followed by a
const_cast. However, because int* to
const void* is a valid standard conversion, and
8.2.9 [expr.static.cast] paragraph 7 allows static_cast
to perform the inverse of a standard conversion sequence, the
C-style cast is interpreted as just a static_cast without
a const_cast and is thus ill-formed.

1230.
Confusing description of ambiguity of destructor name

There is an ambiguity in the unary-expression~X(),
where X is a class-name or decltype-specifier.
The ambiguity is resolved in favor of treating ~ as a
unary complement rather than treating ~X as referring
to a destructor.

It is not clear whether this is intended to apply to an
expression like (~S)(). In large measure, that depends on
whether a class-name is an id-expression or not. If it
is, the ambiguity described in 8.3.1 [expr.unary.op] paragraph
10 does apply; if not, the expression is an unambiguous reference to
the destructor for class S. There are several places in the
Standard that indicate that the name of a type is an
id-expression, but that might be more confusing than helpful.

267.
Alignment requirement for new-expressions

Requirements for the alignment of pointers returned by
new-expressions are given in 8.3.4 [expr.new]
paragraph 10:

For arrays of char and unsigned char, the difference
between the result of the new-expression and the address
returned by the allocation function shall be an integral multiple of
the most stringent alignment requirement (6.9 [basic.types])
of any object type whose size is no greater than the size of the array
being created.

The intent of this wording is that the pointer returned by the
new-expression will be suitably aligned for any data type
that might be placed into the allocated storage (since the
allocation function is constrained to return a pointer to
maximally-aligned storage). However, there is an implicit
assumption that each alignment requirement is an integral multiple
of all smaller alignment requirements. While this is probably a
valid assumption for all real architectures, there's no reason
that the Standard should require it.

For example, assume that int has an alignment requirement
of 3 bytes and double has an alignment requirement of 4
bytes. The current wording only requires that a buffer that is big
enough for an int or a double be aligned on a 4-byte
boundary (the more stringent requirement), but that would allow the
buffer to be allocated on an 8-byte boundary — which might
not be an acceptable location for an int.

A similar assumption can be found in
8.2.10 [expr.reinterpret.cast] paragraph 7:

...converting an rvalue of type "pointer to T1" to the type
"pointer to T2" (where ... the alignment requirements of
T2 are no stricter than those of T1) and back to its
original type yields the original pointer value...

Suggested resolution: Change the wording to

...converting an rvalue of type "pointer to T1" to the type
"pointer to T2" (where ... the alignment requirements of
T1 are an integer multiple of those of T2)
and back to its original type yields the original pointer value...

473.
Block-scope declarations of allocator functions

Looking up operator new in a new-expression
uses a different mechanism from ordinary lookup. According to
8.3.4 [expr.new] paragraph 9,

If the new-expression begins with a unary ::
operator, the allocation function's name is looked up in the
global scope. Otherwise, if the allocated type is a class type
T or array thereof, the allocation function's name is
looked up in the scope of T. If this lookup fails to
find the name, or if the allocated type is not a class type, the
allocation function's name is looked up in the global scope.

Note in particular that the scope in which the
new-expression occurs is not considered. For example,

In this example, the implicit reference to operator
new(std::size_t) finds the global declaration, even though
the block-scope declaration of operator new with a
different signature would hide it from an ordinary reference.

This seems strange; either the block-scope declaration should
be ill-formed or it should be found by the lookup.

Notes from October 2004 meeting:

The CWG agreed that the block-scope declaration should not be
found by the lookup in a new-expression. It would,
however, be found by ordinary lookup if the allocation function
were invoked explicitly.

1628.
Deallocation function templates

According to 8.3.4 [expr.new] paragraphs 18-20, an
exception thrown during the initialization of an object allocated
by a new-expression will cause a deallocation
function to be called for the object's storage if a matching
deallocation function can be found. The rules deal only with
functions, however; nothing is said regarding a mechanism by which
a deallocation function template might be instantiated to free the
storage, although 6.7.4.2 [basic.stc.dynamic.deallocation] paragraph 2 indicates
that a deallocation function can be an instance of a function
template.

One possibility for this processing might be to perform template
argument deduction on any deallocation function templates; if there
is a specialization that matches the allocation function, by the
criteria listed in paragraph 20, that function template would be
instantiated and used, although a matching non-template function would
take precedence as is the usual outcome of overloading between
function template specializations and non-template functions.

There is a slightly related wording problem in
8.3.4 [expr.new] paragraph 21:

If a placement deallocation function is called, it is passed the same
additional arguments as were passed to the placement allocation function,
that is, the same arguments as those specified with
the new-placement syntax.

This wording ignores the possibility of default arguments in the
allocation function, in which case the arguments passed to the
deallocation function might be a superset of those specified in the
new-placement.

196.
Arguments to deallocation functions

8.3.4 [expr.new]
paragraph 10 says that
the result of an array allocation function and the value of the array
new-expression from which it was invoked may be different,
allowing for space preceding the array to be used for implementation
purposes such as saving the number of elements in the array. However,
there is no corresponding description of the relationship between the
operand of an array delete-expression and the argument passed
to its deallocation function.

6.7.4.2 [basic.stc.dynamic.deallocation]
paragraph 3 does state that

the value supplied to operator delete[](void*) in the
standard library shall be one of the values returned by a previous
invocation of either operator new[](std::size_t) or
operator new[](std::size_t, const std::nothrow_t&) in the
standard library.

This statement might be read as requiring an implementation, when
processing an array delete-expression and calling the
deallocation function, to perform the inverse of the calculation
applied to the result of the allocation function to produce the value
of the new-expression.
(8.3.5 [expr.delete]
paragraph 2 requires
that the operand of an array delete-expression "be the pointer
value which resulted from a previous array new-expression.")
However, it is not completely clear whether the "shall" expresses an
implementation requirement or a program requirement (or both).
Furthermore, there is no direct statement about user-defined
deallocation functions.

Suggested resolution: A note should be added to
8.3.5 [expr.delete]
to clarify that any
offset added in an array new-expression must be subtracted in
the array delete-expression.

2087.
Left shift of negative value by zero bits

A shift of zero bits should result in the left operand
regardless of its sign. However, the current wording of
8.8 [expr.shift] paragraph 2 makes it undefined
behavior.

Notes from the February, 2016 meeting:

CWG felt that a reasonable approach might be to
define <<N as equivalent to multiplying by
2N in all cases; see also the resolution of
issue 1457. The resolution of
this question should also be coordinated with SG6 and SG12,
as well as with WG14.

1256.
Unevaluated operands are not necessarily constant expressions

The current definition of constant expressions appears to make
unevaluated operands constant expressions; for example,
new char[10] would seem to be a constant expression if it
appears as the operand of sizeof. This seems wrong.

2192.
Constant expressions and order-of-eval undefined behavior

CWG did not wish to require implementations to detect this kind
of undefined behavior in determining whether an expression is constant
or not, but an implementation should be permitted to reject such
expressions. These should be indeterminately sequenced, not
unsequenced.

Value-initialization of the object created by B()
zero-initializes the object (11.6 [dcl.init] bullet 8.2),
which should mean that the ++x in the mem-initilizer
for A operates on a zero-initialized object, but current
implementations reject this code as non-constant. It is not clear what
in the current wording justifies this treatment.

2349.
Class/enumeration names vs conditions

A name introduced by a declaration in a condition (either introduced
by the decl-specifier-seq or the declarator of the condition)
is in scope from its point of declaration until the end of the
substatements controlled by the condition. If the name is redeclared in the
outermost block of a substatement controlled by the condition, the
declaration that redeclares the name is ill-formed.

This does not exempt class and enumeration names, which can ordinarily
coexist with non-type names in the same scope (6.3.10 [basic.scope.hiding]
paragraph 2). However, there is implementation variance in the handling
of examples like:

2344.
Redeclaration of names in init-statements

A name introduced by a declaration in a condition (either introduced by
the decl-specifier-seq or the declarator of the condition) is in
scope from its point of declaration until the end of the substatements
controlled by the condition. If the name is redeclared in the outermost
block of a substatement controlled by the condition, the declaration that
redeclares the name is ill-formed.

Should there be a similar rule about redeclaring names introduced
by init-statemwents?

2345.
Jumping across initializers in init-statements and conditions

If the condition (9.4 [stmt.select]) yields true the first
substatement is executed. If the else part of the selection
statement is present and the condition yields false, the second
substatement is executed. If the first substatement is reached via a label,
the condition is not evaluated and the second substatement is not executed.

Although 9.7 [stmt.dcl] paragraph 3 forbids bypassing a
declaration with initialization, a condition is not syntactically a
declaration, and the permission to jump into a then clause and the
statement that the condition “is not evaluated” could be read
to indicate that a jump across a condition with initialization is
permitted. Presumably the prohibition in 9.7 [stmt.dcl] would
apply to an init-statement, since it can be a declaration
syntactically, but one would expect the same restrictions to apply to both.

2348.
Non-templated constexpr if

The effect of constexpr if in non-templated code is primarily
limited to not requiring definitions for entities that are odr-used in
discarded statements. This eliminates a plausible implementation techique
of simply skipping the tokens of a discarded statement. Should the
Standard allow such an approach? One needed change might be to say that
all diagnosable rules become “no diagnostic required” inside
discarded statements.

2123.
Omitted constant initialization of local static variables

The zero-initialization (11.6 [dcl.init]) of all
block-scope variables with static storage duration
(6.7.1 [basic.stc.static]) or thread storage duration
(6.7.2 [basic.stc.thread]) is performed before any other
initialization takes place. Constant initialization
(6.6.2 [basic.start.static]) of a block-scope entity with
static storage duration, if applicable, is performed before
its block is first entered.

The fact that a variable need not be constant-initialized if its
block is not entered appears to allow inspection of the variable
after zero-initialization but before constant initialization:

Here, b may or may not have constant initialization,
but we don't have an ODR violation.

If we want to support such code, the nicest option would be
to say that the ODR requires us to act as if we pick one of the
definitions of the inline function, which requires us to make a
consistent choice for all static storage duration variables
within a given function. Alternatively, we could say that if
multiple definitions of a variable disagree over whether it has
constant initialization, then it does not, allowing more
implementation simplicity and no functional change outside of
pathological cases.

Notes from the February, 2016 meeting:

The second example will be dealt with separately under
issue 2242. For the first example,
the Standard should require that local types can be used outside
their function only via a returned object. It was still to be
decided whether this should be undefined behavior or an error
on use of such a type. It was also noted that the same issue can
arise with static member functions.

157.
Omitted typedef declarator

In a simple-declaration, the optional
init-declarator-list can be omitted only when... the
decl-specifier-seq contains either a class-specifier,
an elaborated-type-specifier with a class-key
(12.1 [class.name]
), or an
enum-specifier. In these cases and whenever a
class-specifier or enum-specifier is present in the
decl-specifier-seq, the identifiers in those specifiers are
among the names being declared by the declaration... In such cases,
and except for the declaration of an unnamed bit-field
(12.2.4 [class.bit]
), the
decl-specifier-seq shall introduce one or more names into the
program, or shall redeclare a name introduced by a previous
declaration. [Example:

enum { }; // ill-formed
typedef class { }; // ill-formed

—end example]

In the absence of any explicit restrictions in
10.1.3 [dcl.typedef]
, this paragraph appears
to allow declarations like the following:

In fact, the final example in
10 [dcl.dcl]
paragraph 3 would seem to
indicate that this is intentional: since it is illustrating the
requirement that the decl-specifier-seq must introduce a name
in declarations in which the init-declarator-list is omitted,
presumably the addition of a class name would have made the example
well-formed.

On the other hand, there is no good reason to allow such
declarations; the only reasonable scenario in which they might occur
is a mistake on the programmer's part, and it would be a service to
the programmer to require that such errors be diagnosed.

498.
Storage class specifiers in definitions of class members

I think I can deduce from the existing standard that the following
member definitions are ill-formed:

static void X::f() { }
static int X::n;

To come to that conclusion, however, I have to put together several
things in different parts of the standard. I would have expected to
find an explicit statement of this somewhere; in particular, I would
have expected to find it in 10.1.1 [dcl.stc]. I don't
see it there, or anywhere.

Gabriel Dos Reis: Or in 6.5 [basic.link] which is
about linkage. I would have expected that paragraph to say that that
members of class types have external linkage when the enclosing class
has an external linkage. Otherwise 6.5 [basic.link]
paragraph 8:

Names not covered by these rules have no linkage.

might imply that such members do not have linkage.

Notes from the April, 2005 meeting:

The question about the linkage of class members is already
covered by 6.5 [basic.link] paragraph 5.

2232.
thread_local anonymous unions

It is not clear from the current wording whether the
thread_local specifier can be applied to anonymous unions
or not. According to 10.1.1 [dcl.stc] paragraph 3,

The thread_local specifier indicates that the named entity has
thread storage duration (6.7.2 [basic.stc.thread]). It shall be applied
only to the names of variables of namespace or block scope and to the names
of static data members.

One might think that an anonymous union object would be a
“variable,” but the next paragraph seems to treat variables
and anonymous unions as distinct:

The static specifier can be applied only to names of variables and
functions and to anonymous unions (12.3.1 [class.union.anon]).

1820.
Qualified typedef names

The resolution of issue 482 allows
a typedef to be redeclared in the same or a containing scope using
a qualified declarator-id. This was not the principal
goal of the issue and is not supported by current implementations.
Should the prohibition of qualified declarator-ids be
reinstated for typedefs?

1894.
typedef-names and using-declarations

The resolution of issue 407 does not
cover cases involving using-declarations. For example:

namespace A { struct S {}; }
namespace B {
// This is valid per issue 407
using A::S;
typedef A::S S;
struct S s;
}
namespace C {
// The typedef does not redefine the name S in this
// scope, so issue 407's resolution does not apply.
typedef A::S S;
using A::S;
// The name lookup here isn't ambiguous, because it only finds one
// entity, but it finds both a typedef-name and a non-typedef-name referring
// to that entity, so the standard doesn't appear to say whether this is valid.
struct S s;
}

One possibility might be to remove the rule that a typedef-name
declaration redefines an already-defined name and instead rely on
struct stat-style hiding, taking the non-typedef-name
if name lookup finds both and they refer to the same type.

144.
Position of friend specifier

10.1.7.3 [dcl.type.elab]
paragraph 1 seems to
impose an ordering constraint on the elements of friend class
declarations. However, the general rule is that declaration
specifiers can appear in any order. Should

The core language working group was unable to come to consensus
over what kind of declaration a using-declaration should
emulate. In a straw poll, 7 members favored allowing
using-declarations wherever a non-definition declaration could
appear, while 4 preferred to allow multiple using-declarations
only in namespace scope (the rationale being that the permission for
multiple using-declarations is primarily to support its use in
multiple header files, which are seldom included anywhere other than
namespace scope). John Spicer pointed out that friend
declarations can appear multiple times in class scope and asked if
using-declarations would have the same property under the "like
a declaration" resolution.

As a result of the lack of agreement, the issue was returned to
"open" status.

Currently, it appears that the using-declarations of
i are ill-formed, on the basis of 10.3.3 [namespace.udecl] paragraph 10:

Since a using-declaration is a declaration, the
restrictions on declarations of the same name in the same
declarative region (6.3 [basic.scope]) also apply to
using-declarations.

Because the using-declarations of i refer to
different objects, declaring them in the same scope is not
permitted under 6.3 [basic.scope]. It might, however,
be preferable to treat this case as many other ambiguities are:
allow the declaration but make the program ill-formed if a name
reference resolves to the ambiguous declarations.

The status of the using-declarations of j,
however, is less clear. They both declare the same entity and
thus do not violate the rules of 6.3 [basic.scope].
This might (or might not) violate the restrictions of
12.2 [class.mem] paragraph 1:

Except when used to declare friends (14.3 [class.friend])
or to introduce the name of a member of a base class into a
derived class (10.3.3 [namespace.udecl], _N3225_.11.3 [class.access.dcl]), member-declarations declare members of the
class, and each such member-declaration shall declare at least
one member name of the class. A member shall not be declared
twice in the member-specification, except that a nested
class or member class template can be declared and then later
defined.

Do the using-declarations of j repeatedly
declare the same member? Or is the preceding sentence an
indication that a using-declaration is not a declaration
of a member?

813.
typename in a using-declaration with a non-dependent name

If a using-declaration uses the keyword typename and
specifies a dependent name (17.7.2 [temp.dep]), the name
introduced by the using-declaration is treated as a
typedef-name (10.1.3 [dcl.typedef]).

This wording does not address use of typename in a
using-declaration with a non-dependent name; the primary
specification of the typename keyword in 17.7 [temp.res] does not appear to describe this case, either.

10.3.3 [namespace.udecl] does not deal explicitly with dependent
base classes, but does say in paragraph 3,

In a using-declaration used as a member-declaration, the
nested-name-specifier shall name a base class of the class
being defined. If such a using-declaration names a constructor,
the nested-name-specier shall name a direct base class of the
class being defined; otherwise it introduces the set of declarations
found by member name lookup (13.2 [class.member.lookup], 6.4.3.1 [class.qual]).

In the definition of S, B::f is not a dependent
name but resolves to an apparently unrelated class. However, because
S could be instantiated as S<B>, presumably
17.7 [temp.res] paragraph 8 would apply:

No diagnostic shall be issued for a template definition for which a
valid specialization can be generated.

Note also the resolution of issue 515,
which permitted a similar use of a dependent base class named with a
non-dependent name.

1742.
using-declarations and scoped enumerators

A using-declaration cannot name a scoped enumerator, according
to 10.3.3 [namespace.udecl] paragraph 7. This is presumably because
a scoped enumerator belongs to an enumeration scope and thus logically
cannot belong to the non-enumeration scope in which the
using-declaration appears. It seems inconsistent, however, to
permit using-declarations to name unscoped enumerators but not
scoped enumerators.

Also, 10.3.3 [namespace.udecl] paragraph 3 says,

In a using-declaration used as a member-declaration,
the nested-name-specifier shall name a base class of the class being
defined.

The consequence of this is that

enum E { e0 };
void f() {
using E::e0;
}

is well-formed, but

struct B {
enum E { e0 };
};
struct D : B {
using B::E::e0;
};

is not. Again, this seems inconsistent. Should these rules be
relaxed?

Except for functions with C++ linkage, a function declaration without
a linkage specification shall not precede the first linkage
specification for that function. A function can be declared without a
linkage specification after an explicit linkage specification has been
seen; the linkage explicitly specified in the earlier declaration is
not affected by such a function declaration.

There doesn't seem to be a good reason for these provisions not
to apply to variable names, as well.

In other contexts, inheritance of linkage requires that the earlier
declaration be visible, as in 6.5 [basic.link] paragraph 6:

The name of a function declared in block scope and the name
of a variable declared by a block scope extern declaration
have linkage. If there is a visible declaration of an entity
with linkage having the same name and type, ignoring
entities declared outside the innermost enclosing namespace
scope, the block scope declaration declares that same entity
and receives the linkage of the previous declaration.

The specification for language linkage in
10.5 [dcl.link] paragraph 5, however, makes no
mention of visibility:

A function can be declared without a linkage specification
after an explicit linkage specification has been seen; the
linkage explicitly specified in the earlier declaration is
not affected by such a function declaration.

1617.
alignas and non-defining declarations

If the defining declaration of an entity has an alignment-specifier,
any non-defining declaration of that entity shall either specify equivalent
alignment or have no alignment-specifier. Conversely, if any
declaration of an entity has an alignment-specifier, every defining
declaration of that entity shall specify an equivalent alignment. No
diagnostic is required if declarations of an entity have
different alignment-specifiers in different translation units.

Because this is phrased in terms of the definition of an entity,
an example like the following is presumably well-formed (even though
there can be no definition of n):

alignas(8) extern int n;
alignas(16) extern int n;

Is this intentional?

504.
Should use of a variable in its own initializer require a diagnostic?

It is in general not possible to determine at compile time whether
a reference is used before it is initialized. Nevertheless, there is
some sentiment to require a diagnostic in the obvious cases that can
be detected at compile time, such as the name of a reference appearing
in its own initializer. The resolution of issue 453 originally made such uses ill-formed, but the CWG decided
that this question should be a separate issue.

Rationale (October, 2005):

The CWG felt that this error was not likely to arise very
often in practice. Implementations can warn about such constructs,
and the resolution for issue 453 makes
executing such code undefined behavior; that seemed to address the
situation adequately.

Note (February, 2006):

Recent discussions have suggested that undefined behavior be
reduced. One possibility (broadening the scope of this issue to
include object declarations as well as references) was to require a
diagnostic if the initializer uses the value, but not just the
address, of the object or reference being declared:

(T... b is a non-deduced context per
17.9.2.5 [temp.deduct.type] paragraph 5, so the template arguments must
be specified explicitly.)

Notes from the April, 2013 meeting:

CWG agreed that the example should be ill-formed.

Additional note (August, 2013):

11.3.6 [dcl.fct.default] paragraph 4 explicitly allows for a function
parameter pack to follow a parameter with a default argument:

In a given function declaration, each parameter subsequent to a parameter
with a default argument shall have a default argument supplied in this or a
previous declaration or shall be a function parameter pack.

However, any instantiation of such a function template with a non-empty
pack expansion would result in a function declaration in which one or more
parameters without default arguments (from the pack expansion) would follow
a parameter with a default argument and thus would be ill-formed. Such a
function template declaration thus violates 17.7 [temp.res]
paragraph 8:

If every valid specialization of a variadic template requires an empty
template parameter pack, the template is ill-formed, no diagnostic
required.

Although the drafting review teleconference of 2013-08-26 suggested
closing the issue as NAD, it is being kept open to discuss and resolve this
apparent contradiction.

Notes from the September, 2013 meeting:

CWG agreed that this example should be accepted; the restriction on
default arguments applies to the template declaration itself, not to
its specializations.

2346.
Local variables in default arguments

A local variable shall not appear as a potentially-evaluated expression in
a default argument.

This prohibits plausible uses of constexpr and static
local variables. Presumably this rule should be similar to the one in
12.4 [class.local] paragraph 1, regarding local classes, which
applies to odr-use, not potential evaluation, and to variables with
automatic storage duration.

2340.
Reference collapsing and structured bindings

Given the type Ti designated
by std::tuple_element<i, E>::type,
each vi is a variable of type
“reference to Ti”
initialized with the initializer, where the reference is an
lvalue reference if the initializer is an lvalue and an rvalue
reference otherwise; the referenced type
is Ti.

If Ti is already a reference
type, should this do reference collapsing? Presumably yes,
but reference collapsing is specified in terms of a
typedef-name or decltype-specifier, which are not
used in this description.

670.
Copy initialization via derived-to-base conversion in the second step

we are copy-initializing a B from 0. So by
16.3.1.4 [over.match.copy] we consider all the converting
constructors of B, and choose B(int) to create
a B. Then, by 11.6 [dcl.init] paragraph 15, we
direct-initialize the parameter from that temporary B. By
16.3.1.3 [over.match.ctor] we consider all constructors. The copy
constructor cannot be called with a temporary, but B(A) is
callable.

As far as I can tell, the Standard says that this example is
well-formed, and calls B(A). EDG and G++ have rejected this
example with a message about the copy constructor not being callable,
but I have been unsuccessful in finding anything in the Standard that
says that we only consider the copy constructor in the second step of
copy-initialization. I wouldn't mind such a rule, but it doesn't seem
to be there. And implementing issue 391
causes G++ to start accepting the example.

This question came up before in
a GCC bug
report; in the discussion of that bug Nathan Sidwell said that
some EDG folks explained to him why the testcase is ill-formed, but
unfortunately didn't provide that explanation in the bug report.

I think the resolution of issue 391
makes this example well-formed; it was previously ill-formed because
in order to bind the temporary B(0) to the argument of
A(const A&) we needed to make another
temporary B, and that's what made the example ill-formed. If
we want this example to stay ill-formed, we need to change something
else.

Steve Adamczyk:

I tracked down my response to Nathan at the time, and it related to
my paper N1232 (on the auto_ptr problem). The change that
came out of that paper is in 16.3.3.1 [over.best.ics] paragraph
4:

However, when considering the argument of a user-defined conversion
function that is a candidate by 16.3.1.3 [over.match.ctor] when
invoked for the copying of the temporary in the second step of a class
copy-initialization, or by 16.3.1.4 [over.match.copy], 16.3.1.5 [over.match.conv], or 16.3.1.6 [over.match.ref] in all cases, only
standard conversion sequences and ellipsis conversion sequences are
allowed.

This is intended to prevent use of more than one implicit user-
defined conversion in an initialization.

I told Nathan B(A) can't be called because its argument
would require yet another user-defined conversion, but I was wrong. I
saw the conversion from B to A and immediately
thought “user-defined,” but in fact because B is
a derived class of A the conversion according to 16.3.3.1 [over.best.ics] paragraph 6 is a derived-to-base Conversion (even
though it will be implemented by calling a copy constructor).

So I agree with you: with the analysis above and the change for
issue 391 this example is well-formed. We
should discuss whether we want to make a change to keep it
ill-formed.

233.
References vs pointers in UDC overload resolution

There is an inconsistency in the handling of references
vs pointers in user defined conversions and overloading. The reason
for that is that the combination of 11.6.3 [dcl.init.ref] and
7.5 [conv.qual] circumvents the standard way of ranking
conversion functions, which was probably not the intention of the
designers of the standard.

So while both classes A and B are structurally
equivalent, there is a difference in operator overloading. I want to
start with the discussion of the pointer case (const Z
*a2=a;): 16.3.3 [over.match.best] is used to select the best
viable function. Rule 4 selects A::operator const Z*() as
best viable function using 16.3.3.2 [over.ics.rank] since the
implicit conversion sequence const Z* -> const Z*
is a better conversion sequence than Z* -> const
Z*.

So what is the difference to the reference case? Cv-qualification
conversion is only applicable for pointers according to 7.5 [conv.qual]. According to 11.6.3 [dcl.init.ref] paragraphs
4-7 references are initialized by binding using the concept of
reference-compatibility. The problem with this is, that in this
context of binding, there is no conversion, and therefore there is
also no comparing of conversion sequences. More exactly all
conversions can be considered identity conversions according to
16.3.3.1.4 [over.ics.ref] paragraph 1, which compare equal
and which has the same effect. So binding const Z* to
const Z* is as good as binding const Z* to
Z* in terms of overloading. Therefore const Z
&b2=b; is ambiguous. [16.3.3.1.4 [over.ics.ref]
paragraph 5 and 16.3.3.2 [over.ics.rank] paragraph 3 rule 3
(S1 and S2 are reference bindings ...) do not seem to apply to this
case]

There are other ambiguities, that result in the special treatment
of references: Example:

Since both references of class A and B are
reference compatible with references of class A and since
from the point of ranking of implicit conversion sequences they are
both identity conversions, the initialization is ambiguous.

So why should this be a defect?

References behave fundamentally different from pointers in combination
with user defined conversions, although there is no reason to have this
different treatment.

This difference only shows up in combination with user defined
conversion sequences, for all other cases, there are special rules,
e.g. 16.3.3.2 [over.ics.rank] paragraph 3 rule 3.

So overall I think this was not the intention of the authors of the
standard.

So how could this be fixed? For comparing conversion sequences (and
only for comparing) reference binding should be treated as if it was a
normal assignment/initialization and cv-qualification would have to be
defined for references. This would affect 11.6.3 [dcl.init.ref] paragraph 6, 7.5 [conv.qual] and probably
16.3.3.2 [over.ics.rank] paragraph 3.

Another fix could be to add a special case in 16.3.3 [over.match.best] paragraph 1.

2352.
Similar types and reference binding

What is returned is a reference to a temporary instead of binding
directly to ptr. The rules for reference-related types should
say that T is reference-related to U if U*
can be converted to T* by a qualification conversion.

1599.
Lifetime of initializer_list underlying array

The normative wording of 11.6.4 [dcl.init.list] regarding the
lifetime of the array underlying an initializer_list object
does not match the intent as specified in the example in paragraph 6
of that section, even after application of the resolution of
issue 1290. That example contains the
lines:

void f() {
std::initializer_list<int> i3 = { 1, 2, 3 };
}

The commentary indicates that the lifetime of the array created
for the initialization of i3 “persists for the lifetime
of the variable.” However, that is not the effect of the
normative wording. According to paragraph 3,

if T is a specialization of
std::initializer_list<E>, an initializer_list
object is constructed as described below and used to initialize the
object according to the rules for initialization of an object from a
class of the same type (11.6 [dcl.init]).

In other words, the underlying array for {1,2,3} in
the example is associated with the temporary and shares its lifetime;
its lifetime is not extended to that of the variable.

2168.
Narrowing conversions and +/- infinity

The intended treatment of a floating point infinity with
respect to narrowing conversions is not clear. Is
std::numeric_limits<double>::infinity() usable
in a constant expression, for example, and should that be
different from a calculation that results in an infinity?

Notes from the October, 2015 meeting:

CWG requests the assistance of SG6 in resolving this issue.

Notes from the November, 2016 meeting:

SG6 said that arithmetic operations (not conversions) that
produce infinity are not allowed in a constant expression.
However, using std::numeric_limits<T>::infinity()
is okay, but it can't be used as a subexpression. Conversions that
produce infinity from non-infinity values are considered to be
narrowing conversions.

511.
POD-structs with template assignment operators

A POD-struct is not permitted to have a user-declared copy
assignment operator (12 [class] paragraph 4). However, a
template assignment operator is not considered a copy assignment
operator, even though its specializations can be selected by overload
resolution for performing copy operations (15.8 [class.copy]
paragraph 9 and especially footnote 114). Consequently, X in
the following code is a POD, notwithstanding the fact that copy
assignment (for a non-const operand) is a member function call
rather than a bitwise copy:

1821.
Qualified redeclarations in a class member-specification

12.2 [class.mem] paragraph 1 allows nested classes, class
templates, and enumerations to be declared and then later defined in
the class member-specification. There does not appear to be
a restriction on using a qualified-id in that definition.
Should such a restriction be added?

The initialization of right is in a context that must
be done during the initial parse of the class, but the function
body of compute_right is not supposed to be evaluated
until the class is complete. Current implementations appear to
accept the template case but not the equivalent non-template case.
It's not clear why those cases should be treated differently.

If you change the example to include a forward dependency in
the body of compute_right, e.g.,

1943.
Unspecified meaning of “bit”

CWG decided at the 2014-06 (Rapperswil) meeting to address
only a limited subset of the questions raised by issues
1857 and
1861. This issue is a placeholder for
the remaining questions, such as defining a “bit” in
terms of a value of 2n, specifying whether a bit-field
has a sign bit, etc.

The statement from 14 [class.access] paragraph 1 says that the
name f can be used only by members and friends of S.
Function g is neither, and it clearly contains a use of the
name f. That appears to make it ill-formed, in spite of the fact
that overload resolution will select the public member.

A related question is whether the use of the term “name”
in the description of the effect of access control means that it does
not apply to constructors and destructors, which do not have names.

Mike Miller: The phrase “its name can be used”
should be understood as “it can be referred to by name.”
Paragraph 4, among other places, makes it clear that access control is
applied after overload resolution. The “name” phrasing is
there to indicate that access control does not apply where the name is
not used (in a call via a pointer, for example).

It seems to me that the using declaration in B should hide the
public foo in A. Then the call to B::foo should fail because B::foo
is not accessible in main.

Am I missing something?

Steve Adamczyk:
This is similar to the last example in 14.2 [class.access.base].
In prose, the rule is
that if you have access to cast to a base class and you have access
to the member in the base class, you are given access in the derived
class. In this case, A is a public base class of B and foo is public
in A, so you can access foo through a B object. The actual permission
for this is in the fourth bullet in
14.2 [class.access.base] paragraph 4.

The wording changes for issue 9
make this clearer, but I believe
even without them this example could be discerned to be valid.

See my paper J16/96-0034, WG21/N0852 on this topic.

Steve Clamage:
But a using-declaration is a declaration (10.3.3 [namespace.udecl]).
Compare with

struct B : A {
private:
int foo();
};

In this case, the call would certainly be invalid, even though your
argument about casting B to an A would make it OK. Your argument
basically says that an access adjustment to make something less
accessible has no effect. That also doesn't sound right.

Steve Adamczyk:
I agree that is strange. I do think that's what 14.2 [class.access.base]
says, but perhaps that's not what we want it to say.

581.
Can a templated constructor be explicitly instantiated or specialized?

Although it is not possible to specify a constructor's template
arguments in a constructor invocation (because the constructor has
no name but is invoked by use of the constructor's class's name), it
is possible to “name” the constructor in declarative
contexts: per 6.4.3.1 [class.qual] paragraph 2,

In a lookup in which the constructor is an acceptable lookup result,
if the nested-name-specifier nominates a class C, and
the name specified after the nested-name-specifier, when looked
up in C, is the injected-class-name of C (clause
12 [class]), the name is instead considered to name the
constructor of class C... Such a constructor name shall be
used only in the declarator-id of a declaration that names a
constructor.

Should it therefore be possible to specify template-arguments
for a templated constructor in an explicit instantiation or specialization?
For example,

If so, that should be clarified in the text. In
particular, 15.1 [class.ctor] paragraph 1 says,

Constructors do not have names. A special declarator syntax using an
optional sequence of function-specifiers (10.1.2 [dcl.fct.spec]) followed by the constructor's class name followed by
a parameter list is used to declare or define the constructor.

This certainly sounds as if the parameter list must immediately
follow the class name, with no allowance for a template argument
list.

It would be worthwhile in any event to revise this wording
to utilize the “considered to name” approach of
6.4.3.1 [class.qual]; as it stands, this wording
sounds as if the following would be acceptable:

struct S {
S();
};
S() { } // qualified-id not required?

Notes from the October, 2006 meeting:

It was observed that explicitly specifying the template arguments
in a constructor declaration is never actually necessary because the
arguments are, by definition, all deducible and can thus be omitted.

2257.
Lifetime extension of references vs exceptions

The consensus was that the temporaries should be destroyed immediately
if an exception occurs. 18.2 [except.ctor] paragraph 3 should
be extended to apply to static initialization, so that even if a temporary
is lifetime-extended (because it has static storage duration), it will be
destroyed in case of an exception.

Should S be found? (S is a dependent name, so
if it resolves to a base class type in the instantiated template, it
should satisfy the requirements.) All the compilers I tried allowed
this example, but 15.6.2 [class.base.init] paragraph 2 says,

Names in a mem-initializer-id are looked up in the scope
of the constructor's class and, if not found in that scope, are
looked up in the scope containing the constructor's definition.

The name S is not declared in those scopes.

Mike Miller: Here's another example that is accepted by
most/all compilers but not by the current wording:

6.
Should the optimization that allows a class object to alias another object also allow the case of a parameter in an inline function to alias its argument?

At the London meeting,
15.8 [class.copy]
paragraph 31 was changed to
limit the optimization described to only the following cases:

the source is a temporary object

the return value optimization

One other case was deemed desirable as well:

aliasing a parameter in an inline function call to the function call argument.

However, there are cases when this aliasing was deemed undesirable and,
at the London meeting, the committee was not able to clearly delimit which
cases should be allowed and which ones should be prohibited.

Can we find an appropriate description for the desired cases?

Rationale (04/99): The absence of this optimization does
not constitute a defect in the Standard,
although the proposed resolution in the paper
should be considered when the Standard is revised.

Note (March, 2008):

The Evolution Working Group has accepted the intent of this issue and
referred it to CWG for action (not for C++0x). See paper J16/07-0033 =
WG21 N2173.

Notes from the June, 2008 meeting:

The CWG decided to take no action on this issue until an interested
party produces a paper with analysis and a proposal.

Here we would like to be able to avoid the copy and just
construct the A() directly into the A subobject
of B. But we can't, because it isn't allowed by
15.8 [class.copy] paragraph 34 bullet 3:

when a temporary class object that has not been bound
to a reference (15.2 [class.temporary]) would be copied/moved
to a class object with the same cv-unqualified type, the
copy/move operation can be omitted by constructing the temporary
object directly into the target of the omitted
copy/move

The part about not being bound to a reference was added for an
unrelated reason by issue 185. If
that resolution were recast to require that the temporary object
is not accessed after the copy, rather than banning the reference
binding, this optimization could be applied.

The similar example using pass by value is also not one of the
allowed cases, which could be considered part of issue 6.

According to 16.6 [over.built] paragraph 16, there is an
operator== for PD (“For every pointer to
member type...”), so why wouldn't it be used for this
comparison?

Mike Miller: The problem, as I understand it, is that
16.3.1.2 [over.match.oper] paragraph 3, bullet 3, sub-bullet 3
is broader than it was intended to be. It says that candidate
built-in operators must “accept operand types to which the given
operand or operands can be converted according to 16.3.3.1 [over.best.ics].” 16.3.3.1.2 [over.ics.user]
describes user-defined conversions as having a second standard
conversion sequence, and there is nothing to restrict that second
standard conversion sequence.

My initial thought on addressing this would be to say that
user-defined conversion sequences whose second standard conversion
sequence contains a pointer conversion or a pointer-to-member
conversion are not considered when selecting built-in candidate
operator functions. They would still be applicable after the hand-off
to Clause 5 (e.g., in bringing the operands to their common type,
8.10 [expr.eq], or composite pointer type, 8.9 [expr.rel]), just not in constructing the list of built-in
candidate operator functions.

I started to suggest restricting the second standard conversion
sequence to conversions having Promotion or Exact Match rank, but that
would exclude the Boolean conversions, which are needed
for !, &&, and ||. (It would have
also restricted the floating-integral conversions, though, which might
be a good idea. They can't be used implicitly, I think, because there
would be an ambiguity among all the promoted integral types; however,
none of the compilers I tested even tried those conversions because
the errors I got were not ambiguities but things like “floating
point operands not allowed for %”.)

Bill Gibbons: I recall seeing this problem before, though
possibly not in committee discussions. As written this rule makes the
set of candidate functions dependent on what classes have been
defined, including classes not otherwise required to have been defined
in order for "==" to be meaningful. For templates this implies that
the set is dependent on what templates have been instantiated,
e.g.

There may be other places where the existence of a class
definition, or worse, a template instantiation, changes the semantics
of an otherwise valid program (e.g. pointer conversions?) but it seems
like something to be avoided.

1919.
Overload resolution for ! with explicit conversion operator

Although the intent is that the ! operator should be
usable with an operand that is a class object having an explicit
conversion to bool (i.e., its operand is
“contextually converted to bool”), the
selection of the conversion operator is done via
16.3.1.2 [over.match.oper], 16.3.2 [over.match.viable], and
16.3.3 [over.match.best], which do not make specific allowance
for this special characteristic of the ! operator and
thus will not select the explicit conversion function.

1781.
Converting from nullptr_t to bool in overload resolution

According to 16.3.1.5 [over.match.conv] paragraph 1, when a class
type S is used as an initializer for an object of type T,

The conversion functions of S and its base classes are
considered. Those non-explicit conversion functions that are not hidden
within S and yield type T or a type that can be converted
to type T via a standard conversion sequence
(16.3.3.1.1 [over.ics.scs]) are candidate functions.

Because conversion from std::nullptr_t to bool
is only permitted in direct-initialization (7.13 [conv.fctptr]),
it is not clear whether there is a standard conversion sequence from
std::nullptr_t to bool, considering that an
implicit conversion sequence is intended to model
copy-initialization. Should 16.3.1.5 [over.match.conv] be
understood to refer only to conversions permitted in
copy-initialization, or should the form of the initialization be
considered? For example,

418.
Imperfect wording on error on multiple default arguments on a called function

According to
16.3.3 [over.match.best] paragraph 4, the following program
appears to be ill-formed:

void f(int, int=0);
void f(int=0, int);
void g() {
f();
}

Though I do not expect this is the intent of this paragraph in the
standard.

16.3.3 [over.match.best] paragraph 4:

If the best viable function resolves to a function for which multiple
declarations were found, and if at least
two of these declarations or the declarations they refer to in the case of
using-declarations specify a
default argument that made the function viable, the program is ill-formed.
[Example:

The bulleted list of 16.3.3.2 [over.ics.rank] paragraph 3
consists of a logic ladder of the form “A is better than B if
[some predicate relating A to B], or, if not that, ...”
For example, bullet 3.1 says,

List-initialization sequence L1 is a better
conversion sequence than list-initialization sequence L2
if

L1 converts
to std::initializer_list<X> for some X
and L2 does not, or, if not that,

L1 converts to type “array of N1
T”, L2 converts to type “array
of N2 T”, and N1 is smaller
than N2 ,

The intent is not to fall into the array case if L2
converts to std::initializer_list<X> and L1
does not — i.e., the inverse predicate holds — but that
intent is not well reflected in the actual wording.

According to 8.2.5 [expr.ref] paragraph 4 bullet 3,
you do function overload resolution to determine whether
x.f is a static or non-static member function.
8.3.1 [expr.unary.op] paragraph 6 says that you can only
take the address of an overloaded function in a context that
determines the overload to be chosen, and the initialization of a
function pointer is such a context (16.4 [over.over]
paragraph 1). The problem is that 16.4 [over.over] is
phrased in terms of “an overloaded function name,”
and this is a member access expression, not a name.

There is variability among implementations as to whether this
example is accepted; some accept it as written, some only if the
& is omitted, and some reject it in both forms.

Because the address occurs in a call context and not in one of
the contexts mentioned in 16.4 [over.over] paragraph 1,
the call expression in foo is presumably ill-formed.
Contrast this with the similar example

void g1(int*) {}
void g1(long) {}
void foo1() {
(&g1)(0L);
}

This call presumably is well-formed because 16.3.1.1 [over.match.call] applies to “the address of a set of overloaded
functions.” (This was clearer in the wording prior to the
resolution of issue 704: “...in
this context using &F behaves the same as using the
name F by itself.”) It's not clear that there's any
reason to treat these two cases differently.

This question also bears on the original question of this issue,
since the original wording of 16.3.1.1 [over.match.call] also
described the case of an ordinary member function call like
s.g(0L) as involving the “name” of the function,
even though the postfix-expression is a member access
expression and not a “name.” Perhaps the reference to
“name” in 16.4 [over.over] should be similarly
understood as applying to member access expressions?

1549.
Overloaded comma operator with void operand

Even though a function cannot take a parameter of type void,
the current rules for overload resolution require consideration of
overloaded operators when one operand has a user-defined or enumeration
type and the other has type void. This can result in side
effects and possibly errors, for example:

Related to the preceding, but not resolved by the suggested
resolution, is the following problem. Given:

struct T {
operator int() const;
operator double() const;
};

I believe the standard requires the following assignment to be
ambiguous (even though I expect that would surprise the user):

double x;
void f(const T& t) { x = t; }

The problem is that both of these built-in operator=()s exist
(16.6 [over.built] paragraph 18):

double& operator=(double&, int);
double& operator=(double&, double);

Both are an exact match on the first argument and a user conversion
on the second. There is no rule that says one is a better match than
the other.

The compilers that I have tried (even in their strictest setting)
do not give a peep. I think they are not following the standard.
They pick double& operator=(double&, double) and use
T::operator double() const.

I hesitate to suggest changes to overload resolution, but a
possible resolution might be to introduce a rule that, for built-in
operator= only, also considers the conversion sequence from
the second to the first type. This would also resolve the earlier
question.

It would still leave x += t etc. ambiguous -- which might
be the desired behavior and is the current behavior of some
compilers.

Notes from the 04/01 meeting:

The difference between initialization and assignment is
disturbing. On the other hand, promotion is ubiquitous in the
language, and this is the beginning of a very slippery slope (as
the second report above demonstrates).

The comparison at #1 is, according to the current Standard,
ambiguous. According to 16.6 [over.built] paragraph 12, the
candidates for operator==(L, R) include functions “for
every pair of promoted arithmetic types,” so L could be
either int or long, and the conversion operator
template will provide an exact match for either.

Some implementations unambiguously choose the int candidate.
Perhaps the overload resolution rules could be tweaked to prefer
candidates in which L and R are the same type?

110.
Can template functions and classes be declared in the same scope?

Except that a function template can be overloaded either by
(non-template) functions with the same name or by other function
templates with the same name
(17.9.3 [temp.over]
), a template name declared
in namespace scope or in class scope shall be unique in that scope.

6.3.10 [basic.scope.hiding]
paragraph 2 agrees
that only functions, not function templates, can hide a class name
declared in the same scope:

A class name (12.1 [class.name]
) or
enumeration name (10.2 [dcl.enum]
) can be
hidden by the name of an object, function, or enumerator declared in
the same scope.

However, 6.3 [basic.scope]
paragraph 4
treats functions and template functions together in this regard:

Given a set of declarations in a single declarative region, each of
which specifies the same unqualified name,

they shall all refer to the same entity, or all refer to functions
and function templates; or

exactly one declaration shall declare a class name or enumeration
name that is not a typedef name and the other declarations shall all
refer to the same object or enumerator, or all refer to functions and
function templates; in this case the class name or enumeration name is
hidden

John Spicer: You should be able to take an existing program
and replace an existing function with a function template without
breaking unrelated parts of the program.
In addition, all of the compilers I tried allow this usage (EDG, Sun,
egcs, Watcom, Microsoft, Borland).
I would recommend that function templates be handled exactly like functions
for purposes of name hiding.

Martin O'Riordan: I don't see any justification for extending
the purview of what is decidedly a hack, just for the sake of consistency.
In fact, I think we should go further and in the interest of consistency, we
should deprecate the hack, scheduling its eventual removal from the C++
language standard.

The hack is there to allow old C programs and especially the
'stat.h' file to compile with minimum effort (also several other Posix and X
headers). People changing such older programs have ample opportunity to "do
it right". Indeed, if you are adding templates to an existing program, you
should probably be placing your templates in a 'namespace', so the issue
disappears anyway. The lookup rules should be able to provide the behaviour
you need without further hacking.

579.
What is a “nested” > or >>?

The Standard does not normatively define which > and
>> tokens are to be taken as closing a
template-argument-list; instead, 17.2 [temp.names]
paragraph 3 uses the undefined and imprecise term
“non-nested:”

When parsing a template-id, the first non-nested >
is taken as the end of the template-argument-list rather than a
greater-than operator. Similarly, the first
non-nested >> is treated as two consecutive but
distinct > tokens, the first of which is taken as the end
of the template-argument-list and completes the template-id.

The (non-normative) footnote clarifies that

A > that encloses the type-id of a dynamic_cast, static_cast,
reinterpret_cast or const_cast, or which encloses the
template-arguments of a subsequent template-id, is
considered nested for the purpose of this description.

Aside from the questionable wording of this footnote (e.g., in what
sense does a single terminating character “enclose”
anything, and is a nested template-id
“subsequent?”) and the fact that it is non-normative, it
does not provide a complete definition of what “nesting”
is intended to mean. For example, is the first > in this
putative template-id “nested” or not?

John Spicer:
This is not among the permitted conversions listed in 14.3.

I'm not sure there is a terribly good reason for that. Some of the
template argument rules for external entities were made conservatively
because of concerns about issues of mangling template argument names.

David Abrahams:
I'd really like to see that restriction loosened. It is a serious
inconvenience because there appears to be no way to supply a usable
default in this case. Zero would be an OK default if I could use the
function pointer's equality to zero as a compile-time switch to
choose an empty function implementation:

2105.
When do the arguments for a parameter pack end?

There does not appear to be a clear statement in the Standard
that the first template parameter pack in a template parameter
list corresponds to all remaining arguments in the template
argument list. For example:

It appears that the friend template matches Q::C, because that
class is also A<int>::B::C, but neither GCC nor EDG allow
this code (saying X::x is inaccessible). (Clang doesn't support
friend template declarations with a dependent scope.)

A strict reading of 17.6.4 [temp.friend] paragraph 5 might
suggest that the friend declaration itself is ill-formed, because it does
not declare a member of a class template, but I can't find any compiler
that implements template friends that way.

1945.
Friend declarations naming members of class templates in non-templates

The explicit specialization at #3 replaces the primary member
template #1 of B<int>; however, it is not clear
whether the partial specialization #2 should be considered to
apply to the explicitly-specialized member template of
A<int> (thus allowing the call to p.f()
at #4) or whether the partial specialization will be used only
for specializations of B that are implicitly
instantiated (meaning that #4 could call p.g() but not
p.f()).

is ill-formed because the deduction succeeds in both directions.
This seems surprising. It was suggested that perhaps a
non-deduced context should be considered more specialized than
a deduced context.

310.
Can function templates differing only in parameter cv-qualifiers be overloaded?

cannot be overloaded and I don't see any reason for it
since it is function template specializations that are
treated like ordinary non-template functions, meaning
that the transformation of a
parameter-declaration-clause into the corresponding
parameter-type-list is applied to specializations
(when determining its type) and not to function
templates.

What makes me think so is the contents of 17.6.6.1 [temp.over.link]
and the following sentence from 17.9.2.1 [temp.deduct.call] "If P is a
cv-qualified type, the top level cv-qualifiers of P
are ignored for type deduction". If the transformation
was to be applied to function templates, then there
would be no reason for having that sentence in
17.9.2.1 [temp.deduct.call].

17.9.2.2 [temp.deduct.funcaddr], which my example is
based upon, says nothing
about ignoring the top level cv-qualifiers of the
function parameters of the function template whose
address is being taken.

As a result, I expect that template argument deduction
will fail for the 2-nd and 3-d member templates and
the 1-st one will be used for the instantiation of the
specialization.

both have the
form noexcept(constant-expression)
and the constant-expressions are equivalent,
or

...

it is not clear whether “equivalent” in this context
should be taken as a reference to the definition of
equivalent given in 17.6.6.1 [temp.over.link] paragraph
5:

Two expressions involving template parameters are considered
equivalent if two function definitions containing the
expressions would satisfy the one definition rule
(6.2 [basic.def.odr]), except that the tokens used to
name the template parameters may differ as long as a token
used to name a template parameter in one expression is
replaced by another token that names the same template
parameter in the other expression.

since the context there is expressions that appear in function
template parameters and return types.

Both #1 and #2 can deduce the "a" argument, #1 deduces T as char and
#2 deduces I as 2. However, neither is more specialized because the
proposed rules do not have any array to pointer decay.

#1 is only deduceable because of the rules in
17.9.2.1 [temp.deduct.call] paragraph 2 that
decay array and function type arguments when the template parameter is
not a reference. Given that such behaviour happens in deduction, I believe
there should be equivalent behaviour during partial ordering. #2 should be
resolved as more specialized as #1. The following alteration to the
proposed resolution of DR214 will do that.

Insert before,

If A is a cv-qualified type, A is replaced by the
cv-unqualified version of A.

the following

If P was not originally a reference type,

If A is an array type, A is replaced by the pointer type produced
by the array to pointer conversion

If A is a function type, A is replaced by the pointer type
produced by the function to pointer conversion

For the example above, this change results in deducing 'T const *' against
'char const *' in one direction (which succeeds), and 'char [I]'
against 'T const *' in the other (which fails).

John Spicer:
I don't consider this a shortcoming of my proposed wording, as I don't
think this is part of the current rules. In other words, the
resolution of 214 might make it clearer how this case is handled
(i.e., clearer that it is not allowed), but I don't believe it
represents a change in the language.

I'm not necessarily opposed to such a change, but I think it should be
reviewed by the core group as a related change and not a defect in the
proposed resolution to 214.

Notes from the October 2003 meeting:

There was some sentiment that it would be desirable to have
this case ordered, but we don't think it's worth spending the
time to work on it now. If we look at some larger partial
ordering changes at some point, we will consider this again.

1157.
Partial ordering of function templates is still underspecified

To produce the transformed template, for each type,
non-type, or template template parameter (including template
parameter packs (17.6.3 [temp.variadic]) thereof)
synthesize a unique type, value, or class template
respectively and substitute it for each occurrence of that
parameter in the function type of the template.

The characteristics of the synthesized entities and how they
are determined is not specified. For example, members of a dependent
type referred to in non-deduced contexts are not specified to exist,
even though the transformed function type would be invalid in their
absence.

Note 1: Template argument deduction is an attempt to
match a P and a deduced A; however,
template argument deduction is not specified to fail if the
P and the deduced A are incompatible. This
may occur in the presence of non-deduced contexts.
Notwithstanding the parenthetical statement in 17.9.2.4 [temp.deduct.partial] paragraph 9, template argument deduction
may succeed in determining a template argument for every
template parameter while producing a deduced A that
is not compatible with the corresponding P.

17.9.2.5 [temp.deduct.type] paragraph 2 makes it clear
that there must be exactly one set of deduced values for the
Ps. But there is no such statement in the partial ordering
rule. The algorithm described only does pairwise P/A
matching, so a synthesized call from (2) to (1) via foo(U{},
V{}) could succeed in deduction. Both gcc and clang agree
that (1) is more specialized.

Here, if synthesized for (2) Unique2 and typename
identity<Unique2>::type == Unique2 , then type
deduction would succeed in both directions and the call
bar(0,0) would be ambiguous. However, it seems that
both compilers instead simply treat typename
identity<Unique2>::type as Unique2_b,
thus making template deduction from (2) to (1) fail (based
on the implied missing Consistency rule).

With no template instantiation during synthesis and
consistency, the (2) ==> (1) deduction fails. But if we
consider the (1) ==> (2) call, we'd match T against
Unique1 and then have the non-deduced
context typename identity<Unique1>::type to
match against Unique1, but that would be a
substitution failure. It seems that the approach taken by
gcc and clang (both of which prefer (1) here) is to ignore
the non-deduced context argument, as long as that parameter
type is deduced from a different template parameter type
that did get matched.

Notes from the February, 2016 meeting:

None of these examples appears to reflect a defect in the
current wording; in particular, the second and third
examples involve a dependent type and there could be a later
specialization of identity, so it's impossible to
reason about those cases in the template definition
context. The issue will be left open to allow for possible
clarification of the intent of the wording.

The Standard does not appear to specify whether a non-dependent
reference to a template specialization in a template definition that is
never instantiated causes the implicit instantiation of the referenced
specialization.

1974.
Redundant specification of non-type typename-specifier

When a qualified-id is intended to refer to a type
that is not a member of the current instantiation
(17.7.2.1 [temp.dep.type]) and
its nested-name-specifier refers to a dependent type,
it shall be prefixed by the keyword typename, forming
a typename-specifier. If the qualified-id in
a typename-specifier does not denote a type, the
program is ill-formed.

If a specialization of a template is instantiated for a set
of template-arguments such that
the qualified-id prefixed by typename does not denote
a type, the specialization is ill-formed.

The former requirement is intended to apply to the definition
and the latter to an instantiation of a template, but that intent
is not completely clear, leading to the perception that they are
redundant.

2067.
Generated variadic templates requiring empty pack

If every valid specialization of a variadic template
requires an empty template parameter pack, the template is
ill-formed, no diagnostic required.

I'm inclined to think that this rule should only apply to
code the user wrote. That is, if every valid instantiation
of an entity (that was not itself instantiated) requires at
least one of the enclosing template argument lists to
include an empty template argument pack, then the program is
ill-formed (no diagnostic required).

As the C++ language currently stands, the name "It"
in line (3) refers to the template parameter declared
in line (2), but the name "It" in line (4) refers to
the typedef in the private base class (declared in
line (1)).

This situation is both unintuitive and a hindrance
to sound software engineering. (See also the Usenet
discussion at http://tinyurl.com/32q8d .) Among
other things, it implies that the private section
of a base class may change the meaning of the derived
class, and (unlike other cases where such things
happen) there is no way for the writer of the derived
class to defend the code against such intrusion (e.g.,
by using a qualified name).

Changing this can break code that is valid today.
However, such code would have to:

name a template parameter and not use it
after the opening brace, and

use that same name to access a base-class
name within the braces.

I personally have no qualms breaking such a program.

It has been suggested to make situations like these
ill-formed. That solution is unattractive however
because it still leaves the writer of a derived class
template without defense against accidental name
conflicts with base members. (Although at least the
problem would be guaranteed to be caught at compile
time.) Instead, since just about everyone's intuition
agrees, I would like to see the rules changed to
make class template parameters hide members of the
same name in a base class.

We have some sympathy for a change, but the current rules fall
straightforwardly out of the lookup rules, so they're not
“wrong.” Making private members invisible also would solve
this problem. We'd be willing to look at a paper proposing that.

Additional discussion (April, 2005):

John Spicer: Base class members are more-or-less treated as
members of the class, [so] it is only natural that the base [member]
would hide the template parameter.

Daveed Vandevoorde: Are base class members really
“more or less” members of the class from a lookup
perspective? After all, derived class members can hide base class
members of the same name. So there is some pretty definite
boundary between those two sets of names. IMO, the template
parameters should either sit between those two sets, or they
should (for lookup purposes) be treated as members of the class
they parameterize (I cannot think of a practical difference
between those two formulations).

John Spicer: How is [hiding template parameters]
different from the fact that namespace members can be hidden
by private parts of a base class? The addition of int C
to N::A breaks the code in namespace M in this
example:

Daveed Vandevoorde: C++ has a mechanism in place to handle
such situations: qualified names. There is no such mechanism in place
for template parameters.

Nathan Myers: What I see as obviously incorrect ... is
simply that a name defined right where I can see it, and directly
attached to the textual scope of B's class body, is ignored
in favor of something found in some other file. I don't care that
C1 is defined in A, I have a C1 right
here that I have chosen to use. If I want A::C1, I can
say so.

I doubt you'll find any regular C++ coder who doesn't find the
standard behavior bizarre. If the meaning of any code is changed
by fixing this behavior, the overwhelming majority of cases will
be mysterious bugs magically fixed.

John Spicer: I have not heard complaints that this is
actually a cause of problems in real user code. Where is the
evidence that the status quo is actually causing problems?

In this example, the T2 that is found is the one from
the base class. I would argue that this is natural because base
class members are found as part of the lookup in class B:

This rule that base class members hide template parameters was
formalized about a dozen years ago because it fell out of the
principle that base class members should be found at the same
stage of lookup as derived class members, and that to do otherwise
would be surprising.

Gabriel Dos Reis: The bottom line is that:

the proposed change is a silent change of meaning;

the proposed change does not make the language any more regular;
the current behavior is consistent with everything else, however
“surprising” that might be;

the proposed change does have its own downsides.

Unless presented with real major programming problems the current
rules exhibit, I do not think the simple rule “scopes
nest” needs a change that silently mutates program meaning.

Mike Miller: The rationale for the current specification is
really very simple:

“Unless redeclared in the derived class, members of a base
class are also considered to be members of the derived class.”
(13 [class.derived] paragraph 2)

In class scope, members hide nonmembers.

That's it. Because template parameters are not members, they
are hidden by member names (whether inherited or not). I don't find
that “bizarre,” or even particularly surprising.

I believe these rules are straightforward and consistent, so I
would be opposed to changing them. However, I am not unsympathetic
toward Daveed's concern about name hijacking from base classes. How
about a rule that would make a program ill-formed if a direct or
inherited member hides a template parameter?

Unless this problem is a lot more prevalent than I've heard so
far, I would not want to change the lookup rules; making this kind of
collision a diagnosable error, however, would prevent hijacking
without changing the lookup rules.

Erwin Unruh: I have a different approach that is consistent
and changes the interpretation of the questionable code. At present
lookup is done in this sequence:

it is still consistent in that no lookup is placed between the base
class and the derived class. However, it introduces another
inconsistency: now scopes do not nest the same way as curly braces
nest — but base classes are already inconsistent this way.

Nathan Myers: This looks entirely satisfactory. If even this
seems like too big a change, it would suffice to say that finding a
different name by this search order makes the program ill-formed.
Of course, a compiler might issue only a portability warning in that
case and use the name found Erwin's way, anyhow.

Gabriel Dos Reis: It is a simple fact, even without
templates, that a writer of a derived class cannot protect himself
against declaration changes in the base class.

Richard Corden: If a change is to be made, then making it
ill-formed is better than just changing the lookup rules.

I think changing the semantics of the above code silently would
result in very difficult-to-find problems.

Mike Miller: Another case that may need to be considered in
deciding on Erwin's suggestion or the “ill-formed”
alternative is the treatment of friend declarations
described in 6.4.1 [basic.lookup.unqual] paragraph 10:

1619.
Definition of current instantiation

The definition of the current instantiation, given in
17.7.2.1 [temp.dep.type] paragraph 1, is phrased in terms of the
meaning of a name (“A name refers to the current
instantiation if it is...”); it does not define when a type
is the current instantiation. Thus the interpretation of *this
and of phrases like “member of a class that is the current
instantiation” is not formally specified.

If the type of A::obj had a name, it would be
dependent. However, the rationale for making nested types
dependent is that they are subject to explicit
specialization and thus not knowable at the point of the
template definition. An unnamed type, as in this example,
cannot be explicitly specialized and thus could be
considered as a member of the current instantiation. Which
treatment is intended?

Notes from the February, 2014 meeting:

There are other cases in which a named entity is dependnet, even
though it cannot be explicitly specialized. CWG felt that the most
consistent rule would be to make all nested classes dependent, whether
named or not.

1028.
Dependent names in non-defining declarations

The current wording of 17.7.4 [temp.dep.res] seems to assume
that dependent names can only appear in the definition of a template:

In resolving dependent names, names from the following sources
are considered:

Declarations that are visible at the point of
definition of the template.

Declarations from namespaces associated with the types of
the function arguments both from the instantiation context
(17.7.4.1 [temp.point]) and from the definition context.

However, dependent names can occur in non-defining declarations of
the template as well; for instance,

template<typename T>
T foo(T, decltype(bar(T())));

bar needs to be looked up, even though there is no
definition of foo in the translation unit.

Additional note (February, 2011):

The resolution of this issue can't simply replace the word
“definition” with the word “declaration,”
mutatis mutandis, because there can be multiple declarations
in a translation unit (which isn't true of “the definition”).
As a result, the issue was moved back to "open" status for further
consideration.

2250.
Implicit instantiation, destruction, and TUs

The problem is that the current wording only connects name lookup
with point of instantiation; other semantic checks, such as the
requirement for completeness of a class, should also be performed at
that point.

One might expect this to call operator int when
instantiating. But since operator T is a dependent name, it
is looked up by unqualified lookup only in the definition context,
where it will find no declaration. Argument-dependent lookup will not
find anything in the instantiation context either, so this code is
ill-formed. If we change operator int() to
operator T(), which is a seemingly unrelated change, the
code becomes well-formed.

There is implementation variability on this point.

2118.
Stateful metaprogramming via friend injection

Defining a friend function in a template, then referencing that
function later provides a means of capturing and retrieving
metaprogramming state. This technique is arcane and should be
made ill-formed.

Notes from the May, 2015 meeting:

CWG agreed that such techniques should be ill-formed,
although the mechanism for prohibiting them is as yet
undetermined.

It seems like it might be useful to define a term other than odr-used
for this sort of use, which is like odr-used but doesn't depend on
potentially evaluated context or lvalue-rvalue conversions.

Nikolay Ivchenkov:

Another possibility would be to introduce the extension
described in the closed issue 1272 and
then change 6.2 [basic.def.odr] paragraph 2 as follows:

An expression E is potentially
evaluatedunless it is an unevaluated operand (Clause
8 [expr]) or a subexpression thereof.if and only if

E is a full-expression, or

E appears in a context where a constant expression
is required, or

E is a direct subexpression of a potentially-evaluated
expression and E is not an unevaluated operand.

An expression S is a direct subexpression of an
expression E if and only if S and E
are different expressions, S is a subexpression of
E, and there is no expression X such that
X differs from both S and E,
S is a subexpression of X, and X is a
subexpression of E. A variable whose name appears
as a potentially-evaluated expression is odr-usedunless it is an object that satisfies the requirements for
appearing in a constant expression (8.20 [expr.const])
and the lvalue-to-rvalue conversion (4.1) is immediately
applied...

1602.
Linkage of specialization vs linkage of template arguments

The Standard does not appear to specify the linkage of a template
specialization. 17.8.1 [temp.inst] paragraph 11 does say,

Implicitly instantiated class and function template specializations
are placed in the namespace where the template is defined.

which could be read as implying that the specialization has the
same linkage as the template itself. Implementation practice seems to
be that the weakst linkage of the template and the arguments is used
for the specialization.

1856.
Indirect nested classes of class templates

During the discussion of issue 1484, it was
observed that the current rules do not adequately address indirect nested
classes of class templates (i.e., member classes of member classes of class
templates) in regard to their potential separate instantiation.

which isn't what anyone actually expects. As far as I can tell,
nothing in the standard explicitly forbids this, as written. Syntactically,
this also allows:

template namespace N { void f(); }

although perhaps the surrounding context is enough to suggest that this is
invalid.

Suggested resolution:

I think we should say:

explicit-instantiation:

type-specifier-seqoptdeclaratoropt;

[Steve Adamczyk: presumably, this should havetemplateat the beginning.]

and then say that:

The declarator can be omitted only when the type-specifier-seq
consists solely of an elaborated-type-specifier for a class type, in
which case the instantiation is for the named class. If the
declarator is present the instantiation is for the named entity.

The type-specifier-seq can be omitted only when the declarator
is for a constructor, destructor, or conversion operator.

The type-specifier-seq cannot define any new types.

There are similar problems in 17.8.3 [temp.expl.spec]:

explicit-specialization:

template <> declaration

Here, I think we want:

explicit-specialization:

decl-specifier-seqoptinit-declaratoropt;

with similar restrictions as above.

[Steve Adamczyk: This also needs to havetemplate <>at the beginning, possibly repeated.]

1046.
What is a “use” of a class specialization?

An entity that is the subject of an explicit instantiation
declaration and that is also used in the translation unit shall
be the subject of an explicit instantiation definition somewhere
in the program; otherwise the program is ill-formed, no
diagnostic required.

The term “used” is too vague and needs to be defined.
In particular, “use” of a class template specialization as
an incomplete type — to form a pointer, for instance —
should not require the presence of an explicit instantiation definition
elsewhere in the program.

264.
Unusable template constructors and conversion functions

The note in paragraph 5 of 17.9.1 [temp.arg.explicit] makes
clear that explicit template arguments cannot be supplied in
invocations of constructors and conversion functions because they are
called without using a name. However, there is nothing in the current
wording of the Standard that makes declaring a constructor or
conversion operator that is unusable because of nondeduced parameters
(i.e., that would need to be specified explicitly) ill-formed. It
would be a service to the programmer to diagnose this useless
construct as early as possible.

Among the questions was whether explicit instantiation #2 is valid,
where deduction is required to determine the type of RET.

The first thing I realized when researching this is that the standard
does not really spell out the rules for deduction in declarative
contexts (friend declarations, explicit specializations, and
explicit instantiations). For explicit instantiations,
17.8.2 [temp.explicit] paragraph 2 does
mention deduction, but it doesn't say which set of deduction rules from
17.9.2 [temp.deduct] should be applied.

A trailing template-argument
can be left unspecified in an explicit instantiation provided it can
be deduced from the type of a function parameter
(17.9.2 [temp.deduct]).

This prohibits cases
like #2, but I believe this was not considered in the wording as there
is no reason not to include the return type in the deduction process.

I think there may have been some confusion because the return type is
excluded when doing deduction on a function call. But there are
contexts where the return type is included in deduction, for example,
when taking the address of a function template specialization.

Suggested resolution:

Update 17.9.2 [temp.deduct] to include a section
"Deducing template arguments from a declaration" that describes how
deduction is done when finding a template that matches a declaration.
This should, I believe, include the return type.

Update 17.8.2 [temp.explicit] to make reference to the new
rules in 17.9.2 [temp.deduct] and remove the description of
the deduction details from 17.8.2 [temp.explicit] paragraph
6.

297.
Which template does an explicit specialization specialize?

Andrei Iltchenko points out that the standard has no wording that
defines how to determine which template is specialized by an
explicit specialization of a function template.
He suggests "template argument deduction
in such cases proceeds in the same way as when taking the address
of a function template,
which is described in 17.9.2.2 [temp.deduct.funcaddr]."

John Spicer points out that the same problem exists for all
similar declarations, i.e., friend declarations and explicit
instantiation directives. Finding a corresponding placement
operator delete may have a similar problem.

John Spicer:
There are two aspects of "determining which template" is referred to by
a declaration: determining the function template associated with the
named specialization, and determining the values of the template arguments
of the specialization.

697.
Deduction rules apply to more than functions

17.9.2 [temp.deduct] is all about function types, but these
rules also apply, e.g., when matching a class template partial
specialization. We should add a note stating that we could be doing
substitution into the template-id for a class template partial
specialization.

Additional note (August 2008):

According to 17.6.5.1 [temp.class.spec.match] paragraph 2, argument
deduction is used to determine whether a given partial specialization
matches a given argument list. However, there is nothing in
17.6.5.1 [temp.class.spec.match] nor in 17.9.2 [temp.deduct] and
its subsections that describes exactly how argument deduction is to
be performed in this case. It would seem that more than just a note
is required to clarify this processing.

The Standard appears to specify that the value returned from
main is 2. The reason for this result is that references and
pointers are handled differently in template argument deduction.

For the reference case, 17.9.2.1 [temp.deduct.call] paragraph
3 says that “If P is a reference type, the type
referred to by P is used for type deduction.” Because
of issue 295, all four of the types for the
ref function parameters are the same, with no
cv-qualification; overload resolution does not find a best match among
the parameters and thus the most-specialized function is selected.

For the pointer type, argument deduction does not get as far as
forming a cv-qualified function type; instead, argument deduction
fails in the cv-qualified cases because of the cv-qualification
mismatch, and only the cv-unqualified version of ptr survives
as a viable function.

I think the choice of ignoring cv-qualifiers in the reference case
but not the pointer case is very troublesome. The reason is that when
one considers function objects as function parameters, it introduces a
semantic difference whether the function parameter is declared a
reference or a pointer. In all other contexts, it does not matter: a
function name decays to a pointer and the resulting semantics are the
same.

1221.
Partial ordering and reference collapsing

The current partial ordering rules produce surprising results in
the presence of reference collapsing.

Since partial ordering is currently based solely on the signature
of the function templates, the lack of difference following
substitution of the template type parameter in the following is not
taken into account.

Especially unsettling is that the allegedly "more specialized"
template (#2) is not a candidate in the first call where template
argument deduction fails for it despite a lack of non-deduced
contexts.

This example is covered by 17.9.2.4 [temp.deduct.partial] paragraph 9:

If, for a given type, deduction succeeds in both directions (i.e., the
types are identical after the transformations above) and both P and A were
reference types (before being replaced with the type referred to
above):

if the type from the argument template was an lvalue reference
and the type from the parameter template was not, the parameter type is not
considered to be at least as specialized as the argument type;
otherwise,

if the type from the argument template is more cv-qualified than the
type from the parameter template (as described above), the parameter type
is not considered to be at least as specialized as the argument
type.

For a2(i), the deduction guide is the best match, so this is
an A<double>.

For a3(ci), the first bullet applies, which prefers #1 to #3
since #1 comes from an lvalue reference and #3 does not, resulting in an
A<int>.

For a1(0), the case is not covered by partial ordering, so
16.3.3 [over.match.best] bullet 1.10 applies and prefers #3 to #2, which
is again an A<double>.

It seems inconsistent to prefer #1 to #3 (T const & to
U&&), but to prefer #3 to #2 (U&& to
T&&). Should the rules be expanded to basically prefer
any non-forwarding-reference to a forwarding reference?

In subclause 17.9.2.5 [temp.deduct.type] paragraph 10, deduction from
a function type considers P/A pairs from the parameter-type-list only where
the "P" function type has a parameter. Deduction is not specified to fail
if there are additional parameters in the corresponding "A" function
type.

Notes from the September, 2013 meeting:

CWG agreed that this example should not be accepted. The existing
rules seem to cover this case (deduction is not specified to
“succeed,” so it's a reasonable conclusion that it fails),
but it might be helpful to be clearer.

2328.
Unclear presentation style of template argument deduction rules

The presentation style of 17.9.2.5 [temp.deduct.type]
paragraph 8 results in a specification that is unclear,
needlessly verbose, and incomplete. Specific problems include:

What does it mean for P and A to
have one of a set of forms? Do they both have to have that form?
(That doesn't happen; typically, only P contains template
parameters)

In the introductory sentence,
aren't T, TT, and i supposed to be the
names of template parameters rather than template
arguments?

In T[i], it appears we can deduce i, but
not T (T can only be deduced in the
form T[integer-constant]

What is an integer-constant supposed to be?

What is a cv-list?

Why can we not deduce const T from T?
(Apparently you only get to deduce if both or neither type have
a cv-list, whatever a cv-list is.)

We have extreme redundancy because, for instance, there is
no way to say “in T (T::*)(T), you can deduce any
of those Ts, and it's OK if some of the positions don't
have a T”. So we have seven (!) forms of that
construct, for all cases except the one where none of the three
positions contain a T.

We have special case rules for pointers to member
functions, even though they're not a special case and should be
covered by the rule for pointers to members and the rule for
functions.

We do not allow deducing a template template parameter's value
from a template template argument — there is
a TT<T> form, a TT<i> form,
a template-name<T> form, and
a template-name<i> form, but
no TT<TT> form
nor template-name<TT> form.

2355.
Deducing noexcept-specifiers

The list of deducible forms in 17.9.2.5 [temp.deduct.type] paragraph
8 does not include the ability to deduce the value of the constant in a
noexcept-specifier, although implementations appear to allow it.

2002.
White space within preprocessing directives

The only white-space characters that shall appear between
preprocessing tokens within a preprocessing directive (from
just after the introducing # preprocessing token through
just before the terminating new-line character) are space
and horizontal-tab (including spaces that have replaced
comments or possibly other white-space characters in
translation phase 3).

The effect of this restriction is unclear, however, since
translation phase 3 is permitted to transform all white space
characters and comments into spaces. The relationship between
these two rules should be clarified.

925.
Type of character literals in preprocessor expressions

The resulting tokens comprise the controlling constant expression
which is evaluated according to the rules of 8.20 [expr.const]
using arithmetic that has at least the ranges specified in
21.3 [support.limits], except that all signed and unsigned integer
types act as if they have the same representation as, respectively,
intmax_t or uintmax_t (_N3035_.18.4.2 [stdinth]).
This includes interpreting character literals, which may involve
converting escape sequences into execution character set members.

Ordinary character literals with a single c-char have the
type char, which is neither a signed nor an unsigned integer
type. Although 7.6 [conv.prom] paragraph 1 is clear that
char values promote to int, regardless of whether
the implementation treats char as having the values of
signed char or unsigned char, 19.1 [cpp.cond] paragraph 4 isn't clear on whether character literals
should be treated as signed or unsigned values. In C99, such
literals have type int, so the question does not arise.
If an implementation in which plain char has the values of
unsigned char were to treat character literals as unsigned,
an expression like '0'-'1' would thus have different values
in C and C++, namely -1 in C and some large unsigned value in C++.

there is implementation variance in the value of v: some
produce the string "ax.by.cz" and others produce the string
"ax. by. cz". Although 19.3.2 [cpp.stringize] paragraph 2 is
explicit in its treatment of leading and trailing white space, it is not
clear whether there is latitude for inserting spaces between tokens, as
some implementations do, since the description otherwise is written solely
in terms of preprocessing tokens. There may be cases in which such spaces
would be needed to preserve the original tokenization, but it is not clear
whether the result of stringization needs to produce something that would
lex to the same tokens.

Notes from the April, 2013 meeting:

Because the preprocessor specification is primarily copied directly
from the C Standard, this issue has been referred to the C liaison for
consultation with WG14.

The relevant text from the Standard is found in
19.3.4 [cpp.rescan] paragraph 2:

If the name of the macro being replaced is found during this scan of
the replacement list (not including the rest of the source file's
preprocessing tokens), it is not replaced. Further, if any nested
replacements encounter the name of the macro being replaced, it is not
replaced. These nonreplaced macro name preprocessing tokens are no
longer available for further replacement even if they are later
(re)examined in contexts in which that macro name preprocessing token
would otherwise have been replaced.

The sequence of expansion of G0(42) is as follows:

G0(42)
NIL(G_1)(42)
G_1(42)
NIL(42)

The question is whether the use of NIL in the last
line of this sequence qualifies for non-replacement under the
cited text. If it does, the result will be NIL(42). If
it does not, the result will be simply 42.

The original intent of the J11 committee in this text was
that the result should be 42, as demonstrated by the
original pseudo-code description of the replacement algorithm
provided by Dave Prosser, its author.
The English description,
however, omits some of the subtleties of the pseudo-code and
thus arguably gives an incorrect answer for this case.

As long as the scan involves only preprocessing tokens from
a given macro's replacement list, or tokens resulting from a
replacement of those tokens, an occurrence of the macro's name
will not result in further replacement, even if it is later
(re)examined in contexts in which that macro name preprocessing
token would otherwise have been replaced.

Once the scan reaches the preprocessing token following a
macro's replacement list — including as part of the
argument list for that or another macro — the macro's
name is once again available for replacement. [Example:

The reason that NIL(42) is replaced is that (42)
comes from outside the replacement list of NIL(G_1), hence
the occurrence of NIL within the replacement list for
NIL(G_1) (via the replacement of G_1(42)) is not
marked as nonreplaceable. —end example]

(Note: The resolution of this issue must be coordinated with
J11/WG14.)

Notes (via Tom Plum) from April, 2004 WG14 Meeting:

Back in the 1980's it was understood by several WG14 people
that there were tiny differences between the "non-replacement"
verbiage and the attempts to produce pseudo-code. The
committee's decision was that no realistic programs "in the wild"
would venture into this area, and trying to reduce the
uncertainties is not worth the risk of changing conformance
status of implementations or programs.

745.
Effect of ill-formedness resulting from #error

C99 is very clear that a #error directive causes a translation
to fail: Clause 4 paragraph 4 says,

The implementation shall not successfully translate a preprocessing
translation unit containing a #error preprocessing directive
unless it is part of a group skipped by conditional inclusion.

C++, on the other hand, simply says that a #error directive
“renders the program ill-formed” (19.5 [cpp.error]),
and the only requirement for an ill-formed program is that a diagnostic
be issued; the translation may continue and succeed. (Noted in passing:
if this difference between C99 and C++ is addressed, it would be helpful
for synchronization purposes in other contexts as well to introduce the
term “preprocessing translation unit.”)

897.
_Pragma and extended string-literals

The specification of how the string-literal in a _Pragma
operator is handled does not deal with the new kinds of string literals.
19.9 [cpp.pragma.op] says,

The string literal is destringized by deleting the L
prefix, if present, deleting the leading and trailing double-quotes,
replacing each escape sequence...

The various other prefixes should either be handled or prohibited.

Additional note (October, 2013):

If raw string literals are supported, the question of how to handle
line splicing is relevant. The wording says that “the characters
are processed through translation phase 3,” which is a bit
ambiguous as to whether that includes phases 1 and 2 or not. It would
be better to be explicit and say that the processing of phase 3 or of
phases 1 through 3 is applied.

1944.
New C incompatibilities

Some new features of C++ not only introduce incompatibilities
with previous versions of C++ but also with C; however, the
organization of Annex C [diff] makes it difficult
to specify that a given feature is incompatible with both languages,
and the practice has been only to document the C++ incompatibilities.
Some means of specifying both sets of incompatibilities should be
found, hopefully without excessive duplication between the C and C++
sections.

A is the left operand of a built-in logical AND
(&&, see 8.14 [expr.log.and]) or logical OR
(||, see 8.15 [expr.log.or]) operator, or

...

The intent is that this does not apply to the second operands
of such operators if the first operand is such that they are not
evaluated, but the wording is not clear to that effect. (A similar
question applies to the non-selected operand of the conditional
operator ?:.)

Notes from the October, 2015 meeting:

It appears likely that the text involved will be removed by a
revision to the memory_order_consume specification.

Notes from the February, 2016 meeting:

Action on this issue will be deferred until the specification
for memory_order_consume is complete; it should not currently
be used.

We should really be talking about individual accesses to
“memory locations”. Talking about larger “expression
evaluations” is incorrect, since they may include internal
synchronization. Thus concurrent evaluation of large conflicting
expression evaluations may not actually correspond to a data race.
I'm not sure what term we should be using instead of “expression
evaluation” to denote such individual accesses. Call it
X for now.

There is also an issue with the fact that “sequenced
before” is defined on expression evaluation. “Sequenced
before” should also be defined on Xs. It doesn't make
any sense to talk about “sequenced before” ordering on
two evaluations when one includes the other. Whenever we say
“A is sequenced before B”, we probably
really mean that all Xs in A are sequenced before all
Xs in B. We could probably just include a blanket
statement to that effect.