12
class Base {
    protected:
        union {
            struct {
                bool bBold : 1;
                bool bFakeBold : 1;
            };
            int a;
        };
    public:
        bool isBold() {
            return bBold;
        }
};

Test class:

#include <assert.h>
#include <stdio.h>

int main()
{
    Base d;
    d.bBold = false;
    assert(d.isBold() == false);
    d.bBold = true;
    assert(d.isBold() == true);
    printf("good");
    return 0;
}

Both msvc11 and g++ compile without any error.

Why?

Jichao
  • 40,341
  • 47
  • 125
  • 198

3 Answers3

9

Following code is incorrect by standard.

        struct {
            bool bBold : 1;
            bool bFakeBold : 1;
        };

It's GNU-extension

However, clang gives error, when you try to get access to bBold, so, it's probably MSVC/GCC bug (all depends on realization of this extension, I think, since if you try to access to a member - you will receive correct error).

So, since it's C-extension, where we have no access specifiers - it looks like members of this anonymous struct will be injected in public section.

ForEveR
  • 55,233
  • 2
  • 119
  • 133
  • 1
    I am not sure if it is against the standard. Note that the nested `struct` is not a ``nested type`` but a nested non-static object of an anonymous struct type. – CygnusX1 Jun 25 '13 at 07:08
  • @CygnusX1 anonymous structs without names are not allowed by standard, it's gnu-extension as I can see. – ForEveR Jun 25 '13 at 07:09
  • 2
    Then *that* is against standard, but not what you quote. There is no nested type definition here, is there? – CygnusX1 Jun 25 '13 at 07:10
  • 2
    +1. For everyone who is confused about what exactly is allowed by the Standard in terms of structs without names (as I was confused for a moment after seeing your answer): [Are anonymous structs standard and really what *are* they](http://stackoverflow.com/questions/14248044/are-anonymous-structs-standard-and-really-what-are-they) – jogojapan Jun 25 '13 at 07:23
3

As mentioned already, unnamed structs are is a non-standard extension. Because this is a non-standard extension, it is valid for different compilers to implement this subtly differently. However, for anonymous unions, the same question exists. Modified example:

class C {
    union {
        union {
            int i;
        };
    };
};
int main() {
    C c;
    c.i = 0;
    return c.i;
}

This should cause a compile-time error/warning/other diagnostic, but GCC happily accepts it. Tested with 4.5.3, and Ideone's 4.7.2. I suspect this is a bug in GCC, and if MSVC also accepts this, also a bug in MSVC.

0

The private/protected protect only the fields defined in the same class as the keyword. If one would do the following trick:

class Foo {
    private:
    class Bar {
        public:
        int x;
    }
    public:
    typedef Bar PublicBar;
}

You can still access Foo::PublicBar::x

struct X { ... } is nowdays in C++ a synonim of class X { public: ... }. Fields of union are public too.

In your case, you can hide it in the following way:

class Base {
protected:
    union X {
        struct {
            bool bBold : 1;
            bool bFakeBold : 1;
        };
        int a;
    };
    X x;
public:
    bool isBold() {
        return x.bBold;
    }
};

Now x is private and the definition of inner union does not "leak" into public.

CygnusX1
  • 20,968
  • 5
  • 65
  • 109
  • I don't think the answer to the question is that "deep". This code doesn't have the same problem (with `gcc` in particular): `class Base { protected: struct { bool bBold; bool bFakeBold; };...` – alfC Jun 25 '13 at 07:11