2

I'm having the weirdest error and I've no idea what I'm doing wrong.

template <bool X>
struct A {
    int x;
};

template <bool X>
struct B : public A<X> {
    B() { x = 3; } // Error: 'x' was not declared in this scope.
};

I don't understand how it's possible that I cannot see x from B, given that I'm inheriting A publicly.

At the same time, this code compiles:

template <bool X>
struct A {
    int x;
};

template <bool X>
struct B : public A<X> {};

int main() {
    B<false> b;
    b.x = 4;
};

I'm compiling with g++ 7.0.1.

Edit: It seems that if I reference the full-name of x, the code compiles, as in:

B() { A<X>::x = 3; }

But why?

Svalorzen
  • 5,353
  • 3
  • 30
  • 54
  • Not that it helps, but MSVC has an extension that compiles this. :o – wally Sep 17 '17 at 20:40
  • 1
    MSVC was always single pass. They **JUST** changed that to be compliant with the standard. https://blogs.msdn.microsoft.com/vcblog/2017/09/11/two-phase-name-lookup-support-comes-to-msvc/ – Khouri Giordano Sep 17 '17 at 20:43
  • MSVC does produce an error if I turn off the language extensions. So at least compliant behavior is available. – wally Sep 17 '17 at 20:45

1 Answers1

2

The compiler doesn't know how to find x. Use this->X and it will work.

At the time the compiler is doing its first pass over struct B, the template parameter is not known. By using the this pointer, you are deferring the name lookup until the second pass.

Khouri Giordano
  • 1,426
  • 15
  • 17