#include <string.h>

// g++ -m32 -O3 -fomit-frame-pointer -Wall -fno-rtti -fno-exceptions -S comparison.cc

class Object {
};

class String: public Object {
};

class TypePun {
 public:
  inline TypePun(Object** o) {
    union_.object_ = o;
  }
  inline TypePun(String** s) {
    union_.string_ = s;
  }
  inline Object** object() {
    return union_.object_;
  }
 private:
  union {
    Object** object_;
    String** string_;
  } union_;
};

template <class Dest, class Source>
inline Dest bit_cast(const Source& source) {
  // Compile time assertion: sizeof(Dest) == sizeof(Source)
  // A compile error here means your Dest and Source have different sizes.
  typedef char VerifySizesAreEqual [sizeof(Dest) == sizeof(Source) ? 1 : -1];

  Dest dest;
  memcpy(&dest, &source, sizeof(dest));
  return dest;
}

extern "C" {

  extern String* s;

  extern void bar(Object** o);

  extern void use_union() {
    bar(TypePun(&s).object());
  }

  extern void use_bit_cast() {
    bar(bit_cast<Object**, String**>(&s));
  }

  extern void use_reinterpret_cast() {
    bar(reinterpret_cast<Object**>(&s));  // Causes warning with -Wall -O3 on gcc-4.2.
  }

}

