Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does the "cast to first member of standard layout" type punning rule extend to arrays?

Specifically, I am wrapping a C API in a friendly C++ wrapper. The C API has this fairly standard shape:

struct foo {...};
void get_foos(size_t* count, foo* dst);

And what I'd like to do, is save myself an extra copy by passing a typed-punned wrapper array directly to the C api with a bunch of sanity checking static_assert().

class fooWrapper {
  foo raw_;
public:
   [...]
};

std::vector<fooWrapper> get_foo_vector() {
  size_t count = 0;
  get_foos(&count, nullptr);

  std::vector<fooWrapper> result(count);

  // Is this OK?
  static_assert(sizeof(foo) == sizeof(fooWrapper), "");
  static_assert(std::is_standard_layout<fooWrapper>::value, "");
  get_foos(&count, reinterpret_cast<foo*>(result.data()));

  return result;
}

My understanding is that it is valid code, since all accessed memory locations individually qualify under the rule, but I'd like confirmation on that.

Edit: Obviously, as long as reinterpret_cast<char*>(result.data() + n) == reinterpret_cast<char*>(result.data()) + n*sizeof(foo) is true, it'll work under all major compilers today. But I'm wondering if the standard agrees.

like image 365
Frank Avatar asked Jun 07 '18 18:06

Frank


1 Answers

First, this is not type punning. The reinterpret_cast you're doing is just an over-written way of doing &result.data().foo_. Type punning is accessing an object of one type through a pointer/reference to another type. You're accessing a subobject of the other type.

Second, this doesn't work. Pointer arithmetic is based on having an array (a single object acts as an array of 1 element for the purposes of pointer arithmetic). And vector<T> is defined by fiat to produce an array of Ts. But an array of T is not equivalent to an array of some subobject of T, even if that subobject is the same size as T and T is standard layout.

Therefore, if get_foos performs pointer arithmetic on its given array of foos, that's UB. Oh sure, it will almost certainly work. But the language's answer is UB.

like image 164
Nicol Bolas Avatar answered Sep 27 '22 23:09

Nicol Bolas