Topic: Scoping and anonymous unions


Author: "Brad Daniels" <brad.daniels@missioncritical.com>
Date: 1997/11/14
Raw View
[Moderator's note: this is a repost, due to propagation problems.
Apologies to anyone who sees this twice.  -mod (fjh).]

I ran into this case yesterday:

class X {
    enum { SIZE=100 };
    union {
        double d;
        char str[SIZE];
    };
};
VC++ (5.0) complains because the anonymous union can't see X::SIZE, and I
fear it may be right.  The draft says in section 9-10, "For the purpose of
name look up, after the anonymous union definition, the members of the
anonymous union are considered to have been defined in the scope in which
the anonymous union is declared."  The inclusion of the phrase "after the
anonymous union definition" seems to imply that the body of the union should
not be able to see its enclosing scope.
Of course, VC++ accepts the following:
class X {
public:
    enum { SIZE=100 };
private:
    union {
        double d;
        char str[SIZE];
    };
};

Which is OK for my immediate purposes, but doesn't seem at all consistent.
It seems to me I should need to say X::SIZE in the declaration of str to be
consistent.

I though a slightly cleaner approach might be:

class X {
    union {
        enum { SIZE=100 };
        double d;
        char str[SIZE];
    };
};

This approach avoids creating a new public enumeration, but gets to be a
real mess when you want to have more than one anonymous union using the
constant (since other anonymous unions at the same scope couldn't see the
identifier.)

What's the correct behavior?

Also, I couldn't find it stated explicitly anywhere in Draft 2 of the
standard, so I just wanted to get a sanity check:

namespace X {

const int y=3;

}

In the above example, y should have internal linkage, so it should be safe
to put the above code in a header file, yes?  I just wanted to make sure
namespaces don't do something weird with linkage.

Thanks!
- Brad
--
----------------------------------------------------------------------------
Brad Daniels                  |  Was mich nicht umbringt macht mich hungrig.
Mission Critical Software     |   - Otto Nietzche
Standard disclaimers apply    |     (Friedrich's corpulent brother)
---
[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: fjh@mundook.cs.mu.OZ.AU (Fergus Henderson)
Date: 1997/11/14
Raw View
[Moderator's note: this is a repost, due to propagation problems.
Apologies to anyone who sees this twice.  -mod (fjh).]

"Brad Daniels" <brad.daniels@missioncritical.com> writes:

 >I ran into this case yesterday:
 >
 >class X {
 >    enum { SIZE=100 };
 >    union {
 >        double d;
 >        char str[SIZE];
 >    };
 >};
 >VC++ (5.0) complains because the anonymous union can't see X::SIZE, and I
 >fear it may be right.  The draft says in section 9-10, "For the purpose of
 >name look up, after the anonymous union definition, the members of the
 >anonymous union are considered to have been defined in the scope in which
 >the anonymous union is declared."  The inclusion of the phrase "after the
 >anonymous union definition" seems to imply that the body of the union should
 >not be able to see its enclosing scope.

You are confusing name look up with access control.

Names declared in the enclosing class are always *visible*, for the
purposes of name look up, in nested classes -- and that includes
nested anonymous unions.

However, nested classes don't have *access* to private members of
enclosing classes, unless explicitly declared friends.  In the
case of anonymous unions, there is no way to declare the anonymous
union to be a friend.

Perhaps it would be more useful if the draft said "For the
purposes of name look up _or access control_, ...".

 >Of course, VC++ accepts the following:
 >class X {
 >public:
 >    enum { SIZE=100 };
 >private:
 >    union {
 >        double d;
 >        char str[SIZE];
 >    };
 >};
 >
 >Which is OK for my immediate purposes, but doesn't seem at all consistent.
 >It seems to me I should need to say X::SIZE in the declaration of str to be
 >consistent.

The inconsistency here is just the usual inconsistency in C++
between name look up and accessibility.  In many other languages
(e.g. Ada), names which are not accessible are not visible,
but in C++ a private member may be visible but not accessible.

 >I though a slightly cleaner approach might be:
 >
 >class X {
 >    union {
 >        enum { SIZE=100 };
 >        double d;
 >        char str[SIZE];
 >    };
 >};

This example is ill-formed, by 9.5[class.union]/2:

 "The member-specification of an anonymous union shall
 only defined non-static data members".

Here the member-specification of your anonymous union defines `SIZE',
which is not a non-static-data-member, so it is ill-formed.
A diagnostic is required.

 >Also, I couldn't find it stated explicitly anywhere in Draft 2 of the
 >standard, so I just wanted to get a sanity check:
 >
 >namespace X {
 >
 >const int y=3;
 >
 >}
 >
 >In the above example, y should have internal linkage, so it should be safe
 >to put the above code in a header file, yes?

Yes.  See 3.5[basic.link]/3.

--
Fergus Henderson <fjh@cs.mu.oz.au>   |  "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh>   |  of excellence is a lethal habit"
PGP: finger fjh@128.250.37.3         |     -- the last words of T. S. Garp.
---
[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: "Brad Daniels" <brad.daniels@missioncritical.com>
Date: 1997/11/17
Raw View
Fergus Henderson wrote in message ...
...
>You are confusing name look up with access control.

I never realized there was a distinction before now...

>Perhaps it would be more useful if the draft said "For the
>purposes of name look up _or access control_, ...".

It seems to me it's always wrong to treat name lookup and
access control in a non-uniform manner, but I suppose that
ship has long since sailed.

It really irks me to make something public that should be private.
If I give the union a name so I can make it a friend, I can't refer to
its members without some dummy identifier.  It looks like making
the constant public is my only reasonable option.

> >I thought a slightly cleaner approach might be:
> >
> >class X {
> >    union {
> >        enum { SIZE=100 };
> >        double d;
> >        char str[SIZE];
> >    };
> >};
>
>This example is ill-formed, by 9.5[class.union]/2:
>
> "The member-specification of an anonymous union shall
> only define non-static data members".

For some reason, I was reading the above text to mean simply
that the union should not contain any static data members.

- Brad
--
----------------------------------------------------------------------------
Brad Daniels                  |  Was mich nicht umbringt macht mich hungrig.
Mission Critical Software     |   - Otto Nietzche
Standard disclaimers apply    |     (Friedrich's corpulent brother)
---
[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: stephen.clamage_nospam@eng.sun.com (Steve Clamage)
Date: 1997/11/19
Raw View
On 17 Nov 97 01:55:58 GMT, "Brad Daniels"
<brad.daniels@missioncritical.com> wrote:

>Fergus Henderson wrote in message ...
>...
>>You are confusing name look up with access control.
>
>I never realized there was a distinction before now...
>
>It seems to me it's always wrong to treat name lookup and
>access control in a non-uniform manner, but I suppose that
>ship has long since sailed.

That ship sailed long ago indeed. The ARM (1990) explains the reasons
why access control is applied only after name lookup. I don't see why
you describe that as "non-uniform". Whichever way you do it, you can
find examples that seem to produce odd results. The actual C++ rule
has the advantage of not resulting in, for example, functions whose
semantics but not validity depend only on access privileges.

>>This example is ill-formed, by 9.5[class.union]/2:
>>
>> "The member-specification of an anonymous union shall
>> only define non-static data members".
>
>For some reason, I was reading the above text to mean simply
>that the union should not contain any static data members.

The word "shall" in ANSI and ISO programming language standards is a
technical term meaning that an absolute requirement is being
discussed. Code which violates a "shall" clause is not valid. (Brad
probably realizes this, but I thought it was worth mentioning anyway.)

---
Steve Clamage, stephen.clamage_nospam@eng.sun.com
( Note: remove "_nospam" when replying )
---
[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: "Brad Daniels" <brad.daniels@missioncritical.com>
Date: 1997/11/05
Raw View
I ran into this case yesterday:

class X {
    enum { SIZE=100 };
    union {
        double d;
        char str[SIZE];
    };
};
VC++ (5.0) complains because the anonymous union can't see X::SIZE, and I
fear it may be right.  The draft says in section 9-10, "For the purpose of
name look up, after the anonymous union definition, the members of the
anonymous union are considered to have been defined in the scope in which
the anonymous union is declared."  The inclusion of the phrase "after the
anonymous union definition" seems to imply that the body of the union should
not be able to see its enclosing scope.
Of course, VC++ accepts the following:
class X {
public:
    enum { SIZE=100 };
private:
    union {
        double d;
        char str[SIZE];
    };
};

Which is OK for my immediate purposes, but doesn't seem at all consistent.
It seems to me I should need to say X::SIZE in the declaration of str to be
consistent.

I though a slightly cleaner approach might be:

class X {
    union {
        enum { SIZE=100 };
        double d;
        char str[SIZE];
    };
};

This approach avoids creating a new public enumeration, but gets to be a
real mess when you want to have more than one anonymous union using the
constant (since other anonymous unions at the same scope couldn't see the
identifier.)

What's the correct behavior?

Also, I couldn't find it stated explicitly anywhere in Draft 2 of the
standard, so I just wanted to get a sanity check:

namespace X {

const int y=3;

}

In the above example, y should have internal linkage, so it should be safe
to put the above code in a header file, yes?  I just wanted to make sure
namespaces don't do something weird with linkage.

Thanks!
- Brad
--
----------------------------------------------------------------------------
Brad Daniels                  |  Was mich nicht umbringt macht mich hungrig.
Mission Critical Software     |   - Otto Nietzche
Standard disclaimers apply    |     (Friedrich's corpulent brother)
---
[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: fjh@mundook.cs.mu.OZ.AU (Fergus Henderson)
Date: 1997/11/05
Raw View
"Brad Daniels" <brad.daniels@missioncritical.com> writes:

 >I ran into this case yesterday:
 >
 >class X {
 >    enum { SIZE=100 };
 >    union {
 >        double d;
 >        char str[SIZE];
 >    };
 >};
 >VC++ (5.0) complains because the anonymous union can't see X::SIZE, and I
 >fear it may be right.  The draft says in section 9-10, "For the purpose of
 >name look up, after the anonymous union definition, the members of the
 >anonymous union are considered to have been defined in the scope in which
 >the anonymous union is declared."  The inclusion of the phrase "after the
 >anonymous union definition" seems to imply that the body of the union should
 >not be able to see its enclosing scope.

You are confusing name look up with access control.

Names declared in the enclosing class are always *visible*, for the
purposes of name look up, in nested classes -- and that includes
nested anonymous unions.

However, nested classes don't have *access* to private members of
enclosing classes, unless explicitly declared friends.  In the
case of anonymous unions, there is no way to declare the anonymous
union to be a friend.

Perhaps it would be more useful if the draft said "For the
purposes of name look up _or access control_, ...".

 >Of course, VC++ accepts the following:
 >class X {
 >public:
 >    enum { SIZE=100 };
 >private:
 >    union {
 >        double d;
 >        char str[SIZE];
 >    };
 >};
 >
 >Which is OK for my immediate purposes, but doesn't seem at all consistent.
 >It seems to me I should need to say X::SIZE in the declaration of str to be
 >consistent.

The inconsistency here is just the usual inconsistency in C++
between name look up and accessibility.  In many other languages
(e.g. Ada), names which are not accessible are not visible,
but in C++ a private member may be visible but not accessible.

 >I though a slightly cleaner approach might be:
 >
 >class X {
 >    union {
 >        enum { SIZE=100 };
 >        double d;
 >        char str[SIZE];
 >    };
 >};

This example is ill-formed, by 9.5[class.union]/2:

 "The member-specification of an anonymous union shall
 only defined non-static data members".

Here the member-specification of your anonymous union defines `SIZE',
which is not a non-static-data-member, so it is ill-formed.
A diagnostic is required.

 >Also, I couldn't find it stated explicitly anywhere in Draft 2 of the
 >standard, so I just wanted to get a sanity check:
 >
 >namespace X {
 >
 >const int y=3;
 >
 >}
 >
 >In the above example, y should have internal linkage, so it should be safe
 >to put the above code in a header file, yes?

Yes.  See 3.5[basic.link]/3.

--
Fergus Henderson <fjh@cs.mu.oz.au>   |  "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh>   |  of excellence is a lethal habit"
PGP: finger fjh@128.250.37.3         |     -- the last words of T. S. Garp.
---
[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]