No it's not. The following code compiles perfectly well with
g++:
No, it was perfectly true. It wouldn't let me use offsetof in a
constant expression because I was using it wrong. When I use it right,
it lets me use it. Hence I had to figure out why it wouldn't let me
use it in order that I could use it right.
I'm autistic, and you're demanding far more pedantic language from me
than I ever demanded from anyone else!
Fine. The problem wasn't due to g++'s expansion of offsetof not
being a constant integral expression; it was due to a syntax
error elsewhere.
Yes. In my original post, I didn't claim to know why GCC was rejecting
my usage, and while implying that the standard (rather than GCC) might
be at fault, I also made it clear that I didn't know yet who was at
fault. Correct answer - I was at fault. I don't think that really
needs restating any more.
In some cases of inheritance (particularly where virtual
inheritance is involved), the layout is dynamically defined;
I can see that there is a potential problem with a macro expansion
implementation (rather than GCCs wrapper approach) to offsetof, since
doing the field reference would access the virtual table/whatever of
an object that doesn't exist.
Even so, the layout of the class isn't dynamically defined, it's just
dynamically accessed. The obvious solution is to not use the
traditional macro expansion for offsetof, and just provide the actual
offset of the field using a builtin. Every class/struct has one layout
defined at compile-time irrespective of what inheritance features it
uses or anything else.
Which is undefined behavior if you write it, but which the
library implementor can do if he knows that it will get by the
compiler.
Many libraries (e.g. Sun CC, VC++) still use something like
this, and the standards committee didn't want to ban it. And it
fails as soon as the member is private.
Basic principle of C++ as given by Stroustrup - the programmer can do
anything the language/libraries can do. No special cases just to get
standard features implemented that can't be replaced by others. Anyone
is allowed to develop a library.
If the libraries can do something, I should be well within my rights
to develop alternative libraries. Standard libraries in particular
should not need to be implemented using non-standard features.
And it
fails as soon as the member is private.
At compile time, which it should do. Why should I have the right to
access private fields using offsetof? Why would I define a data
structure node and hide some of its fields from myself?
References could also cause problems. In general, it would
doubtlessly be possible to loosen the rules somewhat. Doing so
would require a fairly detailed analysis, however, to ensure
that the new rules didn't cause any problem for potential
implementations, and no one on the committee felt the effort was
worthwhile. (The case of POD was "established practice", from
C.)
And therefore likely to be used in container template libraries,
obviously, where the applications contained data may end up as
non-pod, thus implying that the data structure nodes that end up
containing it become non-POD too.
Which is presumably why Sun CC, VC++ etc do it. But as you say, it's
still *special* behaviour that only compiler vendors are allowed to
use for their library, and therefore it violoates the stated
principles of the C++ language.
Actually, technically not the case in my code, since I don't use the
application type directly within the node - just a proxy that has the
same size and alignment, to be initialised later with placement new
etc, which is technically POD. But even so, that's just because of the
specific data structures I'm using, which need to leave some items
uninitialised a bit like the overhead items in a vector.
In other words, I got lucky - but you can bet that others didn't.
To look what up? The standard says quite clearly (§18.1/5):
Thankyou. That is a useful reference, yes, and my requesting it is
hardly worthy of the "To look what up?".
In my current circumstances, paying for the standard would mean not
eating for a week, and in any case, finding a reference for something
specific in what is presumably a rather large standard is bound to be
non-trivial, whereas you were likely to know the reference since you
were already telling me what the rules are.
No. It's a perfectly reasonable constraint.
A constraint that means C data structure code cannot be adapted and
wrapped in a C++ template? IIRC, one of the basic design principles of
C++ is that people should be able to adapt their C libraries without a
complete rewrite.
A constraint that even you admit that the standards guys had to allow
compiler writers to break because they couldn't make their libraries
work otherwise?
That's what you call reasonable!
Actually, they're just trying to strike a compromise between the
ideal solution (drop the macro entirely) and C compatibility.
Really. And I suppose the modern solution is the member pointer, which
simply doesn't work at all for low level work.
For high level work, it doesn't do the most obvious useful job
(delegates) properly. In itself perfectly reasonable since it can be
used to implement a library that does.
But we're talking about replacing offsetof for low-level data
structure work.
For that, it is overengineered in that it handles a bunch of special
cases that real applications simply don't need. Its mummy-knows-best
safety rules (which are entirely inappropriate for low level code)
mean that it can't be used for many obvious tasks without
reinterpret-casting, and you can't cast it safely because of all those
unwanted special cases and their unknown implementations. The whole
thing is such a disaster that some compilers need you to drop
nonstandard hints (single inheritance, multiple inheritance, etc) in
order to use a member pointer at all.
The only pretence that member pointers have to being suitable for
low-level work is the unnecessarily cryptic syntax.
In short, it's another seems-like-a-nice-idea invention put into the
standard by people who were feeling creative, and not subjected to
testing in the real world prior to announcing that it would be part of
the standard. Then people got overcommitted to it and determined to
keep it even though it doesn't work.
An experiment that we now can't get rid of, like exception
specifications on function declarations, which are just as broken
(your black boxes are no longer black, and even nested black-boxes
cannot be replaced, many layers down, without probably violating all
the exception specifications running through layers of yours and other
peoples code) but at least no-ones trying to force anyone to use them.
As I said in another post, whatever happened to simply formalizing
existing best practice? - the supposed remit of standards authorities.
Experimental features should be implemented as compiler-specific
extensions and only standardized *after* they have proved their worth.
You know - like the alignment features that no-one bothered to
standardise despite at least two opportunities, that have been proving
their worth as non-standard compiler extensions for decades.
Trying to bully people into using member-pointers won't fix the flaws.
offsetof is needed, like it or not. Without it, there is simply *NO*
sane way for library developers to develop production quality
containers. As the standards people are clearly aware, or else they
wouldn't be exempting compiler writers from the rules they impose on
others.