Search code examples
c++typedef

C++: Is it defined behavior to typedef nested type with same name?


the code:

class Global
{
public:
    static const char *name() {return "Global";}
};
typedef Global T_Outter;

class Outter
{
public:
    typedef T_Outter O_Outter; // <= <1>
    typedef Outter T_Outter; // <= <2>
    static const char *name() {return "Outter";}
    static void test() {printf("self: %s, outter: %s\n", name(), O_Outter::name());}

    class Inner
    {
    public:
        typedef T_Outter O_Outter;
        typedef Inner T_Outter;
        static const char *name() {return "Inner";}
        static void test() {printf("self: %s, outter: %s\n", name(), O_Outter::name());}
    };
};

Outter::test();
Outter::Inner::test();
// output:
// self: Outter, outter: Global
// self: Inner, outter: Outter

what I want to do:

  • obtain nested class info without knowing it's actual parent class or scope
  • the typedefs would be generated by macros, with the tricks, there's no need to manually "bind" Outter and Inner's relationship, it's done by typedef automatically

here's the question:

  • is it defined behavior in the above code?
    • <1> and <2> with same T_Outter name
    • Outter::O_Outter equals to Global
    • Outter::Inner:O_Outter equals to Outter
  • is it portable to use the trick?

Solution

  • It is not allowed to change meaning of a global name inside a class after it was used unqualified in the class definition. The program is ill-formed, NDR.

    See [basic.scope.class]/2:

    A name N used in a class S shall refer to the same declaration in its context and when re-evaluated in the completed scope of S. No diagnostic is required for a violation of this rule.

    Live demo with GCC 10:

    error: declaration of 'typedef class Outter Outter::T_Outter' changes meaning of 'T_Outter' [-fpermissive]

    A possible workaround is to qualify it:

    class Outter {
    public:
        typedef ::T_Outter O_Outter;
        typedef Outter T_Outter;   // OK
        . . .