4
template<typename T>
struct A {
    using U = typename T::U;
    using V = typename T::V; //X
};

struct B {
    using U = int;
    void f() { A<B> a; }   //1
    //A<B> a;              //2
    using V = int;
};

This compiles on current GCC, Clang, MSVC and ICC (https://godbolt.org/z/dvExbxszn).

I would like to know whether this is actually specified to work in the standard. Specifically, where is the point of instantiation of A<B> allowing both B::U and B::V to be looked up?

If we use //2 instead of //1, all four compilers reject the code, but accept if //X is removed. For this case I understand that strict reading of the standard probably makes the program ill-formed even if //X is removed, because the point of instantiation should be above the definition of B. However following the suggested change in CWG 287, compilers allow lookup of A::U which was declared before the point requiring instantiation of A<B>.

With void f() { A<B> a; } however, the instantiation is required from a complete-class context and it seems to me that compilers assume that the point of instantiation is then after the definition of B, so that all names in B are available to lookup in the instantiation. Is this actually specified in the standard or is it a situation analogously to CWG 287 where compilers try to make the instantiations behave like non-template definitions would, against strict interpretation of the standard?

user17732522
  • 53,019
  • 2
  • 56
  • 105
  • 3
    As far as I understand, member function definitions are only looked at after the entire class definition has finished being parsed. It should be equivalent to having the definition after the class with `void B::f() { A a; }`. I can't cite you the relevant language passages though. – François Andrieux Feb 16 '22 at 19:01
  • @FrançoisAndrieux https://eel.is/c++draft/class#mem.general-8 says only that in the definition the class is "_regarded as complete_" in the context and https://eel.is/c++draft/temp.point#4 just says that the point of instantiation is immediately preceding the namespace scope declaration requiring it, which looks like it is before `struct B` to me. – user17732522 Feb 16 '22 at 19:09
  • @FrançoisAndrieux The first sentence of https://eel.is/c++draft/temp.point#4 does not apply, since `A a;` is not inside another template specialization. It is the second sentence that should apply, I think. "_are considered to occur after the end of the class definition_": This seems to be the intuition, but I can't find anything in the standard actually making that explicit. Instead the name lookup rules have special cases for complete-class contexts. `this` is complete in the function definition, because https://eel.is/c++draft/class#mem.general-8.sentence-2 says so specifically. – user17732522 Feb 16 '22 at 19:23
  • 1
    If `B` is required to be complete within `B::f()`'s definition then it implies it is required to be complete for `A a;` which is within that context. Sometimes some language rules are logical deductions from other rules and aren't explicitly written out. This might be one of those cases. – François Andrieux Feb 16 '22 at 19:34
  • [Possible dupe](https://stackoverflow.com/q/57631441)? – JHBonarius Feb 20 '22 at 08:41
  • @JHBonarius No, this question is about the point of instantiation. In the linked question there aren't even any templates involved. – user17732522 Feb 20 '22 at 08:44
  • 1
    Yeah, I'm trying to think along. One of the answers point to the fact that the class definition is complete in the body of the method. So since `A` first occurs there... – JHBonarius Feb 20 '22 at 08:50
  • @JHBonarius Yes, the definition of `f` is in a complete-class context. However, the standard does not seem to say anywhere that this means it behaves as if the definition was defined out-of-class after the class definition. So, lacking this, it seems that the rules for points of instantiations place the instantiation of `A` _above_ the definition of `B`, where `B` is _not_ complete. See standard quotes in the previous comments. – user17732522 Feb 20 '22 at 08:53

0 Answers0