c++ enum scope failed to compile with -std=c++98, but ok with -std=c++11

Viewed 967

A simple program as below, no c++11 syntax at all (e.cpp)

#include<iostream>
using namespace std;
namespace m{
class my{
public:
    enum A{
        u=1,
        v=2,
        w=3
    };
    static A f(A a){
        return (A)(a + A::u);
    }
};
int main(){
    using namespace m;
    my::A r=my::f(my::u);
    return 0;
}

Using g++4.1.2 to compile it:

e.cpp:17:2: warning: no newline at end of file
e.cpp: In static member function ‘static m::my::A m::my::f(m::my::A)’:
e.cpp:11: error: expected primary-expression before ‘)’ token
e.cpp:11: error: ‘A’ is not a class or namespace

Using g++4.9.2 with -std=c++98

g++ e.cpp -std=c++98
e.cpp: In static member function ‘static m::my::A m::my::f(m::my::A)’:
e.cpp:11:36: error: ‘A’ is not a class or namespace
    static A f(A a){return (A)(a + A::u);}
                                    ^

But using -std=c++11 is ok:

g++ e.cpp -std=c++11

To make it compile using c++98, I change it to avoid "A::" to be:

static A f(A a){return (A)(a + u);}

So seems that under c++98, the embeded enum class is not recognized inside a class, while in c++11 it works. Is this a difference in enum resolution, or some previous syntax bug in c++98 standard?

2 Answers

The enumeration name could not be used to qualify an enumerator prior to C++11. So there is no bug in C++98 mode, the code is just ill-formed.

You are correct in deducing the rules have changed.

The C++ FAQ lists the changes made to enumerations in C++11, and cites the proposals that drove those changes.

Enum values are not scoped by the enum type (either in C++98 or C++11). In the following example:

namespace N {
    enum E { X };
}

X is directly in the scope of namespace N. Its fully qualified identifier would be ::N::X.

This behaviour was changed by C++11, where following the same definition, the identifier of X can also be referred using ::N::E::X:

[dcl.enum/11]

An enumerator declared in class scope can be referred to using the class member access operators (::, . (dot) and -> (arrow)), see 5.2.5. [ Example:

struct X {
    enum direction { left=’l’, right=’r’ };
    int f(int i) { return i==left ? 0 : i==right ? 1 : 2; }
};

void g(X* p) {
    direction d; // error: direction not in scope
    int i;
    i = p->f(left); // error: left not in scope
    i = p->f(X::right); // OK
    i = p->f(p->left); // OK
    // ...
}

—end example ]

Related