New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Nested-name-specifier is not mentioned for member definition outside its target scope #4592
Comments
These permissions are, in fact, just redeclarations that happen to be definitions. The generic redeclaration rules handle these cases, I believe. |
I doubt that these rules in the above are intended to be covered by [dcl.meaning]. However, it's not explicitly. I have to try to read [dcl.meaning] more carefully to check whether the meaning is readable. |
I think what are you looking for is [expr.prim.id.qual]/2 and /3. (Yes, it is an unexpected place for declaration rules). |
[expr.prim.id.qual]/2 and /3 are basiclly introducing the concept about declarative nested-name-specifier, it is useful for determining where can the declaration inhabit. It didn't state that we should redeclare the member by using nested-name-specifier. |
By what other means would you possibly refer to that member? If you omit the declarative nested-name-specifier, you're not redeclaring the entity you introduced inside the class or namespace definition. See [dcl.meaning.general] p3.4, and [basic.scope.scope] p3 for "correspond". |
After reading [dcl.meaning] carefully, It is not necessary to be used to interpret the following rules, I think [basic.link#8] is sufficient to interpret that struct A{
void fun(); //#1
};
void fun(){} //#2
namespace N {
template<class>
struct A {
struct B;
};
}
using N::A;
template<> struct A<void> {}; // error: A not nominable in :: the declarator
As per module.reach#3, the primary template is indeed reachable at the point where the explicit specialization defined. In my humble opinion, it still no rule that explicitly interprets why the case is an error. Moreover, the note in the example seems not reasonable, since |
After comparing P1787r5 and P1787r6, there's a quite different for [class#pre-3] between them. In P1787r5, it says
While in P1787r6(i.e, be adopted by the current draft)
It appears to me that the rule in P1787r5 is more clear except that it is unclear whether an explicit specialization declaration corresponds to its primary template declaration since an explicit specialization does not introduce a name, hence it does not satisfy the requirement for that two declarations are corresponding. The remaining sentence can indicate the reason why Is that consider how to interpret the example below the rule when changing [class#pre-3] in P1787r5 to the current content? Please take a look at this issue @opensdh @jensmaurer @languagelawyer |
A class-head-name is not a declarator. I think you're right, however, that [class.pre]/3 is inconsistent with its example. From my best reading of the minutes of the discussion on the subject, the example is just wrong (despite being added at the same time as the aforementioned change to the paragraph): both class definitions should just be Meanwhile, that change removed the rule that specified the target scope for a template specialization/instantiation. That doesn't matter for the correspondence check, since that was removed too, but it is necessary to back up the note in [temp.pre]/7. I'll add that to my list of fixups for P1787. |
Appreciate your clarification. That means that the definition of a partial/explicit specialization for a class template does not have to inhabit a scope where the primary class template is nominable; The partial/explicit specialization can also be defined at a scope in which the lookup will find the class template name, as the issue [defines a member of a namespace without using nested-name-specifier] pointed out before P1787 goes into the standard, no matter what kind of declaration would make the name be found(in the formal example, that's |
@jensmaurer @opensdh Although the example is clarified to be "ok", but it looks like there's no relationship between [class.pre#3] and that example since there's no powerful evidence in [class.pre#3] states this example. As @opensdh has pointed out,
As we see in [dcl.meaning], it explicitly points out which cases are necessary to be looked up and which are not, such as
A similar way for wording the rule of [namespace.def]
So, could we extend the [class.pre#3] by adding the relevant rule for that example?
I think the "otherwise part" would cover this example. |
It's certainly correct. @xmh0511 makes a valid point that the connection to the normative text is somewhat lacking; it might be good to extend the example slightly to illustrate the differences like so: namespace N {
struct X;
template<class>
struct A {
struct B;
};
}
namespace O {using N::X;}
using N::A;
struct O::X {}; // error: X not nominable in O
template<class T> struct A<T>::B {}; // OK
template<> struct ::A<void> {}; // OK
Either that or just specify the (reuse of the) target scope for all template specializations/instantiations. We don't need an explicit appeal to name lookup, because [basic.lookup.unqual]/4 and [basic.lookup.qual.general]/3 say that it happens everywhere by default. (It's true that [basic.lookup.general]/1 is a bit optimistic with the word "uniformly": I guess it means all kinds of names.) |
IMHO, I think target scope might not suitable here. For instance, namespace N {
template<class>
struct A {
};
}
using N::A;
template<> struct A<void> {}; //#1 The target scope of the declaration at
There's no otherwise place that states what is the target scope of an instantiation/explicit specialization. Does that mean the explicit instantiation/specialization and its primary template can have a different target scope? Although, this point(whether they shall have the same target scope) is not specified in the standard. |
That's the problem I've already identified, yes. |
That will no something worry about if the issue has recorded in your fixed list. Please word the rule for stating what the target scope of an
has been removed from the current standard. I think it might also be necessary to be clarified. |
"placed in the namespace" never meant anything anyway, as far as I'm aware. |
Yes. I mean we could use these terminologies introduced by P1787 to give meaning to what the target scope of an (explicit/implicit)instantiation / explicit specialization would be. |
Record: namespace N {
template<class>
struct A {
};
}
using namespace N;
template<> struct A<void>{}; // ok #1
// template struct A<int>; // #2 The explicit instantiation at |
In c++20 standard, For the member functions or static member data which are these members that can be defined outside its enclosing class, it has a normative rule for how to define them outside the enclosing class, they are
For member functions
class#mfct-3
For static data member
class#static.data-3
As well as the definition of members of a namespace
namespace.memdef#2
I tried to find out the alternative normative rule in the current draft that can replace these omission rules, however, I don't find them out. Is it considered a bit radical modification that excises these rules?
The text was updated successfully, but these errors were encountered: