[cpp-threads] More niggles on the strawman proposal

Ben Hutchings ben at decadentplace.org.uk
Wed Jan 18 21:21:12 GMT 2006


Nick Maclaren wrote:
> Here are some more points that need addressing in the strawman model,
> that I have discovered when reading through the C++ standard.
> 
> 
> My Objects Diatribe
> -------------------
> 
> Upon studying it, C++ seems to have eliminated (or not introduced) all
> of the worst problems.  My reading of C++ is that basic actions take
> place on most derived types,

What do you mean by "basic actions"?

> and that most (or all) of the ghastliest
> punning allowed by C is forbidden in C++.

Most of the ghastliest type-punning in C is strictly forbidden by the C
standard too!  C++ has stricter rules for non-POD types, but for POD
types I'm not aware of any restrictions on type-punning beyond those in
C.  There's actually a slight relaxation in that an object of POD type
may also be accessed as an array of char or unsigned char, where C
doesn't promise this for an array of char.

> There are only three issues that I can't resolve.
> 
> The first is that I can't find where it specifies when the array to
> pointer conversion is performed, and when it is not.

It is done wherever an rvalue is required.

> By experiment, it
> seems to be done for all function arguments and not much else, though I
> have failed to locate the wording.

The conversion itself is specified as a standard conversion in
[conv.array] (4.2).  There are references in several places to
lvalue-to-rvalue conversion, array-to-pointer conversion and
function-to-pointer conversion, the latter two covering the types that
don't have rvalues.

> Another aspect of this is that there is the same fundamental ambiguity
> with any function that is polymorphic and can take array arguments, but
> I can't find any of them.

C++ makes the same adjustment of array-typed parameters as C, so for
example the declarations

    void f(const char []);
    void f(const char *);

refer to the same function.

It is possible to pass array lvalues as references, but then they must
be of known dimension, e.g.:

    void f(const char (&)[10]);

Unfortunately the overload rules are such that f("abcdefghi") would be
ambiguous; both these functions are an equally good match for an
argument of type const char[10].

> Encapsulated classes do not, of course, have
> the same problems.
> 
> The second is the issue to do with padding bytes in structure and union
> members (because they are POD aggregates).  For example, is the
> following permitted?
> 
>     union (int a[2]; int b;}
> 
> Thread 1:  a[1] = 0;
> Thread 2;  b = 1;
> 
> This isn't introduced by threading, of course, because it also shows up
> in "(a[1] = 0)+(b = 1)", but it will be more important in threaded
> programs.  It needs clarifying, unless I have simply failed to find the
> reference.

The specification of unions in [class.union] (9.5/1) says that only one
member can hold a value at once.  So even though a[1] does not overlap
b, it is undefined behaviour to read it after writing to b.  So I think
the above multithreaded code will be defined to have a data race without
any need for particular mention of unions.

<snip>
> Initialization, Constructors and Copying of Aggregates
> ------------------------------------------------------
> 
>     1) C++ makes a definition visible before it is initialised (3.3.1)
> and forbids access to its members only for const-qualified objects
> (8.5).  In fact, there is an implication that constructors with
> side-effects are called sequentially in sub-object order.

That's guaranteed by [class.base.init] (12.6.2).

> Threading makes the sequencing more visible than it is in a serial
> program, including in cases like:
> 
>     int n = ...;
>     int a[5] = {1,2,n,4,5};
> 
> Does C++ require the sub-objects to be initialised, copied etc. in
> order?  That is how I read it, and will assume it, but it then brings in
> the question of what the occurs-before constraints are, especially when
> doing such things on volatile (or __asynch volatile) sub-objects.

Initialisation order is sort of implied by the wording in 8.5.1/10, but
that's rather tenuous.  Arrays cannot be assigned to, but they can be
copied by a default copy-constructor of a class type (12.8/8), and that
certainly doesn't specify the order in which array elements are copied.

> I don't see this as being a major difficulty, but I do see it as
> impacting performance.

-- 
Ben Hutchings
Make three consecutive correct guesses and you will be considered an expert.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: This is a digitally signed message part
Url : http://www.decadentplace.org.uk/pipermail/cpp-threads/attachments/20060118/034b71b1/attachment.pgp


More information about the cpp-threads mailing list