I am aware of the strong type-aliasing rule. However, cppreference notes that
An implementation cannot declare additional non-static data members that would occupy storage disjoint from the real and imaginary components and must ensure that the class template specialization does not contain any padding. The implementation must also ensure that optimizations to array access account for the possibility that a pointer to value_type may be aliasing a std::complex specialization or array thereof.
Does this requirement allow code like the following to be legal, even if it isn't necessarily moral?
std::size_t numDoubles = 100;
double* a = (double*) std::malloc(numDoubles * sizeof(double));
std::complex<double>* b = reinterpret_cast<std::complex<double>*>(a);
DoSomethingWith(b[1]);
Does the answer change if new[] is used to generate the array-of-double?
XY Problem Explanation: I'm trying to abstract over an allocator provided by a third-party library that might not be present; that allocator returns a void*; I'm trying to avoid the does-the-library-exist details leaking into the header. So I have a structure like the following:
// foo.h
namespace impl {
void* Allocate(std::size_t numBytes);
}
template<typename T>
T* Allocate(std::size_t num) {
static_assert(std::is_pod_v<T>);
return static_cast<T*>(Allocate(num * sizeof(T)));
}
// foo.cpp
#if LIBRARY_PRESENT
void* impl::Allocate(std::size_t numBytes) { return LibraryAllocate(numBytes); }
#else
void* impl::Allocate(std::size_t numBytes) { return std::malloc(numBytes); }
#endif
Unfortunately, std::complex is not POD, because it has a non-trivial default constructor. I'm hoping I can ignore that problem.