is this class POD ?

B

bartek

template <class T, unsigned size>
struct Array {
typedef unsigned SizeType;
typedef T ValueType;
typedef T* Ptr;
typedef T const* ConstPtr;

// Default copy ctor and assignment op are fine.

SizeType Size() const { return size; }

T& operator[](SizeType i) { return m_array; }
T const& operator[](SizeType i) const { return m_array; }

Ptr Begin() { return &m_array[0]; }
ConstPtr Begin() const { return &m_array[0]; }

Ptr End() { return &m_array[0] + size; }
ConstPtr End() const { return &m_array[0] + size; }

private:
ValueType m_array[size];
};

It defines neither a copy-ctor nor a destructor.
Does the presence of private section render it as non-POD?

I assume that, if the above class was a POD type, objects of the
following types T and U would end up with equivalent memory layout:

typedef float TX[3];
typedef TX TY[4];

typedef Array<float, 3> UX;
typedef Array<UX, 4> UY;

typedef TY T;
typedef UY U;

Thanks.
 
R

Rob Williscroft

bartek wrote in in
comp.lang.c++:

Subject: is this class POD ?
template <class T, unsigned size>
struct Array {

[snip POD-ish stuff]
private:
ValueType m_array[size];
};

It defines neither a copy-ctor nor a destructor.
Does the presence of private section render it as non-POD?

The private section isn't the problem, its the private *data*.
I assume that, if the above class was a POD type, objects of the
following types T and U would end up with equivalent memory layout:

typedef float TX[3];
typedef TX TY[4];

typedef Array<float, 3> UX;
typedef Array<UX, 4> UY;

typedef TY T;
typedef UY U;

I don't really understand the above, but it doesn't matter
as Array<> isn't a POD.

Unfortunatly POD only really exists as a concept to provide
compatibility with how C ( no ++ ) does things, useful uses
beyond that are rare.

Rob.
 
B

bartek

bartek wrote in
in
comp.lang.c++:

Subject: is this class POD ?
template <class T, unsigned size>
struct Array {

[snip POD-ish stuff]
private:
ValueType m_array[size];
};

It defines neither a copy-ctor nor a destructor.
Does the presence of private section render it as non-POD?

The private section isn't the problem, its the private *data*.

That's what I actually meant.
In that case, making the data public would result in the Array class
becoming POD-compliant?
I assume that, if the above class was a POD type, objects of the
following types T and U would end up with equivalent memory layout:

typedef float TX[3];
typedef TX TY[4];

typedef Array<float, 3> UX;
typedef Array<UX, 4> UY;

typedef TY T;
typedef UY U;

I don't really understand the above, but it doesn't matter
as Array<> isn't a POD.

Unfortunatly POD only really exists as a concept to provide
compatibility with how C ( no ++ ) does things, useful uses
beyond that are rare.

Sorry for putting it in a somewhat contrived way.
Indeed C compatibility is what I'm going after.

Say, I have a C library which uses similar typedefs around in its
interfaces:

typedef float my_vector_t[3];
typedef float my_matrix_t[4][4];

I need to use those interfaces from C++ code.
Though, I'd like to keep out from using C arrays in my interfaces, so
wrapping arrays into a class seems a reasonable solution. Moreover, if
those C++ wrapped arrays were binary-compatible with C arrays, I could
gain both performance and unification.

If I was sure that the following C++ objects and C arrays had equivalent
binary representations, I could get rid of explicit conversions on
interface borders, and get the adventage of using strict types throughout
my program.

float x[4][4];
Array<Array<float, 4>, 4> y;
 
R

Rob Williscroft

bartek wrote in in comp.lang.c++:
The private section isn't the problem, its the private *data*.

That's what I actually meant.
In that case, making the data public would result in the Array class
becoming POD-compliant?
Yes.

[snip]
Unfortunatly POD only really exists as a concept to provide
compatibility with how C ( no ++ ) does things, useful uses
beyond that are rare.

Sorry for putting it in a somewhat contrived way.
Indeed C compatibility is what I'm going after.

Say, I have a C library which uses similar typedefs around in its
interfaces:

typedef float my_vector_t[3];
typedef float my_matrix_t[4][4];

I need to use those interfaces from C++ code.
Though, I'd like to keep out from using C arrays in my interfaces, so
wrapping arrays into a class seems a reasonable solution. Moreover, if
those C++ wrapped arrays were binary-compatible with C arrays, I could
gain both performance and unification.

If I was sure that the following C++ objects and C arrays had
equivalent binary representations, I could get rid of explicit
conversions on interface borders, and get the adventage of using
strict types throughout my program.

float x[4][4];
Array<Array<float, 4>, 4> y;

eg

struct xplusplus
{
float x[4][4];
// whatever ...
};

IIU( The Standard )C, x is at offset 0 of xplusplus, but you may
be able to find a platform where sizeof( xplusplus ) > sizeof( x ).

So maybe:

Array<Array<float, 4>, 4> &y = *
reinterpret_cast< Array<Array<float, 4>, 4> * >( x )
;

Will work Ok until you try copying your Array.

Don't do it its UB. If you get your code working, your tying
your code to your current platform and your current compiler.

If you show some samples of the C API your dealing with then
myself or others may be able to give some better advice on
how best to deal with it.

Rob.
 
J

John Carson

bartek said:
template <class T, unsigned size>
struct Array {
typedef unsigned SizeType;
typedef T ValueType;
typedef T* Ptr;
typedef T const* ConstPtr;

// Default copy ctor and assignment op are fine.

SizeType Size() const { return size; }

T& operator[](SizeType i) { return m_array; }
T const& operator[](SizeType i) const { return m_array; }

Ptr Begin() { return &m_array[0]; }
ConstPtr Begin() const { return &m_array[0]; }

Ptr End() { return &m_array[0] + size; }
ConstPtr End() const { return &m_array[0] + size; }

private:
ValueType m_array[size];
};

It defines neither a copy-ctor nor a destructor.
Does the presence of private section render it as non-POD?

I assume that, if the above class was a POD type, objects of the
following types T and U would end up with equivalent memory layout:

typedef float TX[3];
typedef TX TY[4];

typedef Array<float, 3> UX;
typedef Array<UX, 4> UY;

typedef TY T;
typedef UY U;

Thanks.
--
bartekd [at] o2 [dot] pl



http://www.parashift.com/c++-faq-lite/intrinsic-types.html#faq-26.7
 
B

bartek

(...)
eg

struct xplusplus
{
float x[4][4];
// whatever ...
};

IIU( The Standard )C, x is at offset 0 of xplusplus, but you may
be able to find a platform where sizeof( xplusplus ) > sizeof( x ).

Of course, it seems I was missing the obvious all the time.

Somehow, I assumed that:

struct X {
float x;
};

being a POD, should be equivalent to:

float x;

Obviously, I was missing the point. POD-ness is not relevant here.
Thanks for pointing that out.
 
C

Claudio Puviani

bartek said:
template <class T, unsigned size>
struct Array {
typedef unsigned SizeType;
typedef T ValueType;
typedef T* Ptr;
typedef T const* ConstPtr;

// Default copy ctor and assignment op are fine.

SizeType Size() const { return size; }

T& operator[](SizeType i) { return m_array; }
T const& operator[](SizeType i) const { return m_array; }

Ptr Begin() { return &m_array[0]; }
ConstPtr Begin() const { return &m_array[0]; }

Ptr End() { return &m_array[0] + size; }
ConstPtr End() const { return &m_array[0] + size; }

private:
ValueType m_array[size];
};


Because this is a template, whether or not an instantiation is a POD type depends
on the template arguments. An Array<double, 5> would be a POD type, but an
Array<std::string, 7> would not because std::string itself is not a POD. The
presence of typedefs and non-virtual member functions doesn't make a class a
non-POD type.
It defines neither a copy-ctor nor a destructor.

That's irrelevant to determining whether a class is a POD type.
Does the presence of private section render it as non-POD?

No. POD types are allowed to have private sections.

It's a loose convention to make POD types structs (of PODs) with only data
members, but it's not a technical limitation. A class with only POD data members
and with only non-virtual member functions is itself a POD, regardless of how you
set up accessibility. To be even more evil, a class could have non-POD _static_
data members and still be a POD type. :)

Claudio Puviani
 
B

bartek

bartek said:
template <class T, unsigned size>
struct Array {
typedef unsigned SizeType;
typedef T ValueType;
typedef T* Ptr;
typedef T const* ConstPtr;

// Default copy ctor and assignment op are fine.

SizeType Size() const { return size; }

T& operator[](SizeType i) { return m_array; }
T const& operator[](SizeType i) const { return m_array; }

Ptr Begin() { return &m_array[0]; }
ConstPtr Begin() const { return &m_array[0]; }

Ptr End() { return &m_array[0] + size; }
ConstPtr End() const { return &m_array[0] + size; }

private:
ValueType m_array[size];
};


Because this is a template, whether or not an instantiation is a POD
type depends on the template arguments. An Array<double, 5> would be a
POD type, but an Array<std::string, 7> would not because std::string
itself is not a POD. The presence of typedefs and non-virtual member
functions doesn't make a class a non-POD type.


Yes of course you're right. I somehow didn't mention the 'background'
information regarding the class. Indeed, regarding POD-ness, I meant it
only for primitive types.
That's irrelevant to determining whether a class is a POD type.


No. POD types are allowed to have private sections.

It's a loose convention to make POD types structs (of PODs) with only
data members, but it's not a technical limitation. A class with only
POD data members and with only non-virtual member functions is itself
a POD, regardless of how you set up accessibility. To be even more
evil, a class could have non-POD _static_ data members and still be a
POD type. :)

Soon after posting the question, I've realised that I misinterpreted the
definition of POD.

While POD reserves binary compatibility with C structs, I have confused
it with some sort of "encapsulated-type equivalence"... That is, I
thought that a class (no bases, no virtuals, no non-trivial copy or
destruction) with a single data member of type T, is guaranteed to have
the same memory layout as the type T by itself.

I've assumed that:

struct X {
float f[3];
};

has the same binary representation as:

typedef float Y[3];

so that:

X array_of_x[10];

ends up with the same memory layout as:

Y array_of_y[10];

Now I realise that, though, it seems to work on many platforms,
of course, it is not guaranteed.

Cheers.
 
R

Rob Williscroft

Claudio Puviani wrote in @news4.srv.hcvlny.cv.net in comp.lang.c++:
That's irrelevant to determining whether a class is a POD type.

From 9/4:

A POD-struct is an aggregate class that has no non-static data
members of type non-POD-struct, non-POD-union (or array of such
types) or reference, and has no user-defined copy assignment
operator and no user-defined destructor.

"aggregate class" (8.5.1) may not have user defined ctor's, so any
ctor/dtor is right out.

Rob.
 
C

Claudio Puviani

Rob Williscroft said:
Claudio Puviani wrote

From 9/4:

A POD-struct is an aggregate class that has no non-static data
members of type non-POD-struct, non-POD-union (or array of such
types) or reference, and has no user-defined copy assignment
operator and no user-defined destructor.

"aggregate class" (8.5.1) may not have user defined ctor's, so any
ctor/dtor is right out.

Thank you. If I'd taken a moment to think about it, it should have been obvious
to me even without checking the standard, since a memcopy or memset would violate
any contraints imposed by those two functions.

Claudio Puviani
 
J

John Carson

Claudio Puviani said:
A class with only
POD data members and with only non-virtual member functions is itself
a POD, regardless of how you set up accessibility. To be even more
evil, a class could have non-POD _static_ data members and still be a
POD type. :)


Further to Rob's point, 8.5.1 p1 reads:

An aggregate is an array or a class (clause 9) with no user-declared
constructors (12.1), no private or protected non-static data members (clause
11), no base classes (clause 10), and no virtual functions (10.3).


Thus non-static private (and protected) members are ruled out.
 
C

Claudio Puviani

John Carson said:
Further to Rob's point, 8.5.1 p1 reads:

An aggregate is an array or a class (clause 9) with no user-declared
constructors (12.1), no private or protected non-static data members (clause
11), no base classes (clause 10), and no virtual functions (10.3).


Thus non-static private (and protected) members are ruled out.

Again one of those things that 30 more seconds of thought would have brought up.
Since compilers are allowed to reorder data members that have different
accessibility, obviously (in retrospect), classes with mixed access specifiers
can't be POD types.

Interestingly, since a class that has all data members either private or
protected shares the same physical attributes as one that has only public data
members, we can infer that an implicit requirement for a POD is that it must
allow static initializers like:

XYZ xyz = { 1, 'b', 2.7 };

I'm not sure that this limitation is particularly meanigful or useful, but then
again, it doesn't even rank as high as a minor irritant.

Thanks for pointing out clause 11. I need to stop posting at 4am. ;-)

Claudio Puviani
 
J

Jerry Coffin

[ ... ]
Since compilers are allowed to reorder data members that have different
accessibility, obviously (in retrospect), classes with mixed access specifiers
can't be POD types.

Technically, they can be, but they don't provide the guarantees that
people normally associate with POD types. The wording of the standard
also has one other little oddity in this area: even a vacuous access
specifier has the same effect. Consider, the following:

struct X {
int x;
public: int y;
public: int z;
};

This still fits the standard's definition of POD but the relative
order of y and z is not guaranteed, even though neither "public:" has
changed accessibility of anything.

This problem should probably be forwarded to the standards committee,
but I've had a few too many bouts with censorship on
comp.lang.c++.moderated and comp.std.c++, so the dubious honor of
doing so will have to fall to somebody else.
 

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,770
Messages
2,569,584
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top