Re: c++0x pods and constructors
On Oct 31, 4:12 am, "dragan" <spambus...@prodigy.net> wrote:
James Kanze wrote:
On Oct 29, 11:40 pm, "dragan" <spambus...@prodigy.net> wrote:
I think "aggregate" gets thrown around so much, but it should
probably be reserved more for implementer-level discussion
rather than user-level. It seems so minor relative to the
notion of POD (or layout compatibility! Errgh, so
frustrating!).
Yes and no. For the user, aggregate initialization can be an
advantage in certain cases, e.g. my examples of letting the
compiler calculate array size. For the user, there are really
three things which interesting:
1. Aggregate initialization: useful for letting the compiler
calculate the size of an array, and in general for static
data.
2. Static initialization, for avoiding order of initialization
issues. This requires trivial constructors and constant
expressions in the initializer; for compound types (struct's
and arrays), the type must be an aggregate, and aggregate
initialization must be used. (Otherwise, you must have a
constructor somewhere, and the type ceases to be trivial.)
3. PODs or layout compatibility: mainly important with regards
to communicating with other languages, especially C. (The
system API is generally defined in terms of C these days.)
I think POD may be the key thing for layout compatibility
with C and probably other languages. PODs no longer have to
be aggregates in C++0x: they can have constructors, just
not default or copy constructors, and no copy assignment
operator. (N2690).
Layout compatibility is an awkward problem. C++ can mandate
a certain number of things with regards to how the C++
compiler lays out data, but it can't mandate anything with
regards to how other languages layout data. In the end,
it's a lot like the ``extern "C"'' fiasco: C++ requires a
compiler to support it, stating that functions declared
``extern "C"'' must be callable from C (or something along
those lines). Which is all nice and fine, but what does it
mean if the platform doesn't have a C compiler? Or if it
has several C compilers, with different calling conventions?
"extern C" fiasco? News to me that it was a fiasco (you must
be an implementor/insider, I bet)! I thought it was more like
"thank god we can still use DLLs in C++".
Fiasco may be too strong a word, but formally, the standard
guarantees much less than it seems to. (I certainly doesn't
guarantee anything with regards to DLLs, for example.) All that
it says (with regards to C) is ``Every implementation shall
provide for linkage to functions written in the C programming
language, "C", and linkage to C + + functions, "C++".'' Except
that it doesn't specify how these "functions written in the C
programming language" are to be compiled or linked; an
implementation may require you to compile them using a special C
compiler, which generates code incompatible with the system API,
for example. And it doesn't address the issue of what to do if
there is no C compiler for the system.
At least some of the people involved with the standardization
proceedure are aware of this weakness, although the committee
doesn't seem to have wanted to address it. I think the general
intent is more along the lines that IF there is at least one C
implementation available on the platform, then the compiler must
support linkage with one of them, and document which one, and
what is necessary to make it work.
The probable reason the committee didn't address the problem is
that it isn't one in practice. Practically all platforms that
support C++ have a standard C ABI, which is adhered to by all C
compilers, and practically all C++ compilers come with a C
compiler, and require no special steps to link C and C++. So
the standard may not say exactly what was wanted, but in
practice, everything works as was desired.
Until the day someone decides that C is dead enough that they
don't need a C compiler for their platform.
[...]
If you look at it closely, you'll see that the standard
doesn't actually give any guarantees with regards to
standard layout and other languages, for the reason stated
above.
'Care to restate that reason?
The C++ standard can't impose anything on other languages, only
on C++.
There may be some advanced programming techniques which
depend on standard layout, but for the everyday user, the
only really significant distinction is whether the class
could be written in C or not
You meant if a class could look like a struct to C, surely.
More or less, yes. With the addition of non-virtual member
functions, but that's about it.
---if it could, it will be accessible from C, and probably
from most other languages as well (on typical small and
medium general purpose computers
That covers a lot (the most of it?) of ground, and propably
shouldn't be flattened.
Typical small and medium general purpose computers represent but
a small percentage of all computers. I'd guess off hand that
something like 90% of all computers are embedded systems. At
the other end, and this is the place where I suspect most of the
problems come, are the mainframes. IBM System z doesn't define
everything in terms of C, at least under the traditional OS's.
(You can also get it with Linux.) Cobol is still the
predominant language there.
---I wouldn't count on it on mainframes, nor for that matter
on embedded systems); otherwise, it won't be. (You may, of
course, add non-virtual member functions, including
conversion operators, but not constructors, destructors or
assignment operators, without causing problems.)
I'm still hoping that Mr. Coffin was right about "convenience
constructors" being OK. (Else I'll have to research and find
out why there cannot be such. I'll blindly accept the
concrete "special functions" as being special and reserved,
but I really would want to know why "convenience constructors"
are a no-go, if indeed so).
You can't add "convenience constructors" today, and I'm sure
that Jerry didn't say that. The next version of the standard
will allow it, I think, but only if you explicitly say you want
the "trivial" default constructor. And while initialization
syntax has been somewhat unified, I still don't think you can
get all of the features of aggregate initialization (especially
static initialization) if you provide any constructor; at most,
you'll be guaranteed a C compatible layout (but that's typically
the case today, with most compilers).
The other thing that is often important is whether the class
is an aggregate which supports static initialization. But
in practice, the two overlap; there are very few cases where
you can use static aggregate initialization but couldn't
write the class in C. (The presence of a pointer to member
in the class would be an example of one.)
I should have stopped responding to your post probably after I
asked whether you meant the current standard or the yet-to-be
(draft) C++. All of a sudden, I feel like I know NOTHING!
Errrgh!! I think my house may explode if I start up Visual C++
and _I_ use it! I saw no red sticker on the box.. I got it for
free as a download! ;)
Unless I explicitly state otherwise, I'm talking about the
current standard. There are no implementations of the next
standard (can't be, since it doesn't exist yet), and the way
things are going, I'm beginning to wonder if there will be any
in my lifetime.
With regards to Visual C++, it's a concrete implementation;
concrete implementations always give you a lot more guarantees
than the standard gives.
As long as you're not concerned with portability, you can use
all of the guarantees the implementation gives. Once you're
concerned about portability, especially about potential
portability to systems you don't know yet, it becomes trickier.
How about conversion operators?
You can have conversion operators in an aggregate
(according to the definition), if other conditions are
met.
I assume in a POD also.
A conversion operator is just an ordinary member function.
A positive note for the post to end on! At least something is
concrete! (Until someone says a POD can't have member
functions!)
(Aside: Are overloaded operators fast compared to functions? I
don't know why that sticks in my mind. Yeah I know, I could
test it, but I think in the past I have and have found that. I
may be mistaken).
An overloaded operator is just an ordinary function with a funny
name. The only time they might impact performance is when they
are used instead of a built-in operator.
--
James Kanze