0

I'm getting "was not declared in this scope" errors when trying to compile a library containing heavily templated code. It seems like the code was developed using gcc-2.95, and (as I was told) did compile about four years ago. As I found on StackOverflow and the C++-FAQ the code is indeed expected to fail, and seems to rely on non-conforming compilation.

Minimal reproduction example, compile with gcc -c example.cpp:

// file: example.cpp
template <typename T>
class Base {
  protected:
    int i;
};

template <typename T>
class Derived : protected Base<T> {
  public:
    void f() {
        // i = 5;     // Error: i was not declared in this scope
        this->i = 5;  // compiles
    }
};

My question is: How do I compile this library using more recent compilers?

The library code uses the faulty syntax (i=5) all over the place, so I'd prefer to avoid manually changing the whole library to 'this->i=5'. The provided links suggest 'using' statements, but while that would reduce my work, my preferred method would involve no code changes, but forcing the compiler into the old behaviour of 'assuming this' on these variables. I could not find a compiler-switch for this situation, -std=c++98, -fpermissive etc. didn't work.

Quote from the C++-FAQ:

Perhaps surprisingly, the following code is not valid C++, even though some compilers accept it:

I also tried using CLang++, with the same results. Which compilers would accept this code without changes?

Edit: Added info on -fpermissive, as Brian suggested

DocDrum
  • 21
  • 3
  • Have you tried `-fpermissive`? – Brian Bi Nov 11 '18 at 17:29
  • @πάντα ῥεῖ: that dup seems completely unrelated, this is a dependent name lookup issue or something like that – Mat Nov 11 '18 at 17:32
  • 4
    @DocDrum: fix your code. That's the only viable solution for using modern compilers. – Mat Nov 11 '18 at 17:33
  • 1
    One cannot assume that code is correct and just because it compiled. Even if the compiler has a bug and allows this, there are no guarantees you'll get a usable program. – user4581301 Nov 11 '18 at 17:52

1 Answers1

1

Unfortunately, as @Mat said in the comments, the only viable alternative here is to correct the code (and you've shown you already know how to do that).

This is a result of two-phase name lookup, so to get a compiler to accept it, you need one that doesn't implement two-phase name lookup. With Microsoft's compiler you can use the -Zc:twoPhase- flag to get the old behavior with the current compiler (i.e., to get the compiler to accept your code as-is).

g++ had two-phase name lookup reasonably correct starting with g++ 4.7 if memory serves. I'd be pretty confident that all the g++ 3.x series will still accept your code, and early g++ 4.x probably will as well, but I'm pretty sure g++ 4.7 and later will reject it.

As for Clang--if memory serves, it had two-phase name lookup from the beginning. Early versions undoubtedly had some bugs, so it's barely possible one of them might allow this, but I kind of doubt it--this is pretty much the classic demonstration of when two-phase name lookup broke existing code, so any compiler that tries to implement two-phase name lookup almost certainly has a test case similar to this.

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
  • This is valuable information, thanks for the explanation! we had gcc-4.4 installed until lately, possibly that's the version that was reported as working. I'll try to get a local 4.4 install, before patching in hundreds of 'this->'. – DocDrum Nov 11 '18 at 21:17