Why can't PODs have constructors?

J

JohnQ

There must be something at the implementation level that makes the standard
disallow constructors in PODs (?). What is that? Don't most implementations
just break out the constructor member functions into construct_obj_x
non-member functions taking a 'this' ptr?

It sure would be convenient to initialize structs with constructors and
still having them be PODs.

John
 
I

Ian Collins

JohnQ said:
There must be something at the implementation level that makes the
standard disallow constructors in PODs (?). What is that? Don't most
implementations just break out the constructor member functions into
construct_obj_x non-member functions taking a 'this' ptr?

It sure would be convenient to initialize structs with constructors and
still having them be PODs.
It would rule out static initialisation.
 
R

Roland Pibinger

There must be something at the implementation level that makes the standard
disallow constructors in PODs (?). What is that?
It sure would be convenient to initialize structs with constructors and
still having them be PODs.

Built-in types have constructors (e.g. int i(3);) and you can write
constructors for POD structs.
 
V

Victor Bazarov

Roland said:
Built-in types have constructors (e.g. int i(3);) and you can write
constructors for POD structs.

I believe the reason for the question is that as soon as you write
a constructor for a POD struct, it stops being a POD struct. Just
something you might want to keep in mind.

V
 
R

Roland Pibinger

I believe the reason for the question is that as soon as you write
a constructor for a POD struct, it stops being a POD struct.

Why? A constructed POD behaves the same way as a 'C struct' (almost),
it's just initialized properly, e.g.

struct Point {
Point(): x(0), y(0) {}
Point (int xcoord, int ycoord): x(xcoord), y(ycoord) {}
int x;
int y;
};


int main() {
Point p1, p2 (7, 9);
p2 = p1;
Point p3 (p2);
// Point p4 = { 1, 2 }; // error
Point a[99];
}
 
J

Jerry Coffin

There must be something at the implementation level that makes the standard
disallow constructors in PODs (?). What is that? Don't most implementations
just break out the constructor member functions into construct_obj_x
non-member functions taking a 'this' ptr?

It sure would be convenient to initialize structs with constructors and
still having them be PODs.

The definition of PODs was _intended_ to support two separate things: 1)
static initialization, and 2) layout compatibility with C.

Allowing ctors wouldn't (at least as things are normally implemented)
affect layout compatibility with C. It could, however, remove the
possibility of static initialization.

OTOH, I think this requirement could be loosened somewhat without any
problem: at the very least, I believe a ctor that contained only an
intialization list (no body) and all the initialization values were
constant expressions could still support static initialization. A body
that did essentially the same things (simple assignments, rvalues are
all constant expressions) would be easy to support as well.
 
V

Victor Bazarov

Jerry said:
The definition of PODs was _intended_ to support two separate things:
1) static initialization, and 2) layout compatibility with C.

Allowing ctors wouldn't (at least as things are normally implemented)
affect layout compatibility with C. It could, however, remove the
possibility of static initialization.

OTOH, I think this requirement could be loosened somewhat without any
problem: at the very least, I believe a ctor that contained only an
intialization list (no body) and all the initialization values were
constant expressions could still support static initialization. A body
that did essentially the same things (simple assignments, rvalues are
all constant expressions) would be easy to support as well.

I guess that introducing such a requirement (to analyse the constructor
for containing constant expressions only, both in the initialiser list
and on the right-hand side of assignments in the body, and no side
effects in the body as well) would put an undue strain on the compiler
implementors.

V
 
Z

Zeppe

JohnQ said:
There must be something at the implementation level that makes the
standard disallow constructors in PODs (?). What is that? Don't most
implementations just break out the constructor member functions into
construct_obj_x non-member functions taking a 'this' ptr?

It sure would be convenient to initialize structs with constructors and
still having them be PODs.

IMHO, because of this:

struct Foo
{
Foo(int x, int y) x(x), y(y) {}
int x, y;
};

int main()
{
Foo f; // ERROR!
}

So, no constructors.

Regards,

Zeppe
 
V

Victor Bazarov

Zeppe said:
IMHO, because of this:

struct Foo
{
Foo(int x, int y) x(x), y(y) {}

There is colon missing there somewhere...
int x, y;
};

int main()
{
Foo f; // ERROR!

Yes, because class 'Foo' has no default c-tor. But how is that
an explanation why it's not a POD any more?
}

So, no constructors.

???

V
 
Z

Zeppe

Victor said:
Yes, because class 'Foo' has no default c-tor. But how is that
an explanation why it's not a POD any more?

Well, to me it was obvious that I should be able to create any POD with
the empty constructor.

Otherwise it would be required to have an empty constructor available,
which would be pretty bad.

Regards,

Zeppe
 
H

Howard Hinnant

"JohnQ said:
There must be something at the implementation level that makes the standard
disallow constructors in PODs (?). What is that? Don't most implementations
just break out the constructor member functions into construct_obj_x
non-member functions taking a 'this' ptr?

It sure would be convenient to initialize structs with constructors and
still having them be PODs.

John

Fwiw, a slight revision of
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2294.html was
voted into the C++0X working draft last week. This paper includes the
following rationale:
The proposed changes decompose the current POD requirements into trivial type
requirements and standard-layout type requirements, and remove the dependency
on the definition of aggregates. Because these decomposed requirements are
somewhat less restrictive than the requirements for aggregates, the effect is
to make POD's more broadly useful and solve the problems identified in the
Introduction and Motivating examples. It also opens up the possibility of
designing useful classes that meet one or the other, but not both, of the new
trivial and standard-layout requirements.

-Howard
 
J

Jerry Coffin

[ ... ]
I guess that introducing such a requirement (to analyse the constructor
for containing constant expressions only, both in the initialiser list
and on the right-hand side of assignments in the body, and no side
effects in the body as well) would put an undue strain on the compiler
implementors.

I rather doubt it'd be much strain at all -- I'm pretty sure virtually
every reasonably self-respecting compiler's optimizer already detects
such things anyway.
 
B

BobR

JohnQ said:
There must be something at the implementation level that makes the standard
disallow constructors in PODs (?). What is that? Don't most implementations
just break out the constructor member functions into construct_obj_x
non-member functions taking a 'this' ptr?

PODs do have Ctor, copy-Ctor, and assignment operators. Otherwise you would
not be able to use them in std containers (like std::vector). You just can't
write your own and keep it a POD ('C'). (IMHO.)
It sure would be convenient to initialize structs with constructors and
still having them be PODs.
John

A little extra step can do that.
This uses a 'RECT' from windows. It's a POD 'C' struct with 4 longs.
Try this with your own POD struct.

struct MyRect : public virtual RECT{
MyRect( long x1 = 0, long y1 = 0, long x2 = 10, long y2 = 10 ){
left = x1; // init the RECT members
bottom = y1;
right = x2;
top = y2;
}
~MyRect(){ this->RECT::~RECT();}
RECT Rect(){ return *this;}
};

{ // main or ?
using std::cout; // for NG post
MyRect rect( 10, 12, 22, 42 );
cout<<" MyRect rect.bottom="<< rect.bottom << std::endl;
RECT rect1 = rect.Rect();
cout<<" RECT rect1.bottom="<< rect1.bottom << std::endl;

cout<<" sizeof(rect)="<<sizeof( rect )<<std::endl;
cout<<" sizeof(rect1)="<<sizeof( rect1 )<<std::endl;
}
/* - output -
MyRect rect.bottom=12
RECT rect1.bottom=12
sizeof(rect)=20
sizeof(rect1)=16 // sliced back to POD
// (sixeof long == 4 on my sys)
*/

Of course it would take something a little more complex to justify the extra
layer, or you would just do:
RECT rect2 = { 14, 19, 25, 55};

[ corrections, comments welcome. ]
 
I

Ian Collins

Roland said:
Why? A constructed POD behaves the same way as a 'C struct' (almost),
it's just initialized properly, e.g.

struct Point {
Point(): x(0), y(0) {}
Point (int xcoord, int ycoord): x(xcoord), y(ycoord) {}
int x;
int y;
};


int main() {

Try adding

Point points[2] = {{1,2},{3,4}};
Point p1, p2 (7, 9);
p2 = p1;
Point p3 (p2);
// Point p4 = { 1, 2 }; // error
Point a[99];
}
 
J

JohnQ

Howard Hinnant said:
Fwiw, a slight revision of
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2294.html was
voted into the C++0X working draft last week. This paper includes the
following rationale:

Which sounds like I might get the guarantee I want someday. It also implies
that I can do it now and chances are that it will work.

I have a question, based upon the link you gave. Wouldn't it be easier to
enforce structs to be PODs? That is, just disallow anything in a struct that
is a party spoiler in regards to layout and size. In still other words,
don't allow structs to be classes and let the compiler warn when an attempt
is made to declare or derive or compose illegally. As long as structs are
allowed to evolve into classes, a lot of programmer productivity goes out
the window.

John
 
J

JohnQ

BobR said:
PODs do have Ctor, copy-Ctor, and assignment operators. Otherwise you
would
not be able to use them in std containers (like std::vector). You just
can't
write your own and keep it a POD ('C'). (IMHO.)


A little extra step can do that.
This uses a 'RECT' from windows. It's a POD 'C' struct with 4 longs.
Try this with your own POD struct.

struct MyRect : public virtual RECT{

Why the virtual inheritance?
MyRect( long x1 = 0, long y1 = 0, long x2 = 10, long y2 = 10 ){

Defining all the default args will lead to ambiguity errors being produced
by the compiler.
left = x1; // init the RECT members
bottom = y1;
right = x2;
top = y2;
}
~MyRect(){ this->RECT::~RECT();}

Ooo, that destructor doesn't look good at all there the way you defined it.
(Wouldn't be allowed in a POD either).
RECT Rect(){ return *this;}

You were _trying_ to define a conversion operator, but you don't have to
because MyRect IS a RECT. If you were to embed the RECT into MyRect instead
of derive from it, then you'd need a conversion operator. Currently I'm
doing the derivation from RECT rather than composition (embedding) with
RECT, but it escapes me why I decided that in this case derivation was
better than composition (probably so I don't have to provide accessor
functions and the conversion operator)..

That's kind of what I've been doing to get compatibility of MyRect and RECT
(I do something a little different, but for practical discussion, it
suffices to say that). But it doesn't solve the problem since you can't
create an array of MyRects and get the desired layout (a contiguous array of
16-byte RECT-like things). It should be possible to define a MyRect so that
it is 16-bytes and still allows initializing constructors.
Of course it would take something a little more complex to justify the
extra
layer, or you would just do:
RECT rect2 = { 14, 19, 25, 55};

Well consider that you might want to construct a MyRect with 2 MyPoint
objects:

MyRect(MyPoint& origin, MyPoint& extent);

MyRect will (again/still) not FORMALLY be a POD if you define the above
constructor.

John
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,994
Messages
2,570,223
Members
46,813
Latest member
lawrwtwinkle111

Latest Threads

Top