I ran to an over-specialized container somewhere in production code. It was C++98 upgraded to C++11, but I wonder how many UBs (or implementation-defined behaviors) are in it. Basically, without any useful interfaces the idea boils down to this:
template<class T>
class Box {
public:
using DataType = T;
Box() : sz(def_size), data_ptr(allocate(def_size)) {}
T* data() { return reinterpret_cast<T*>(data_ptr); }
protected:
using BlockType = alignas(alignof(T)) char[sizeof(T)];
BlockType * allocate(size_t sz) {
BlockType* ptr = new BlockType[sz];
for(auto p = ptr, ptrE = ptr + sz; ptr != ptrE; ++ptr ) {
auto* obj = new(p) T;
// do some initialization on obj
}
return ptr;
}
private:
size_t sz;
BlockType *data_ptr;
};
One I can think of: compiler is not required to implement that kind of over-alignment. A cross-compiler used for project did.
But did the C++ standard define the use of pointer arithmetics on the value returned by data()
as a pointer to an element of an array? Pointers to blocks aren't necessary to be pointers to instances of T?