On Sun, Jul 28, 2013 at 10:42 AM, Nevin Liber <nevin@eviloverlord.com> wrote:
On 28 July 2013 11:44, Gabriel Dos Reis <gdr@cs.tamu.edu> wrote:
We shouldn't be doing anything in rash.

Who is arguing for a rash decision?  This sounds like a straw man to me.

As far as I can tell, we are exploring how to meet this very real need of programs (efficiently turning a buffer of raw data into something which has structure), which is currently being met (either accidentally or deliberately) by relying on certain undefined behavior not being undefined in any practical sense.

FWIW, I don't agree that such code necessarily has undefined behavior. Consider this ugly code, which is the kind of thing people have been writing for years:

ALIGNED(16) char buffer[BUFFER_SIZE];
size_t buffer_pos, buffer_read;

T *get_from_network() {
  if (buffer_pos + sizeof(T) < buffer_read) read_more_into_buffer(sizeof(T));
  assert(is_suitably_aligned_for<T>(buffer+buffer_pos));
  return (T*)buffer[buffer_pos];
}

Now, [basic.life]p1 says that, unless the object has non-trivial initialization, its lifetime begins "when storage with the proper alignment and size for type T is obtained". The wording here is circular, because we don't know whether an object is being initialized until we know whether its lifetime begins, and vice versa, but it can be argued that the lifetime of a T object began *before* the data was copied into the buffer, because storage with suitable size and alignment was obtained before that point.

More generally, my view of how the lifetime rules in [basic.life]p1 are intended to work is:
 * If there exists a set of times when objects' lifetimes begin and end, and that set gives the program defined behavior, then the program has defined behavior
 * Otherwise, the program has undefined behavior

(In effect, the programmer chooses when lifetimes begin and end, and does not need to write this intent in the source code.) Different choices of lifetime beginning/end can only change whether the program has defined behavior, and cannot imbue it with two different defined behaviors, so this approach seems to be coherent, and (I think) captures what people expect.

(The [basic.life]p1 rules are also somewhat defective, because obtaining storage of suitable size and alignment for an object of class type without a trivial default constructor should not start the lifetime of such an object, but if the object is not initialized, the relevant rule does not apply.)