Why Does the Standard C++ Grammar Not Cover this Case? - c++

I am mainly referring to the C++03 standard but, after a quick glance, it should also be applicable to the C++11 standard.
The following code compiled and executed successfully in VC++2010:
template<typename T>
class CC {
public:
T f(T a) {
return a*a;
}
};
template<>
class ::CC<int> { //<--- ::CC<int> syntax allowed by VC++2010, but is it non-standard ?
public:
int f(int a) {
return a*a;
}
};
int main(int argc, _TCHAR* argv[])
{
::CC<int> c;
}
Notice the ::CC<int> syntax to refer to the template defined in the global namespace. This is not the same as the NamespaceA::CC<int> syntax where the :: operator is preceded by something. With some other tools, I tried to parse this using the grammar strictly from the C++03 but it gave me errors and it seems to me that the standard accepts only NamespaceA::CC<int> form in the class head declaration.
On a closer look, the issue is that the class-head is defined by this grammar in the standard:
class-head:
class-key identifier(optional) base-clause(optional)
class-key nested-name-specifier identifier base-clause(optional)
class-key nested-name-specifier(optional) template-id base-clause(optional)
And since nested-name-specifier is of the form AA::bb::..., it doesn't accept my ::CC.
My question is, why the C++ standard doesn't allow the ::CC form? Is it just my incorrect interpretation of the standard grammar? Should the proper grammar looks like this:
class-head:
...
class-key '::'(optional) nested-name-specifier(optional) template-id base-clause(optional)
Note, the above form is really used by the standard somewhere else, say, in specifying declarator-id:
declarator-id:
id-expression
::(optional) nested-name-specifier(optional) class-name

From a comment by Columbo,
Of course a nested-name-specifier can be ::, and CC is the identifier, …?
That is not the case, at least not in the context of this question. Up until the 2014 version of the C++ standard, a bare double semicolon did not qualify as a nested-name-specifier. The 2003 version of the standard said a nested-name-specifier took on one of the two forms, in BNF:
class-or-namespace-name :: nested-name-specifieropt
class-or-namespace-name :: template nested-name-specifier
There was no room for a bare class ::CC to fit into this specification. The 2011 version added quite a bit to the BNF for a nested-name-specifier:
::opt type-name ::
::opt namespace-name ::
decltype-specifier ::
nested-name-specifier identifier ::
nested-name-specifier templateopt simple-template-id ::
This still left no room for class ::CC. The 2014 version of the standard finally addressed this by saying a nested-name-specifier is one of
::
type-name ::
namespace-name ::
decltype-specifier ::
nested-name-specifier identifier ::
nested-name-specifier templateopt simple-template-id ::
There are a number of ways to look at this interesting "feature". One is that this is a longstanding bug in the language specification, first identified in 2002 as issue #355. One of the jobs of a compiler vendor is to identify and patch over bugs in the language specification, and then get those bugs fixed in an upcoming release of the standard. From this point of view, template<> class ::CC<int> {...} should compile.
An alternative point of view is that this was not a bug. The BNF for a nested-name-specifier in both the 2003 and 2011 versions of the standard were quite clear, and thus template<> class ::CC<int> {...} should not compile. Whether this was an unfortunate misfeature or a deliberate feature didn't matter. The code in the question should not compile from the perspective of this point of view.
Which point of view is correct is debatable. That the issue that first reported this discrepancy was not rejected was a sign that there was some meat to that report. On the other hand, that nothing was done about it through two revisions of the standard also says something.
That said, now that the standard has been clarified, there is a bug in newer releases of GCC because even if one specifies --std=c++14, they do not allow template<> class ::CC<int> {...} to compile.

In the C++ draft, the nested-name-specifier is mentioned in [class].11:
If a class-head-name contains a nested-name-specifier, the class-specifier shall refer to a class that was previously declared directly in the class or namespace to which the nested-name-specifier refers, or in an element of the inline namespace set ([namespace.def]) of that namespace (i.e., not merely inherited or introduced by a using-declaration), and the class-specifier shall appear in a namespace enclosing the previous declaration. In such cases, the nested-name-specifier of the class-head-name of the definition shall not begin with a decltype-specifier.
And it can of course also be :: according to [expr.prim.id.qual].
In your code, you're using class ::CC<int> in a template class specialization, for which [temp.expl.spec].2 also applies:
An explicit specialization shall be declared in a namespace enclosing the specialized template. An explicit specialization whose declarator-id or class-head-name is not qualified shall be declared in the nearest enclosing namespace of the template, or, if the namespace is inline ([namespace.def]), any namespace from its enclosing namespace set. Such a declaration may also be a definition. If the declaration is not a definition, the specialization may be defined later ([namespace.memdef]).
Hence, I think, using a qualified name should be okay.

Related

Why does clang warn about namespaced out-of-line destructor definition? [duplicate]

Recent versions of clang (since clang-11) issue a warning when compiled with -pedantic for the following segment of code:
namespace foo {
template <int A>
struct Bar {
~Bar();
};
} // namespace foo
template <int A>
foo::Bar<A>::~Bar(){}
With the generated warning (and error with -Werror) being:
<source>:10:12: error: ISO C++ requires the name after '::~' to be found in the same scope as the name before '::~' [-Werror,-Wdtor-name]
foo::Bar<A>::~Bar(){}
~~~~~~~~~~~^~
::Bar
Live Example
clang is the first compiler I've seen to issue this diagnostic, and as far as I'm aware, what was written above is completely valid C++. Two different ways that seem to suppress this is to either define within the same namespace or explicitly qualify the destructor name -- such as:
...
template <int A>
foo::Bar<A>::~Bar<A>(){}
Is Clang's diagnostic here correct? It's my understanding that the type's name would absolutely be in the correct name-scope as foo::Bar<A>::~ -- and that the qualification of ~Bar<A>() should be unnecessary.
From what I have learned since posting the question, this warning is, strictly-speaking, correct -- though it most likely a defect in the wording of the standard.
According to Richard Smith in LLVM Bug 46979:
The diagnostic is correct, per the standard rules as written; strictly-speaking, the C++ rules require this destructor to be written as
template<typename T>
A::B<T>::~B<T>()
Per C++ [basic.lookup.qual]p6:
In a qualified-id of the form:
nested-name-specifier[opt] type-name :: ~ type-name
the second type-name is looked up in the same scope as the first.
This means that the second B is looked up in class A, which finds only the class template B and not the injected-class-name.
This is not an especially useful rule, and likely isn't the intended rule, which is why this diagnostic (along with a bunch of similar diagnostics for plausible but formally incorrect destructor names) is disabled by default but included in -pedantic.
Looking further into this, I can find the mentioned passage for [basic.lookup.qual]/6 in the C++20 standard, but it appears drafts for C++23 have changed this -- which points towards this most likely being a defect.
In drafts for [basic.lookup.qual] for C++23, this whole section has been overhauled and is currently, at the time of writing, replaced with [basic.lookup.qual]/4 which states:
If a qualified name Q follows a ~:
(4.1) If Q is a member-qualified name, it undergoes unqualified lookup as well as qualified lookup.
(4.2) Otherwise, its nested-name-specifier N shall nominate a type.
If N has another nested-name-specifier S, Q is looked up as if its lookup context were that nominated by S.
(4.3) Otherwise, if the terminal name of N is a member-qualified name M, Q is looked up as if ~Q appeared in place of M (as above).
(4.4) Otherwise, Q undergoes unqualified lookup.
(4.5) Each lookup for Q considers only types (if Q is not followed by a <) and templates whose specializations are types.
If it finds nothing or is ambiguous, it is discarded.
(4.6) The type-name that is or contains Q shall refer to its (original) lookup context (ignoring cv-qualification) under the interpretation established by at least one (successful) lookup performed.
[Example 4:
struct C {
typedef int I;
};
typedef int I1, I2;
extern int* p;
extern int* q;
void f() {
p->C::I::~I(); // I is looked up in the scope of C
q->I1::~I2(); // I2 is found by unqualified lookup
}
struct A {
~A();
};
typedef A AB;
int main() {
AB* p;
p->AB::~AB(); // explicitly calls the destructor for A
}
— end example]
(The full quote has been posted here since this is from a draft, and the wording may be subject to change in the future)
This appears to explicitly correct this issue by ensuring that lookup is performed as one would expect.
So basically the diagnostic is correct under older versions of C++ due to a defect in the wording -- but C++23 appears to change that. I am not sure whether this will be retroactively fixed in older versions as a defect given that it appears no compiler actually follows this pedantic requirement.

Is a class template's name in scope for a qualified out-of-line destructor's definition?

Recent versions of clang (since clang-11) issue a warning when compiled with -pedantic for the following segment of code:
namespace foo {
template <int A>
struct Bar {
~Bar();
};
} // namespace foo
template <int A>
foo::Bar<A>::~Bar(){}
With the generated warning (and error with -Werror) being:
<source>:10:12: error: ISO C++ requires the name after '::~' to be found in the same scope as the name before '::~' [-Werror,-Wdtor-name]
foo::Bar<A>::~Bar(){}
~~~~~~~~~~~^~
::Bar
Live Example
clang is the first compiler I've seen to issue this diagnostic, and as far as I'm aware, what was written above is completely valid C++. Two different ways that seem to suppress this is to either define within the same namespace or explicitly qualify the destructor name -- such as:
...
template <int A>
foo::Bar<A>::~Bar<A>(){}
Is Clang's diagnostic here correct? It's my understanding that the type's name would absolutely be in the correct name-scope as foo::Bar<A>::~ -- and that the qualification of ~Bar<A>() should be unnecessary.
From what I have learned since posting the question, this warning is, strictly-speaking, correct -- though it most likely a defect in the wording of the standard.
According to Richard Smith in LLVM Bug 46979:
The diagnostic is correct, per the standard rules as written; strictly-speaking, the C++ rules require this destructor to be written as
template<typename T>
A::B<T>::~B<T>()
Per C++ [basic.lookup.qual]p6:
In a qualified-id of the form:
nested-name-specifier[opt] type-name :: ~ type-name
the second type-name is looked up in the same scope as the first.
This means that the second B is looked up in class A, which finds only the class template B and not the injected-class-name.
This is not an especially useful rule, and likely isn't the intended rule, which is why this diagnostic (along with a bunch of similar diagnostics for plausible but formally incorrect destructor names) is disabled by default but included in -pedantic.
Looking further into this, I can find the mentioned passage for [basic.lookup.qual]/6 in the C++20 standard, but it appears drafts for C++23 have changed this -- which points towards this most likely being a defect.
In drafts for [basic.lookup.qual] for C++23, this whole section has been overhauled and is currently, at the time of writing, replaced with [basic.lookup.qual]/4 which states:
If a qualified name Q follows a ~:
(4.1) If Q is a member-qualified name, it undergoes unqualified lookup as well as qualified lookup.
(4.2) Otherwise, its nested-name-specifier N shall nominate a type.
If N has another nested-name-specifier S, Q is looked up as if its lookup context were that nominated by S.
(4.3) Otherwise, if the terminal name of N is a member-qualified name M, Q is looked up as if ~Q appeared in place of M (as above).
(4.4) Otherwise, Q undergoes unqualified lookup.
(4.5) Each lookup for Q considers only types (if Q is not followed by a <) and templates whose specializations are types.
If it finds nothing or is ambiguous, it is discarded.
(4.6) The type-name that is or contains Q shall refer to its (original) lookup context (ignoring cv-qualification) under the interpretation established by at least one (successful) lookup performed.
[Example 4:
struct C {
typedef int I;
};
typedef int I1, I2;
extern int* p;
extern int* q;
void f() {
p->C::I::~I(); // I is looked up in the scope of C
q->I1::~I2(); // I2 is found by unqualified lookup
}
struct A {
~A();
};
typedef A AB;
int main() {
AB* p;
p->AB::~AB(); // explicitly calls the destructor for A
}
— end example]
(The full quote has been posted here since this is from a draft, and the wording may be subject to change in the future)
This appears to explicitly correct this issue by ensuring that lookup is performed as one would expect.
So basically the diagnostic is correct under older versions of C++ due to a defect in the wording -- but C++23 appears to change that. I am not sure whether this will be retroactively fixed in older versions as a defect given that it appears no compiler actually follows this pedantic requirement.

Does the use a simple-template-id in a nested-name-specifier unambiguously mean a class template specialization?

struct A{
template<typename U>
void T(){}
};
struct B{
template<typename U>
struct T{
using type = U;
};
};
struct C:A,B{
};
int main(){
C::T<int>::type d;
}
This example is accepted by neither GCC nor Clang.
As per basic.lookup.qual#1
The name of a class or namespace member or enumerator can be referred to after the​::​ scope resolution operator ([expr.prim.id.qual]) applied to a nested-name-specifier that denotes its class, namespace, or enumeration. 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.
That means that when looking up the declarations for the template name T, the specialization of T shall denote a type in this context. On the other hand, as per class.member.lookup#4
If C contains a declaration of the name f, the declaration set contains every declaration of f declared in C that satisfies the requirements of the language construct in which the lookup occurs.
Again, when looking up the template T in the scope of C, only those templates whose specialization is a type should be considered by this lookup. The scope of C does not have any declarations for T, hence the lookup will be performed for S(T,C) in every one of its base classes. The template T in A does not satisfy the requirement. Meanwhile, the template T declared in the scope of B does satisfy the requirement. So the lookup is not ambiguous and the B::T is the unique result. That means C::T<int>::type d should be well-formed. Why do both GCC and Clang reject this example? Can it be considered a bug of in both? If I missed something, what's the reason that this example should be ill-formed?
The lookahead required to have the lookup for T depend on the :: even as the interpretation of < depends on the meaning of T is considered undesirable. As such, lookup for a name followed by < is not restricted to types and namespaces regardless of any >:: found later. P1787R6 fixed this, restricting the special lookup to identifiers immediately followed by :: (since other kinds of names can’t refer to types or namespaces anyway).

typename keyword and nested name specifier

struct A{};
template <typename T>
struct B
{
typename ::A a1; //(1)
typename A a2; //(2): error
};
int main(){return 0;}
Why is the first case correct, but the second isn't? I don't understand the meaning of that restriction.
And anyway, why is the first case allowed? ::A isn't template-parameter dependent name. What's meaning in it?
The rule isn't that you can only use typename if the type is nested in a dependent scope. The rules are, more or less:
you must use typename if it's in a dependent scope
you can only use typename where it's allowed by the grammar.
The grammar allows it for a subset of qualified-id, specified by
typename-specifier:
typename nested-name-specifier identifier
typename nested-name-specifier template<opt> simple-template-id
nested-name-specifier:
:: (C++14 or later)
::<opt> type-name ::
::<opt> namespace-name ::
decltype-specifier ::
nested-name-specifier identifier ::
nested-name-specifier template<opt> simple-template-id ::
So the second case is certainly forbidden, since it doesn't involve any nesting. Strictly speaking, before C++14, the first was also forbidden, since a global qualifier :: didn't match that grammar.
As #MikeSeymour's answer explains, going strictly by the standard (C++11, I don't have a C++14 text on hand), case (1) should actually be erroneous as well - typename prefixing a qualified name can only be used when there's at least one name on the left-hand side of the ::.
However, as pointed out by #hvd in the comments, CWG issue 382 indicates the actual intent is to allow typename before any qualified name, including global-namespace qualification. Since this is what most compilers seem to implement, the rest of this answer follows with this idea.
When viewed like this, it's not that case (2) is a restriction, it's that case (1) is benevolence. The required rule (and its very original wording, I believe) is basically that "if a qualified name which depends on template parameters denotes a type, you must prefix it with typename." For convenience, it is loosened to "typename can be used for any qualified name which dentoes a type, whether it's dependent or not."(1)
In contrast, an unqualified name can never be ambiguous as to whether it refers to a type or not, so it never requires typename and typename is therefore not allowed there.
(1)This loosening is not really explicitly stated in the standard, but follows from the combination of several rules. Basically, wherever a simple-type-specifier (something which denotes a type) is allowed, the grammar also allows a typename-specifier (a qualified name prefixed with typename). The rules for templates (mainly in 14.6) only state that typename is required when a dependent qualified name denotes a type. Since nothing forbids typename in other contexts, it can be used with any qualified name which denotes a type (even outside of template context).

Name lookup of first namespace name in nested-name-specifier?

Given a nested-name-specifier A:: in a translation unit that doesn't have any classes, templates, enumerations, or typedefs, if well-formed, the identifier A must refer to a namespace.
For example:
namespace X
{
int i;
}
int main()
{
X::i = 42; // Here X:: is a nested-name-specifier
// and X is a namespace-name
// i is looked up qualified w.r.t. X
}
In the above example A is X, however my question is about the general case.
How does name lookup proceed for a namespace-name A in A::?
The name lookup rules are summarized in 3.4, but it isn't clear to me how (or which ones) that apply in such a situation.
For example, is the lookup of A an unqualified name lookup? Does 3.4.1 apply to it?
Put another way: Which namespaces are searched for a namespace named A, and in what order? How did you conclude this from the standard?
Yes, A is a regular unqualified name lookup per 3.4.1, successively searching the scopes enclosing the nested-name-specifier, with the exception that only classes and namespace names are found. For example, you could have this:
int main()
{
int X;
X::i = 42; // OK, int X not found.
}
http://ideone.com/NaEIVd
Actually using this loophole is not recommended; if X were an object of class type then X::i and X.i could be completely different things.
To arrive at this conclusion from the Standard, start at 3.4.3 (qualified lookup, which is the high-level construct we're ultimately analyzing), which says in paragraph 1,
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. 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.
Reading on to paragraph 2, it doesn't apply because the qualified-id isn't being declared. The remaining paragraphs likewise specify inapplicable exceptions. So, what is the thing preceding the ::? Refer to the grammar.
nested-name-specifier:
::
type-name ::
namespace-name ::
decltype-specifier ::
nested-name-specifier identifier ::
nested-name-specifier templateopt simple-template-id ::
Only type-name :: and namespace-name :: match our a priori criteria. Also these overlap with what we've found so far. How is a type-name or namespace-name usually resolved in a particular context? Unqualified lookup. Proceed to 3.4.1.
First, 3.4.1/1 is a general rule to bear in mind:
In all the cases listed in 3.4.1, the scopes are searched for a declaration in the order listed in each of the respective categories; name lookup ends as soon as a declaration is found for the name. If no declaration is found, the program is ill-formed.
The next applicable paragraph is 6:
A name used in the definition of a function following the function’s declarator-id that is a member of namespace N (where, only for the purpose of exposition, N could represent the global scope) shall be declared before its use in the block in which it is used or in one of its enclosing blocks (6.3) or, shall be declared before its use in namespace N or, if N is a nested namespace, shall be declared before its use in one of N’s enclosing namespaces.
This rule doesn't tell us to actually search in the global namespace for the name, but it does mention the function's enclosing namespace (in this case the global one) in a list, and paragraph 1 says to search listed namespaces. So that's sufficient to construct a name lookup.
What it surprisingly doesn't do is mention a recursive search prioritizing inner, enclosed namespaces, but you don't actually have such a thing in your example so I'll stop here :) . It's much faster to leave compiling to the compiler, and work manually only in case of a problem.
In the example you gave, X would be considered an unqualified name lookup. And as such it does follow the rules in 3.4.1
In this case the namespaces searched are as follows:
The local namespace of the main() function prior to the definition. (In which a namespace may not be defined per 7.3.1.4.)
The global namespace.
I'm afraid I can't point to a place in the standard where it specifically says namespace names are the same as any other name. But they are. The name lookup doesn't know that's a namespace name (it could be a class name or a struct name) until it actually finds a namespace with that name.