Post by Andrey Semashev
On Wed, Oct 12, 2016 at 2:11 PM, Andrey Semashev
Although on the other hand, presence of a user-defined copy
constructor is not the proper reason to prohibit offsetof - the
constructor does not affect binary layout at all.
Can you provide standard wording justifying that claim? If a type is
neither standard layout nor trivially copyable, I cannot off-hand think
of any rule in the standard that requires the data members to even be
stored within the object. In some cases it might be reasonable for a C++
implementation to do interesting things with such types, such as putting
(some of) the members in a separate garbage-collected heap, or
automatically applying the pimpl idiom for ABI stability, or adding or
rearranging the members to support some kind of runtime instrumentation.
Off the top of my head I can remember the standard requires non-static
data members to have increasing addresses within the class and the same
access mode region. Strictly speaking, that does not preclude the compiler
garbage collection is not allowed because the members have to be destroyed
in a particular order on the object destruction.)
The point of putting members on a GC heap is to allow them to be found as
GC roots, not necessarily to allow them to be collected.
An implementation in which members (that aren't in virtual bases) are
outside the class's byte range may be currently allowed, but in many
aspects is absurd. It means things like the size of the class could be
less than the sum of the size of its members. It also means that using
placement new could result in calling malloc, which is often what calling
placement new is intending to avoid.
If an implementation wanted to put members into a garbage collection root,
it could just register them in a list somewhere pointing within the class.
The members don't actually need to be outside the class. Since any defined
copy or move operation would have to go through a constructor and/or
destructor, this works.
Post by Andrey Semashev
Since offsetof is a constant expression I would prefer the program
to be ill-formed if those conditions are violated. The current
behavior is undefined, which I guess is for compatibility with C.
That's not true. Use on non-standard-layout types is
1) An implementation must document which types are supported.
2) If a type is supported, the behavior must be as documented in the
standard -- you get the offset of the member.
3) If a type is not supported, the program is ill-formed.
In that case I don't see how "conditionally-supported" differs from
"implementation-specific" for non-standard-layout types. Imprecise wording
Then you should look up the definition of "conditionally-supported" in the
One thing that concerns me about defect report 2709 is that "conditionally
supported" seems to imply that using offsetof in unsupported situations is
ill-formed, when it should probably be undefined behavior. Otherwise, to
conform to the Standard, every compiler would have to implement offsetof
using a keyword, rather than the simple reinterpret_cast maze some
implementations use (e.g. Visual C++).
Post by Andrey Semashev
If a program contains a violation of any diagnosable rule or an occurrence
of a construct described in
this Standard as âconditionally-supportedâ when the implementation does
not support that construct,
a conforming implementation shall issue at least one diagnostic message.
Anyway, that doesn't really change my point. I think the standard should
define offsetof for more types than it currently does.
I think it would make sense to also require it to be guaranteed to be
available for trivially copyable types.
Yes, but because members of reference type do not break being
trivially-copyable, a statement about the behavior being undefined for
reference types would be needed.
What do you think about this wording?
The macro offsetof(*type*, *member-designator*) accepts a restricted set of
type arguments in this International Standard. Use of the offsetof macro
with a *type* other than a standard-layout class or trivially copyable
class (Clause 9) is conditionally-supported; if unsupported, the result is
undefined. The expression offsetof(*type*, *member-designator*) is never
type-dependent (126.96.36.199) and it is value-dependent (188.8.131.52) if and only
if *type* is dependent. The result of applying the offsetof macro to a
static data member or a function member, or a *member-designator*
containing a member of reference type, is undefined.
- Allows trivially-copyable types.
- If an implementation doesn't support some use case, the behavior is
undefined. Some existing implementations will simply explode if you try
offsetof on e.g. members of virtual base classes, rather than throw a
compiler error. Others do throw an error.
- Since trivially-copyable types include classes with reference members,
this notes that offsetof(type, referencemember) is undefined. Also,
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to email@example.com.
To post to this group, send email to firstname.lastname@example.org.
Visit this group at https://groups.google.com/a/isocpp.org/group/std-discussion/.