New wording for [namespace.memdef]/1 - c++

I believe the new wording for [namespace.memdef]/1 tries to explain the conflict between the two declarations using M::g; and void g(); in namespace X, but I fail to understand the relationship between this new wording and the alluded conflict.
A declaration in a namespace N (excluding declarations in nested
scopes) whose declarator-id is an unqualified-id ([dcl.meaning]),
whose class-head-name (Clause [class]) or enum-head-name
([dcl.enum]) is an identifier, or whose elaborated-type-specifier
is of the form class-key attribute-specifier-seqopt
identifier ([dcl.type.elab]), or that is an opaque-enum-declaration, declares (or redeclares) its unqualified-id or identifier as a member of N. [ Note: An explicit instantiation ([temp.explicit]) or explicit specialization
([temp.expl.spec]) of a template does not introduce a name and thus
may be declared using an unqualified-id in a member of the enclosing
namespace set, if the primary template is declared in an inline
namespace.  — end note ] [ Example:
namespace X {
void f() { /* ... */ } // OK: introduces X​::​f()
namespace M {
void g(); // OK: introduces X​::​M​::​g()
}
using M::g;
void g(); // error: conflicts with X​::​M​::​g()
}
 — end example ]
Even when I look at the DR 1838 which probably gave origin to the change in this paragraph, I have some problems understanding the following sentence (emphasis is mine):
The Standard is not clear about what happens when an entity is
declared but not defined in an inner namespace and declared via a
using-declaration in an outer namespace, and a definition of an entity with that name as an unqualified-id appears in the outer
namespace. Is this a legitimate definition of the inner-namespace
entity, as it would be if the definition used a qualified-id, or is
the definition a member of the outer namespace and thus in conflict
with the using-declaration? There is implementation divergence on
the treatment of such definitions.
The example that follows this sentence is exactly the same as the one in the paragraph [namespace.memdef]/1. I highlighted the word definition above, as there is no definition for the function X::g() in the alluded Example. What am I missing?

Related

VS2015 and clang compile this code, but g++ rejects it. Which one is correct?

VS2015 and clang compile this code, but g++ rejects it.
namespace A {
struct B {
friend void f();
};
}
void A::f() {}
int main(){
}
I think g++ is right because of this Note in 7.3.1.2/3:
If a friend declaration in a non-local class first declares a class,
function, class template or function template97 the friend is a member
of the innermost enclosing namespace. The friend declaration does not
by itself make the name visible to unqualified lookup
([basic.lookup.unqual]) or qualified lookup ([basic.lookup.qual]).
[ Note: The name of the friend will be visible in its namespace if a
matching declaration is provided at namespace scope (either before or
after the class definition granting friendship).  — end note ] If a
friend function or function template is called, its name may be found
by the name lookup that considers functions from namespaces and
classes associated with the types of the function arguments
([basic.lookup.argdep]). If the name in a friend declaration is
neither qualified nor a template-id and the declaration is a function
or an elaborated-type-specifier, the lookup to determine whether the
entity has been previously declared shall not consider any scopes
outside the innermost enclosing namespace. [ Note: The other forms of
friend declarations cannot declare a new member of the innermost
enclosing namespace and thus follow the usual lookup rules.  — end
note ]
This part of your quote is more definitive than the note you emphasized:
The friend declaration does not by itself make the name visible to unqualified lookup ([basic.lookup.unqual]) or qualified lookup ([basic.lookup.qual]).
Your definition relies on qualified lookup to find a function already declared inside the namespace. But the name is not visible to qualified lookup. This code should be rejected.
Here's a related rule, found in secion 8.3 [dcl.meaning]:
When the declarator-id is qualified, the declaration shall refer to a previously declared member of the class or namespace to which the qualifier refers (or, in the case of a namespace, of an element of the inline namespace set of that namespace) or to a specialization thereof; the member shall not merely have been introduced by a using-declaration in the scope of the class or namespace nominated by the nested-name-specifier of the declarator-id .

Where in the Standard does it say that a member alias-declaration can be used as if it was a static member?

Consider the following snippet:
#include <iostream>
struct A { int i; using Int = int; };
int main()
{
std::cout << sizeof(A::Int) << '\n';
}
It compiles and executes normally in clang and GCC. I know this looks obvious, but I couldn't find anything in the Standard (C++14) supporting the reference to A::Int in main().
This is just your normal qualified lookup. From [basic.lookup.qual]:
The name of a class or namespace member or enumerator can be referred to after the :: scope resolution
operator (5.1) applied to a nested-name-specifier that denotes its class, namespace, or enumeration.
Then from [class.qual]:
If the nested-name-specifier of a qualified-id nominates a class, the name specified after the nested-namespecifier
is looked up in the scope of the class (10.2), except for the cases listed below. The name shall
represent one or more members of that class or of one of its base classes (Clause 10). [ Note: A class member
can be referred to using a qualified-id at any point in its potential scope (3.3.7). —end note ] The exceptions
to the name lookup rule above are the following:
a destructor name [...]
a conversion-type-id of a conversion-function-id [...]
the names in a template-argument of a template-id [...]
the lookup for a name specified in a using-declaration [...]
The nested-name-specifier in your example is A, which is a class. None of those exceptions apply. So we just look up the name, Int, in the scope of class.
From [dcl.typedef]:
A name declared with the typedef specifier becomes a typedef-name. Within the scope of its declaration, a
typedef-name is syntactically equivalent to a keyword and names the type associated with the identifier in
the way described in Clause 8. A typedef-name is thus a synonym for another type.
[...]
A typedef-name can also be introduced by an alias-declaration. The identifier following the using keyword
becomes a typedef-name and the optional attribute-specifier-seq following the identifier appertains to that
typedef-name. It has the same semantics as if it were introduced by the typedef specifier.
So your alias-declaration introduces the name Int into the scope of A, which is found according to the qualified lookup rules I just enumerated.

Declaring an incomplete type template parameter in place in-the argument list

I have seen use like:
boost::error_info<struct tag_name, std::string> name_info;
Here tag_name names an incomplete type and the struct keyword preceding it seems to declare it in-place, instead of the slightly more verbose:
struct tag_name;
boost::error_info<tag_name, std::string> name_info;
What is the relevant part of the standard that allows this?
§3.4.4/2 specifies how elaborated-type-specifiers, in any situation, are looked up and what effect they may have:
If the elaborated-type-specifier is introduced by the class-key and
this lookup does not find a previously declared type-name [..] the
elaborated-type-specifier is a declaration that introduces the
class-name as described in 3.3.2.
Then §3.3.2/7(.2) reads
The point of declaration of a class first declared in an elaborated-type-specifier is as follows: [..]
for an elaborated-type-specifier of the form
class-key
identifier
if the elaborated-type-specifier is used in the decl-specifier-seq or
parameter-declaration-clause of a function defined in namespace scope,
the identifier is declared as a class-name in the namespace that
contains the declaration; otherwise, except as a friend declaration,
the identifier is declared in the smallest namespace or block scope
that contains the declaration.

Where am I wrong here? The lookup for the name Node finds the injected-class-name for the struct Node

I'm in doubt about the first comment in the Example at §3.4.4/3 (C++14):
struct Node {
struct Node* Next; // OK: Refers to Node at global scope
struct Data* Data; // OK: Declares type Data
// at global scope and member Data
};
From §3.3.2/7 (see below), one concludes that the comment is correct, because the global namespace is the smallest namespace containing the declaration struct Node* Next;.
§3.3.2/7 (my emphasis)
The point of declaration of a class first declared in an
elaborated-type-specifier is as follows:
for a declaration of the form
class-key attribute-specifier-seqopt identifier ;
the identifier is declared to be a class-name in the scope that
contains the declaration, otherwise
for an elaborated-type-specifier of the form
class-key identifier
if the elaborated-type-specifier is used in the decl-specifier-seq or parameter-declaration-clause of a function defined in namespace scope, the identifier is declared as a
class-name in the namespace that contains the declaration; otherwise, except as a friend declaration, the identifier is declared in the smallest namespace or block scope that contains the
declaration. [ Note: These rules also apply within templates. —end
note ] [ Note: Other forms of elaborated-type-specifier do not
declare a new name, and therefore must refer to an existing
type-name. See 3.4.4 and 7.1.6.3. —end note ]
However from §3.4.4/2 (see below) I get the impression that the lookup for the name Node finds the injected-class-name Node, so it can't refer to Node in the global scope.
§3.4.4/2 (my emphasis)
If the elaborated-type-specifier has no nested-name-specifier, and
unless the elaborated-type-specifier appears in a declaration with
the following form:
class-key attribute-specifier-seqopt identifier ;
the identifier is looked up according to 3.4.1 but ignoring any non-type names that have been declared. If the
elaborated-type-specifier is introduced by the enum keyword and this lookup does not find a previously declared type-name, the
elaborated-type-specifier is ill-formed. If the elaborated-type-specifier is introduced by the class-key and this lookup does not find a previously declared type-name, or if the
elaborated-type-specifier appears in a declaration with the form:
class-key attribute-specifier-seqopt identifier ;
the elaborated-type-specifier is a declaration that introduces the
class-name as described in 3.3.2.
The first sentence of [basic.scope.pdecl]/7 makes clear that that paragraph deals with a class first declared in an elaborated-type-specifier; it is therefore not applicable to the struct Node in struct Node* Next;, because Node is not first declared in that elaborated-type-specifier.
Instead, the unqualified name lookup for Node does find the injected-class-name (see [basic.lookup.unqual]/p1 and 7.1) rather than ::Node. You'll need to write some rather contrived code for this to matter, though. For example:
struct A {};
struct B : private A {};
struct C : public B {
struct A m_a; // error: A is the inaccessible injected-class-name, not ::A
struct ::A m_a2; // OK
};
Note that GCC accepts this code, which I believe is a bug.
The passage from 3.3.2 is about declaring classes, not objects.
Your declaration struct Node* Next cannot possibly match "class-key identifier"; the latter only matches literally half of the tokens in the former.

Declaration and definition in c++

I thought that every declaration is definition because there was the following quote from standard:
A declaration is a definition unless %restrictions%.
But my assumption is not true. Actually, applying ODR we have that the following program
class A;
class A;
int main(){ }
is ill-formed. But it is not true. I can't to find part of standard which permit to redeclare class type in the declarative region.
Yes, "a declaration is a definition unless %restrictions%" is true. Have you read the restrictions? One of them is:
it is a class name declaration
So class A; is not a definition because it is covered by one of the restrictions.
Just to clarify, quoting C++11, [basic.def]§2
Your quote (from C++11 3.1/2) answers the general question: "unless %restrictions%" means that not every declaration is a definition. It's only a definition if none of those restrictions apply.
If you read those restrictions, you'll find
it is a class name declaration
which answers your specific question. class A; is a class name declaration, but not a definition.
I can't to find part of standard which permit to redeclare class type in the declarative region.
In general, you can declare an entity multiple times in the same declarative region, per C++11 3.3.1/4
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 [other cases not relevant here]
The paragraph § 3.1.2 states that
A declaration is a definition unless it declares a function without
specifying the function’s body (8.4), it contains the extern specifier
(7.1.1) or a linkage-specification 25 (7.5) and neither an initializer
nor a function- body, it declares a static data member in a class
definition (9.2, 9.4), it is a class name declaration (9.1), it is an
opaque-enum-declaration (7.2), it is a template-parameter (14.1), it
is a parameter-declaration (8.3.5) in a function declarator that is
not the declarator of a function-definition, or it is a typedef
declaration (7.1.3), an alias-declaration (7.1.3), a using-declaration
(7.3.3), a static_assert-declaration (Clause 7), an attribute-
declaration (Clause 7), an empty-declaration (Clause 7), or a
using-directive (7.3.4).
Here
class A;
class A;
int main(){ }
it is a class name declaration.
In a statement
A declaration is a definition unless %restrictions%.
the %restrictions%. part is important.
I thought that every declaration is definition
Let's prove that this is not true by a contradiction. So assume this is true. Then because we can have many redeclaration and every of this declarations is definition - we can have many redefinitions, right? But C++ Standard n3337 § 3.2/1 says
No translation unit shall contain more than one definition of any
variable, function, class type, enumeration type, or template.
what contradicts our assumption and thus this is not true that every declaration is definition.
Consider the case of:
Header1.h:
class A;
void function1(A * a);
Header2.h:
class A;
void function2(A * a);
main.cpp
#include "Header1.h"
#include "Header2.h"
#include "A.h" // header file defining A
int main()
{
}
what this really looks like to the compiler is:
class A;
void function1(A * a);
class A;
void function2(A * a);
class A { /* definition from A.h */ };
int main()
{
}