26

The C++17 Standard says in [support.types.layout]:

Use of the offsetof macro with a type other than a standard-layout class is conditionally-supported.

And in [defns.cond.supp]:

conditionally-supported

program construct that an implementation is not required to support

I find this definition of offsetof not very precise.

  • Does it mean that I can safely attempt to use this with non standard-layout classes?

  • How is "conditionally-supported" different from implementation defined?

  • Is a compiler not supporting offsetof for a particular type of class required to produce a diagnostic?

Acorn
  • 24,970
  • 5
  • 40
  • 69
Vittorio Romeo
  • 90,666
  • 33
  • 258
  • 416
  • IIRC `offsetof` is in the process of being revised for C++20, getting rid of the "conditionally-supported" part, adding the notion of *stable-layout* classes, and/or extending the current definition of *standard-layout*. I don't remember the specifics though, and can't remember where I read that :/ – Morwenn Nov 28 '17 at 00:04
  • @Morwenn - It it [p0545r0](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0545r0.html) you had in mind? – StoryTeller - Unslander Monica Nov 29 '17 at 14:17
  • @StoryTeller Yes, it looks like it :) – Morwenn Nov 29 '17 at 14:18

1 Answers1

16

Does it mean that I can safely attempt to use this with non standard-layout classes?

If the implementation permits it. Being conditionally supported means this must be documented.

How is "conditionally-supported" different from implementation defined?

To quote the standard on this:

[defns.cond.supp] conditionally-supported - "program construct that an implementation is not required to support"

[defns.impl.defined] implementation-defined behavior - "behavior, for a well-formed program construct and correct data, that depends on the implementation and that each implementation documents"

The key difference is what choice the implementation has. Do it exactly as the standard says, or not at all. Vs. doing it in one of several ways without an option to refuse.

Is a compiler not supporting offsetof for a particular type of class required to produce a diagnostic?

If it's a conforming implementation, it will issue a diagnostic ([intro.compliance]/2.2 courtesy of @T.C.):

"If a program contains a violation of any diagnosable rule or an occurrence of a construct described in this document as “conditionally-supported” when the implementation does not support that construct, a conforming implementation shall issue at least one diagnostic message."

StoryTeller - Unslander Monica
  • 165,132
  • 21
  • 377
  • 458
  • 3
    UB or ill-formed? The difference is, admittedly, subtle. – Yakk - Adam Nevraumont Nov 27 '17 at 19:49
  • 2
    @Yakk - I don't see anything in the definition of the macros semantics or standard layout types that calls it ill-formed (either with a required diagnostic or not). I think that leaves us with UB. – StoryTeller - Unslander Monica Nov 27 '17 at 19:50
  • honestly conditionally supported is really no different than an implementation choosing to define undefined behavior... it's still not portable and is still dangerous. – Mgetz Nov 27 '17 at 20:08
  • @Mgetz - To borrow from Yakk, the difference is subtle, but it'd still a difference. Implementation defined means the construct is considered valid to begin with. Conditionally supported means the construct may not be valid. – StoryTeller - Unslander Monica Nov 27 '17 at 20:10
  • @Mgetz - And to make matters worse for us, [the standard may even use the two in tandem](http://eel.is/c++draft/expr.reinterpret.cast#8) :) – StoryTeller - Unslander Monica Nov 27 '17 at 20:13
  • @StoryTeller to me this is a defect in the standard as this is already covered by the fact that any implementation can define undefined behavior. Until feature test macros are implemented for this; this is as far as I'm concerned UB as I highly doubt any compiler will treat this as ill formed. I do recognize the subtle difference however between implementation defined and undefined, but in this case if the implementation chooses not to support then the result is still undefined. – Mgetz Nov 27 '17 at 20:22
  • @Mgetz - An implementation may pull the rug on you with UB because it doesn't have to document anything. Do one thing in version 1.0 and another in version 2.0. IB must be documented. Documentation makes introducing breaking changes much harder. I don't see it as a defect, but yet again, YMMV. – StoryTeller - Unslander Monica Nov 27 '17 at 20:27
  • 3
    Code that exhibits UB that would run can cause time-travelling nasal demons. UB exhibiting code that cannot run cannot cause time-travelling nasal demons. Ill-formed code (code that makes your program ill-formed) that cannot run (is unreachable) can cause time-travelling (dimension hopping?) nasal demons. The difference is real; claiming that it is merely UB because it doesn't say it is ill-formed seems overly optimistic. Ill-formed programs have *no requirements* placed on them by the standard. Programs whose abstract machine *executes UB* have *no requirements* placed on them. – Yakk - Adam Nevraumont Nov 27 '17 at 20:38
  • 4
    [\[intro.compliance\]/2.2](https://timsong-cpp.github.io/cppwp/intro.compliance#2.2): "If a program contains [...] an occurrence of a construct described in this document as “conditionally-supported” when the implementation does not support that construct, a conforming implementation shall issue at least one diagnostic message." – T.C. Nov 27 '17 at 21:57