Re: Template technicality - What does the standard say?
On Oct 14, 4:58 am, Stephen Horne <sh006d3...@blueyonder.co.uk> wrote:
On Mon, 13 Oct 2008 10:08:32 -0700 (PDT), James Kanze
<james.ka...@gmail.com> wrote:
On Oct 13, 6:08 pm, Erik Wikstr=F6m <Erik-wikst...@telia.com> wrote:
What is it that I'm missing, offsetof is a macro, it should
be expanded before the compiler can even begin worrying
about whether an expression is constant or not.
I'm just guessing, because of course, g++ lets you use a
legal offsetof as a constant, but I'll bet he's actually
trying to use it on something that isn't a PODs, which is
undefined behavior. In that case, g++ generates an error; a
lot of compilers will just give you some random (constant)
value.
No.
Read for tone and you'll see I'm seriously pissed off and
frustrated, and that thing about offsetof was ranting rather
than a properly organised request for help. For example, no
quoted error messages.
I understood that you were pissed off. Still, g++ is fully
conform with regards to offsetof, and does allow it's use in an
integral constant expression. So presumably, your real problem
is elsewhere. And since most compilers don't complain about use
of offsetof on a non-POD, but g++ does, I made a guess that that
might be the real problem.
Anyway, I said that GCC wouldn't let me use offsetof in a
constant expression, which *was* perfectly true.
No it's not. The following code compiles perfectly well with
g++:
#include <cstddef>
#include <iostream>
struct S
{
int i ;
int j ;
int k ;
} ;
int
main()
{
char a[ offsetof( S, k ) ] ;
std::cout << sizeof( a ) << std::endl ;
return 0 ;
}
You're doing something else wrong.
I also said "now I have to figure out why" which I have since
done.
The GCC errors directed me to lines that contained nothing
much more than offsetof, and complained about pointer
operators etc that weren't there (hence macro expansion). I
just recently read the part of the GCC manual that tells me it
defines offsetof to map to a builtin, unless I dreamed that up
in a stress-related psychotic episode (it's pretty bad when
you hallucinate about reading manuals), making the
macro-expansion-implying errors seem strange.
Some other code relating to alignment used hand-written code
that effectively does an offsetof. When GCC complained about
that, I fixed it by simply using offsetof instead. This seems
to suggest GCC is actually doing something different to macro
expansion, since replacing the code that the macro is
traditional expanded to with the macro gave different
behaviour. I guess it doesn't really matter, so long as
offsetof works, which it does - my problem was due to being in
a template again, and the need for "typename", which is
perfectly reasonable for a change.
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.
For the record, g++ defines offsetof as a macro (as required by
the standard), but that macro expands to something like
"__builtin_offsetof( t, e )" (which is, IMHO, the only
reasonable way of implementing it). So what you actually get is
a compiler built in, which is either a constant integral
expression, or causes an error, depending on whether the use of
offsetof is legal or not.
You've got my interest, though. Why on earth should offsetof
for a non-POD struct/field be undefined?
Because it can't be implemented in the general case, and no one
considered it worth the effort of specifying when it would be
legal, and when not, except for a PODS, which is all that is
necessary for C compatibility (and the only reason it's there is
for reasons of C compatibility).
POD vs. non-POD shouldn't change the layout of a struct.
In some cases of inheritance (particularly where virtual
inheritance is involved), the layout is dynamically defined; the
compiler doesn't know it. And the "classical" implementation of
offsetof in C is something like:
#define offsetof( S, e ) ((size_t)(&(((S*)0)->e)))
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.
A non-POD struct might act as if it holds extra data, though
that data is external to the struct, but that has nothing to
do with offsetof. Some fields may be private and inaccessible
to offsetof (a compile-time error), some fields may be
pointers or references (not an error - just means you're
referring to the pointer), but that applies to POD and non-POD
equally.
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.)
Also, it's not as if the macro expansion ever instantiates the
type. It just "imagines" a hypothetical instance at address
zero and takes the address of the field.
About the only thing I can think of which could *almost*
legitimately screw up offsetof would be overriding the * or ->
pointer dereference operators, but even if a macro expansion
of offsetof uses ->, it uses it with a *pointer* left argument
rather than the non-pointer object, so the override is
irrelevant. Same goes if the macro uses * and . instead.
Can you give me a reference to look this up?
To look what up? The standard says quite clearly (=A718.1/5):
The macro offsetof accepts a restricted set of type
arguments in this International Standard. type shall be
a POD structure or a a POD union. The result of
applying the offsetof macro to a field that is a static
data member or a function member is undefined.
I mean, the idea that I can't take the offsetof a field in a
data structure node just because the application is using a
non-POD type for the contained data is beyond ridiculous.
No. It's a perfectly reasonable constraint.
In keeping with my generally pissed-off tone, I'll also ask if
the standards people came up with this one specifically to
drive me nuts? Or are you just baiting me for fun?
Actually, they're just trying to strike a compromise between the
ideal solution (drop the macro entirely) and C compatibility.
--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orient=E9e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S=E9mard, 78210 St.-Cyr-l'=C9cole, France, +33 (0)1 30 23 00 34