0

I want to write simple C++ wrapping (for RAII purposes) around the following C API:

typedef void* T;

T createT(Arg arg);
int foo(T t);
closeT(T t);
int bar(const T* ptrToArrayOfT, unsigned long size);

For the first three functions it's simple (for shortiness I omit checking for errors and throwing exceptions):

class C {
public:
  C(Arg arg) : t_(createT(arg)) {}
  ~C() { closeT(t_); }
  int doFoo() { return foo(t_); }
private:
  T t_;
}

As for bar I would like to have function with the following signature:

int doBar(const vector<C>& vec);

Here is how I'm thinking of implementing it:

int doBar(const vector<C>& vec) {
  static_assert(sizeof(C) == sizeof(T));
  return bar(reinterpret_cast<const T*>(vec.data()), vec.size());
}

Is it safe way to do? (I doubt because C has private member). If it's not, then is there any way to implement bar() without giving out t_ member of C? (Using vector is not necessary).

Dmitry J
  • 867
  • 7
  • 20
  • The static assertion is meaningless, since `T` is defined as `void*`. – Bartek Banachewicz Jul 27 '17 at 13:56
  • @BartekBanachewicz, I don't assert for size of what `T` is pointing to. I assert that `C` has exactly same size as `void*`. – Dmitry J Jul 27 '17 at 13:59
  • What is the purpose of the `bar` function? – Holt Jul 27 '17 at 14:12
  • @Holt, how is that important? Ok, it kind of waits for signals from objects T is pointing to, and returns index of the one that signaled. But whatever it does, I can't implement it's functionality on my own, I have to form an array of `T` and pass it to `bar`. – Dmitry J Jul 27 '17 at 14:24
  • 1
    @DmitryJ Exactly. But per the standard `sizeof(void *)` (remember `typedef void* T;`) is undefined. – idmean Jul 27 '17 at 15:02

1 Answers1

0

No, this code is not safe and violates strict aliasing.

You can easily write this, for instance, without giving access to t_:

int doBar(const vector<C>& vec) {
  std::vector<const T> ts();
  ts.reserve(vec.size());
  for (auto c : vec) {
     ts.emplace_back(c.t_);
  }
  return bar(ts.data(), ts.size());
}
idmean
  • 14,540
  • 9
  • 54
  • 83