Movatterモバイル変換


[0]ホーム

URL:


This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 119a. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.

2025-12-20


273. POD classes andoperator&()

Section:Clause 11  [class]    Status:CD1    Submitter:Andrei Iltchenko    Date:10 Mar 2001

[Moved to DR at October 2002 meeting.]

I think that the definition of a POD class in the current versionof the Standard is overly permissive in that it allows for POD classesfor which a user-defined operator functionoperator& maybe defined. Given that the idea behind POD classes was to achievecompatibility with C structs and unions, this makes 'Plain old'structs and unions behave not quite as one would expect them to.

In the C language, ifx andy are variables ofstruct or union typeS that has a memberm, thefollowing expression are allowed:&x,x.m,x= y. While the C++ standard guarantees that ifx andy are objects of a POD class typeS, the expressionsx.m,x = y will have the same effect as they wouldin C, it is still possible for the expression&x to beinterpreted differently, subject to the programmer supplying anappropriate version of a user-defined operator functionoperator& either as a member function or as a non-memberfunction.

This may result in surprising effects. Consider:

    // POD_bomb is a POD-struct. It has no non-static non-public data members,    // no virtual functions, no base classes, no constructors, no user-defined    // destructor, no user-defined copy assignment operator, no non-static data    // members of type pointer to member, reference, non-POD-struct, or    // non-POD-union.    struct  POD_bomb  {       int   m_value1;       int   m_value2;       int  operator&()       {   return  m_value1++;   }       int  operator&() const       {   return  m_value1 + m_value2;   }    };

6.9 [basic.types] paragraph 2 states:

For any complete POD object typeT, whether or not the objectholds a valid value of typeT, the underlying bytes(6.8.1 [intro.memory]) making up the object can be copied intoan array ofchar orunsigned char [footnote:By using, for example, the library functions (16.4.2.3 [headers])memcpy ormemmove]. If thecontent of the array ofchar orunsigned char iscopied back into the object, the object shall subsequently hold itsoriginal value. [Example:
    #define N sizeof(T)    char buf[N];    T obj;   // obj initialized to its original value    memcpy(buf, &obj, N);// between these two calls to memcpy,// obj might be modified    memcpy(&obj, buf, N);// at this point, each subobject of obj of scalar type// holds its original value
end example]

Now, supposing that the complete POD object typeT in theexample above isPOD_bomb, and we cannot any more count onthe assertions made in the comments to the example. Given a standardconforming implementation, the code will not even compile. And I seeno legal way of copying the contents of an object of a complete objecttypePOD_bomb into an array ofchar orunsignedchar withmemcpy ormemmove without making useof the unary& operator. Except, of course, by means ofan ugly construct like:

    struct  POD_without_ampersand  {       POD_bomb   a_bomb;    }  obj;    #define N sizeof(POD_bomb)    char buf[N];    memcpy(buf, &obj, N);    memcpy(&obj, buf, N);

The fact that the definition of a POD class allows for POD classesfor which a user-definedoperator& is defined, may alsopresent major obstacles to implementers of the offsetof macro from<cstddef>

17.2 [support.types] paragraph 5 says:

The macrooffsetof accepts a restricted set of type argumentsin this International Standard.type shall be a POD structureor a POD union (Clause 11 [class]). The result ofapplying theoffsetof macro to a field that is a static datamember or a function is undefined."

Consider a well-formed C++ program below:

    #include <cstddef>    #include <iostream>    struct  POD_bomb  {       int   m_value1;       int   m_value2;       int  operator&()       {   return  m_value1++;   }       int  operator&() const       {   return  m_value1 + m_value2;   }    };    // POD_struct is a yet another example of a POD-struct.    struct  POD_struct  {       POD_bomb   m_nonstatic_bomb1;       POD_bomb   m_nonstatic_bomb2;    };    int  main()    {       std::cout << "offset of m_nonstatic_bomb2: " << offsetof(POD_struct,           m_nonstatic_bomb2) << '\n';       return  0;    }

See Jens Maurer's paper 01-0038=N1324 for an analysis of this issue.

Notes from 10/01 meeting:

A consensus was forming around the idea of disallowingoperator& in POD classes when it was noticed that it ispermitted to declare global-scopeoperator& functions,which cause the same problems. After more discussion, it wasdecided that such functions should not be prohibited in POD classes,and implementors should simply be required to "get the right answer"in constructs such asoffsetof andva_start thatare conventionally implemented using macros that use the "&"operator. It was noted that one can cast the original operand tochar & to de-type it, after which one can use thebuilt-in "&" safely.

Proposed resolution:




[8]ページ先頭

©2009-2026 Movatter.jp