Feature Proposal: Explicitly declare a struct (or class) as POD

Discussion in 'C++' started by jmucchiello, Aug 25, 2009.

  1. jmucchiello

    jmucchiello Guest

    I posted this to comp.std.c++ last week and it never showed up so I'll
    post it here to see if there's any interest. Sorry if that's against
    the rules but I don't know where a FAQ might be.
    -------
    Hi, I have a proposal for a language addition. I realize it is far
    too late
    for this idea in C++0x but I think it would be a good addition to the
    language.

    My proposal is to make it possible to explicitly mark a struct (or
    class) as
    plain-old-data (POD). Currently, the language specification states the
    rules for
    determining IF a struct (or class) is POD. While these rules were
    relaxed in
    C++0x, the objective of this proposal is to allow the designer to
    force a struct
    to be POD and to allow the compiler to output errors if the
    requirement is
    violated.

    As with any proposal for language change there comes the issue of
    syntax or
    keyword usage. This proposal follows the hallowed tradition of piling
    yet
    another meaning onto the 'static' keyword. To mark a struct as POD one
    adds the
    static keyword after the struct (or class) keyword:

    struct static Foo { ... };

    Once marked as POD, any construct that would make it impossible
    for the
    struct to be POD MUST be flagged as an error by the compiler:

    class Foo {
    public:
    virtual int f() {}
    };

    struct static Bar : public Foo { ... }; // error Bar cannot
    contain
    // virtual functions

    struct static Baz {
    int x;
    Foo foo; // error, POD structs cannot contain non-POD elements
    };

    struct static Boo { ... };

    class Goo : public Boo {
    public:
    virtual int f() {} // this is legal, Goo is not POD
    };

    That's it in a nutshell. A few anticipated concerns are addressed
    below:

    Does C++ need this?

    Do we need anything? Seriously, every version of C++'s language
    specification spent a section or two describing what POD is and how to
    achieve
    it for backward compatibility with C and system calls. Having a way
    for the
    compiler to know what MUST be POD and tell you when you have caused a
    struct to
    exit the realm of POD must be a useful concept. Frankly, I'm surprised
    it
    doesn't already exist.

    Couldn't attributes be used instead of overloading static yet again?

    My understanding of attributes is that they are helpers to the
    compiler. The
    whole point of adding POD requirements to struct is as a help to the
    library
    developer. So while it could be done with attributes (as could default
    and
    deleted constructors, for example), attributes speak to the compiler.
    Here, the
    library designer is speaking to the library user.

    Should POD status affect name-mangling?

    This is not a lang-spec issue really. It would be nice since it
    would ensure
    the POD status of the struct across separate compilations. It would
    also break
    existing ABIs however that should not be an issue since moving from C+
    +03 to
    C++0x will also break existing ABIs I suspect.

    Does this impact compatibility with C?

    I suspect that if this proposal were accepted as part of C++ a lot
    of existing
    headers would be modified using a #define that is defined as empty
    when the
    compiler is in C mode and is defined as static when in C++ mode:

    #ifdef __CPLUSPLUS
    #define __POD__ static
    #else
    #define __POD__
    #endif

    struct __POD__ FILELAYOUT { ... };


    Thanks for listening. I'll now stand back and see where I've gone
    astray. :)

    Joe Mucchiello
    jmucchiello, Aug 25, 2009
    #1
    1. Advertising

  2. jmucchiello wrote:
    > I posted this to comp.std.c++ last week and it never showed up so I'll
    > post it here to see if there's any interest. Sorry if that's against
    > the rules but I don't know where a FAQ might be.

    http://www.parashift.com/c -faq-lite/ (Doesn't mention this I don't think?)

    A few quick comments:

    > Hi, I have a proposal for a language addition. I realize it is far
    > too late
    > for this idea in C++0x but I think it would be a good addition to the
    > language.
    >
    > My proposal is to make it possible to explicitly mark a struct (or
    > class) as
    > plain-old-data (POD). Currently, the language specification states the
    > rules for
    > determining IF a struct (or class) is POD. While these rules were
    > relaxed in
    > C++0x, the objective of this proposal is to allow the designer to
    > force a struct
    > to be POD and to allow the compiler to output errors if the
    > requirement is
    > violated.
    >
    > As with any proposal for language change there comes the issue of
    > syntax or
    > keyword usage. This proposal follows the hallowed tradition of piling
    > yet
    > another meaning onto the 'static' keyword. To mark a struct as POD one
    > adds the
    > static keyword after the struct (or class) keyword:
    >
    > struct static Foo { ... };


    I'm not sure I like the idea of writing:

    static struct static Foo { ... } inst;

    It's almost as bad as trying to explain to someone what

    int const * const

    and permutations thereof actually mean!

    >
    > Once marked as POD, any construct that would make it impossible
    > for the
    > struct to be POD MUST be flagged as an error by the compiler:
    >
    > class Foo {
    > public:
    > virtual int f() {}
    > };
    >
    > struct static Bar : public Foo { ... }; // error Bar cannot
    > contain
    > // virtual functions
    >
    > struct static Baz {
    > int x;
    > Foo foo; // error, POD structs cannot contain non-POD elements
    > };
    >
    > struct static Boo { ... };
    >
    > class Goo : public Boo {
    > public:
    > virtual int f() {} // this is legal, Goo is not POD
    > };
    >
    > That's it in a nutshell. A few anticipated concerns are addressed
    > below:
    >
    > Does C++ need this?
    >
    > Do we need anything? Seriously, every version of C++'s language
    > specification spent a section or two describing what POD is and how to
    > achieve
    > it for backward compatibility with C and system calls. Having a way
    > for the
    > compiler to know what MUST be POD and tell you when you have caused a
    > struct to
    > exit the realm of POD must be a useful concept. Frankly, I'm surprised
    > it
    > doesn't already exist.
    >
    > Couldn't attributes be used instead of overloading static yet again?
    >
    > My understanding of attributes is that they are helpers to the
    > compiler. The
    > whole point of adding POD requirements to struct is as a help to the
    > library
    > developer. So while it could be done with attributes (as could default
    > and
    > deleted constructors, for example), attributes speak to the compiler.
    > Here, the
    > library designer is speaking to the library user.
    >
    > Should POD status affect name-mangling?
    >
    > This is not a lang-spec issue really. It would be nice since it
    > would ensure
    > the POD status of the struct across separate compilations. It would
    > also break
    > existing ABIs however that should not be an issue since moving from C+
    > +03 to
    > C++0x will also break existing ABIs I suspect.
    >
    > Does this impact compatibility with C?
    >
    > I suspect that if this proposal were accepted as part of C++ a lot
    > of existing
    > headers would be modified using a #define that is defined as empty
    > when the
    > compiler is in C mode and is defined as static when in C++ mode:
    >
    > #ifdef __CPLUSPLUS
    > #define __POD__ static
    > #else
    > #define __POD__
    > #endif
    >
    > struct __POD__ FILELAYOUT { ... };
    >
    >
    > Thanks for listening. I'll now stand back and see where I've gone
    > astray. :)


    How do you propose this should interact with templates? Surely this
    would be the most useful area for it. I.e. the template parameter
    must/musn't be a POD would be useful, but is totally overlooked by your
    suggestion as it stands.

    If concepts isn't dead (C++2X? ;) perhaps?) then isn't this just one
    area which would be covered by concepts and thus completely redundant?

    Alan
    Alan Woodland, Aug 25, 2009
    #2
    1. Advertising

  3. jmucchiello

    Daniel Pitts Guest

    jmucchiello wrote:
    > I posted this to comp.std.c++ last week and it never showed up so I'll
    > post it here to see if there's any interest. Sorry if that's against
    > the rules but I don't know where a FAQ might be.
    > -------
    > Hi, I have a proposal for a language addition. I realize it is far
    > too late
    > for this idea in C++0x but I think it would be a good addition to the
    > language.
    >
    > My proposal is to make it possible to explicitly mark a struct (or
    > class) as
    > plain-old-data (POD). Currently, the language specification states the
    > rules for
    > determining IF a struct (or class) is POD. While these rules were
    > relaxed in
    > C++0x, the objective of this proposal is to allow the designer to
    > force a struct
    > to be POD and to allow the compiler to output errors if the
    > requirement is

    Perhaps instead a declaration, make it an assertion.

    I don't have a lot of practice with metaprogramming in C++, but I could
    imagine there is some sort of test one couple perform that indicates
    whether a particular datatype is POD or not. That way you could do
    something like:

    struct somepod {...};

    ASSERT_POD(somepod);

    and more importantly:

    template<typename foo>
    void doSomethingWithPod(foo f) {
    ASSERT_POD(somepod);
    }
    --
    Daniel Pitts' Tech Blog: <http://virtualinfinity.net/wordpress/>
    Daniel Pitts, Aug 25, 2009
    #3
  4. Daniel Pitts wrote:
    > jmucchiello wrote:
    >> I posted this to comp.std.c++ last week and it never showed up so I'll
    >> post it here to see if there's any interest. Sorry if that's against
    >> the rules but I don't know where a FAQ might be.
    >> -------
    >> Hi, I have a proposal for a language addition. I realize it is far
    >> too late
    >> for this idea in C++0x but I think it would be a good addition to the
    >> language.
    >>
    >> My proposal is to make it possible to explicitly mark a struct (or
    >> class) as
    >> plain-old-data (POD). Currently, the language specification states the
    >> rules for
    >> determining IF a struct (or class) is POD. While these rules were
    >> relaxed in
    >> C++0x, the objective of this proposal is to allow the designer to
    >> force a struct
    >> to be POD and to allow the compiler to output errors if the
    >> requirement is

    > Perhaps instead a declaration, make it an assertion.
    >
    > I don't have a lot of practice with metaprogramming in C++, but I could
    > imagine there is some sort of test one couple perform that indicates
    > whether a particular datatype is POD or not. That way you could do
    > something like:
    >
    > struct somepod {...};
    >
    > ASSERT_POD(somepod);
    >
    > and more importantly:
    >
    > template<typename foo>
    > void doSomethingWithPod(foo f) {
    > ASSERT_POD(somepod);
    > }

    Here we go:

    template <typename T>
    class pod_asserter {
    public:
    enum {is_pod=1};
    private:
    typedef union {
    T inst;
    } pod_asserter_t;
    static pod_asserter_t test;
    };

    #define ASSERT_POD(x) ((void)pod_asserter< x >::is_pod)

    struct foo {
    int a;
    };

    struct bar {
    virtual ~bar() {}
    };

    int main() {

    ASSERT_POD(foo);
    ASSERT_POD(int);
    ASSERT_POD(float);
    ASSERT_POD(bar);

    return 0;
    }

    Of course that won't work with C++0x though! The error message isn't
    great either, but I think that could be improved.

    Alan
    Alan Woodland, Aug 25, 2009
    #4
  5. jmucchiello

    Balog Pal Guest

    "jmucchiello" <>
    >I posted this to comp.std.c++ last week and it never showed up so I'll
    > post it here to see if there's any interest. Sorry if that's against
    > the rules but I don't know where a FAQ might be.
    > -------
    > Hi, I have a proposal for a language addition. I realize it is far
    > too late
    > for this idea in C++0x but I think it would be a good addition to the
    > language.
    >
    > My proposal is to make it possible to explicitly mark a struct (or
    > class) as
    > plain-old-data (POD).

    ....

    I plan a similar thing, more elaborated control on the layout as just POD.
    In a few words I'd like add two attributes, 'free-layout' and
    'standard-layout' (note: in C++0x that is the term used for what you refer
    as POD...)

    The second would force a strict POD-compatible layout if it is possible (
    removing the fiddling-license of the implementation wrt private sections,
    etc...) and make the program ill-formed if it is not possible (i.e. having
    virtuals).

    The first would go the other direction, allowing to ignore the current
    laying-out rules, like 'increasing order within the same access section' and
    'distinct address for every member' -- IOW allowing free reordering of the
    data members and use zero-size for empty members.
    And a good compiler would have a switch to make 'free-layout' the default
    for everything not wearing the other attribute.

    I think the new 'attribute' facility is fit to handle the case in a
    convenient way, and is similar to how similar stuff is already controlled in
    the practice.
    Balog Pal, Aug 25, 2009
    #5
  6. jmucchiello

    Greg Herlihy Guest

    On Aug 25, 2:06 pm, Alan Woodland <> wrote:
    > Daniel Pitts wrote:


    > Here we go:
    >
    > template <typename T>
    > class pod_asserter {
    > public:
    >         enum {is_pod=1};
    > private:
    >         typedef union {
    >                 T inst;
    >         } pod_asserter_t;
    >         static pod_asserter_t test;
    >
    > };
    >
    > #define ASSERT_POD(x) ((void)pod_asserter< x >::is_pod)
    >
    > struct foo {
    >    int a;
    >
    > };
    >
    > struct bar {
    >    virtual ~bar() {}
    >
    > };
    >
    > int main() {
    >
    >    ASSERT_POD(foo);
    >    ASSERT_POD(int);
    >    ASSERT_POD(float);
    >    ASSERT_POD(bar);
    >
    >    return 0;
    >
    > }


    For C++0x, just use this test:

    #include <type_traits>

    static_assert(std::is_pod<x>::value, "type is not a pod");

    replacing "x" with the type to be tested.

    Greg
    Greg Herlihy, Aug 26, 2009
    #6
  7. jmucchiello

    jmucchiello Guest

    On Aug 25, 3:39 pm, Daniel Pitts
    <> wrote:
    > Perhaps instead a declaration, make it an assertion.


    That removes all ability for the compiler to optimize around it. Also
    there is nothing stopping someone from screwing up the meta-
    programming object and declaring a non-POD POD. I also think the
    ability to export the POD status of struct to the name-mangling is
    helpful for large projects where you don't want someone coming along
    and adding a virtual function to an internal used struct. The linker
    would point out that the POD and non-POD versions of the same struct
    are not the same type.
    jmucchiello, Aug 26, 2009
    #7
  8. jmucchiello wrote:
    > On Aug 25, 3:39 pm, Daniel Pitts
    > <> wrote:
    >> Perhaps instead a declaration, make it an assertion.

    >
    > That removes all ability for the compiler to optimize around it. Also

    That's not true at all - it's pretty straightforward for a compiler to
    tell if something is a POD or not, and act sensibly and I'd be willing
    to bet that most do where possible.

    > there is nothing stopping someone from screwing up the meta-
    > programming object and declaring a non-POD POD. I also think the

    Yes there is, the ASSERT_POD example I provided does exactly that, using
    the current language, and apparently this will be supported without any
    trickery at all in C++0x.

    > ability to export the POD status of struct to the name-mangling is
    > helpful for large projects where you don't want someone coming along
    > and adding a virtual function to an internal used struct. The linker
    > would point out that the POD and non-POD versions of the same struct
    > are not the same type.

    Relying on the name mangling scheme explicitly for doing anything seems
    like a bad idea. I fail to see how any proposal encouraging people to
    assume specific things about name-mangling schemes, which are
    implementation defined can be a good thing.

    You also talked about C compatibility for PODs, but this:

    template <typename T>
    struct foo {
    T bar;
    };

    is a POD, yet not 'C' compatible in respect, and doesn't even result in
    any symbols in the output anyway to inspect the 'POD status' of it as
    you'd like us to do.

    As far as I know most implementations don't store any type info of
    instances in the symbols they export, e.g:

    foo<int> inst;

    results in:
    ajw05@pc2ajw05:~ > nm test.o


    0000000000000000 B inst

    on my platform. What would you expect to change there if I accidentally
    made inst not a POD? Currently I can't even tell if it's an int, a POD
    or a non-POD by inspecting the binary.

    It seems like the useful parts of this proposal (being sure if any type
    is POD or not) are already feasible, and being improved in upcoming
    standards apparently. The other parts seem to have dubious usefulness
    and technical merits.

    Alan
    Alan Woodland, Aug 26, 2009
    #8
  9. jmucchiello

    jmucchiello Guest

    On Aug 26, 12:49 pm, Alan Woodland <> wrote:
    > You also talked about C compatibility for PODs, but this:
    >
    > template <typename T>
    > struct foo {
    >         T bar;
    >
    > };
    >
    > is a POD, yet not 'C' compatible in respect, and doesn't even result in
    >   any symbols in the output anyway to inspect the 'POD status' of it as
    > you'd like us to do.


    No, it is not a POD. T can be a non-POD type and that would make foo
    non-POD. This example is exactly what my proposal is for. In my
    proposal, you would say:

    template <typename T>
    struct static foo {
    T bar;
    };

    class C {
    public:
    virtual ~C() {}
    };

    foo<C> aFoo; // compiler error

    How would you get the same functionality using a static assert?

    I brought up C compatibility for stuff like operating system structs.
    That has nothing to do with whether or not valid C++ POD structs are
    the valid C structs.

    #ifdef __CPP__
    #define __POD__ static
    #else
    #define __POD__
    #endif

    struct __POD__ FILETIME {
    time_t created;
    time_t modified;
    time_t accessed;
    #ifdef __CPP__
    FILETIME(time_t c, time_t m, time_t a) : created(c), modified(m),
    accessed(a) {}
    FILETIME(time_t t = 0) : created(t), modified(t), accessed(t) {}
    #endif
    };

    >As far as I know most implementations don't store any type info of
    >instances in the symbols they export, e.g:
    >
    >foo<int> inst;


    Of course not, there's nothing about that in the spec: try this and
    watch how much type info is generated. I specifically talked about
    name mangling, not global data.

    foo<int> func(foo<int> a) {
    return 0;
    }
    jmucchiello, Aug 26, 2009
    #9
  10. jmucchiello wrote:
    > On Aug 26, 12:49 pm, Alan Woodland <> wrote:
    >> You also talked about C compatibility for PODs, but this:
    >>
    >> template <typename T>
    >> struct foo {
    >> T bar;
    >>
    >> };
    >>
    >> is a POD, yet not 'C' compatible in respect, and doesn't even result in
    >> any symbols in the output anyway to inspect the 'POD status' of it as
    >> you'd like us to do.

    >
    > No, it is not a POD. T can be a non-POD type and that would make foo
    > non-POD. This example is exactly what my proposal is for. In my
    > proposal, you would say:
    >
    > template <typename T>
    > struct static foo {
    > T bar;
    > };
    >
    > class C {
    > public:
    > virtual ~C() {}
    > };
    >
    > foo<C> aFoo; // compiler error
    >
    > How would you get the same functionality using a static assert?

    The fact that foo<T> is/isn't a POD isn't what actually matters when you
    declare/define foo though. It's where foo<T> gets used that it matters.
    It's not an error to pass some T that makes foo non-POD, unless you
    later hand foo off to something that assumes foo<T> is always POD.

    If foo assumes that T itself is POD then it's easy enough to modify
    ASSERT_POD to work inside of foo's definition.

    Where it really matters that foo<T> is a POD would be the place where
    you do something that assumes it is a POD (e.g. memcpy or whatever), and
    that's the place I'd be looking to put the ASSERT_POD call. An
    ASSERT_POD in some function that calls memcpy serves as documentation to
    a reader, and enforces it through the compiler. In fact if you didn't
    put ASSERT_POD in places where you actually did things that assumed it
    was POD you'd still be open to breakages later on, even with your
    proposed way of doing things.

    e.g.:

    template <typename T>
    void super_optimised_pod_routine(const T& bar) {
    ASSERT_POD(T);
    // do some clever fast things here
    }

    Under your proposal there is no way to say T must be a POD here, which
    is by far the most useful scenario for POD testing.

    I fail to see any strong arguments for benefits of what you propose that
    can't already be covered (arguably better) by checking PODness where it
    really counts.

    I'd be more enthusiastic about a proposal for allowing you to write:
    template <POD T>
    except for the fact it's already possible to achieve this functionality
    as I outlined.

    >> As far as I know most implementations don't store any type info of
    >> instances in the symbols they export, e.g:
    >>
    >> foo<int> inst;

    >
    > Of course not, there's nothing about that in the spec: try this and
    > watch how much type info is generated. I specifically talked about
    > name mangling, not global data.
    >
    > foo<int> func(foo<int> a) {
    > return 0;
    > }

    It's completely implementation defined what I see from that. There's no
    reason why your implementation can't write POD in big letters there
    already if whoever made your implementation thought it mattered. It
    seems somewhat bizarre to leave mangling completely open-ended yet add
    one small caveat requiring implementations to mention if the arguments
    and return types are POD or not. For what's required of an
    implementation right now the mangling could be done based on a MD5 hash!

    Alan
    Alan Woodland, Aug 26, 2009
    #10
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Ajax Chelsea

    Is array of POD still a POD type?

    Ajax Chelsea, Dec 1, 2003, in forum: C++
    Replies:
    1
    Views:
    329
    Ron Natalie
    Dec 1, 2003
  2. BigMan
    Replies:
    3
    Views:
    1,415
    BigMan
    Apr 22, 2005
  3. Replies:
    1
    Views:
    345
    Victor Bazarov
    Feb 17, 2006
  4. Mike Oliver
    Replies:
    0
    Views:
    382
    Mike Oliver
    Feb 1, 2011
  5. Himanshu Garg
    Replies:
    1
    Views:
    141
    Himanshu Garg
    Sep 21, 2003
Loading...

Share This Page