1. Revision History
1.1. Revision 0
Initial Release 🎉
2. Motivation
is a relic of its time. It’s a macro, works only on standard
layout types, and by its very definition requires a compiler to either
implement it via an intrinsic or to use undefined behavior.
While it would be nice to assume that
and similar tools are no
longer needed, this is unfortunately not the case. When working with some C
APIs, or older C++ APIs, knowing the offset of a type is necessary for a
library to remain "ABI" safe. A good example of this is the Python scripting
language. Python’s C API allows users to "bind" C and C++ types to the Python
API. Of important note is that data members can be bound to a Python class
directly via the
struct. This struct requires type information
about the "reflected" member in the form of a constant (such as
or
), and the offset to the given member. As using
can in
some cases cause undefined behavior, it means that fully valid code is technically speaking not safe to work in a portable manner, thus upending
Python’s C API which is designed for portable use across platforms.
An example of this problem can be found below (actual final binding code has been removed for clarity):
#include <Python.h>#include "structmember.h"struct CustomObject { PyObject_HEAD PyObject * first ; PyObject * last ; int number ; }; static PyMemberDef Custom_members [] = { { "first" , T_OBJECT_EX , offsetof ( CustomObject , first ), 0 , "first name" }, { "last" , T_OBJECT_EX , offsetof ( CustomObject , last ), 0 , "last name" }, { "number" , T_INT , offsetof ( CustomObject , number ), 0 , "custom number" }, { } /* Sentinel */ };
As we can see above, offsets for
,
, and
are all obtained
via the
macro. However, this also places us into the predicament
that we are unable to write a generic function to handle all of this work for
us. Specifically, under standard C++, we cannot implement something equivalent
to the following:
template < class T > PyMemberDef readonly ( PyObject * ( T ::* member ), char const * name , char const * docs = nullptr ) { return { name , T_OBJECT_EX , offsetof ( T , member ), READONLY , docs }; } template < class T > PyMemberDef member ( PyObject * ( T ::* member ), char const * name , char const * docs = nullptr ) { return { name , T_OBJECT_EX , offsetof ( T , member ), 0 , docs }; }
This paper attempts to fix this by creating a new function named
that can take pointer to member data as a parameter directly, without needing
to know the name of the actual member.
is intended to be similar
to
in the same way that
is similar to
.
3. Design Considerations
The design for
is simple. Given any pointer to member data for a
Standard Layout class, vendors will return the offset to said member according
to the current target environment. In theory this sounds wild and unwiedly,
however in practice, all current vendors simply place the offset to said member
inside its pointer to member as either a
or an
.
There is, however, one interesting caveat.
can be implemented
entirely via
. Doing so means that
cannot be
. This paper is not tackling changing the constraints found on
, but a discussion is needed on whether
should be
, and whether
should permit
casting of
pointer to member data from Standard Layout classes to a
.
To match
, it is the author’s recommendation that
be
placed into the
header.
4. Wording
The following is working for the library section.
namespace std { template < class T > ptrdiff_t offset ( T const & pmd ) noexcept ; }
-
Constraints This function shall not participate in overload resolution unless:
-
isstd :: is_member_object_pointer_v < T > true
-
isstd :: is_standard_layout_v < class - of < T >> true
Note: There is not
type trait available in standard C++. The above is shown for exposition purposes only.std :: class_of_t < T > -
-
Returns
An object of type
, the value of which is the offset in bytes from the beginning of an object of the class-ofstd :: ptrdiff_t
to the member specified byT
including padding if any.T -
Remarks
While
is conditionally supported for non-standard layout types,offsetof
is intended to be more tightly constrained and only for standard layout types.offset
4.1. Feature Testing
The
feature test macro should be added.