#include <algorithm>
#include <cassert>
#include <initializer_list>
#include <iostream>
#include <iterator>
#include <memory>
#include <vector>
using namespace std;
// All the JointPool / JointAllocator code would be 'library' code in practice and should be
// compared to the code required to implement joint allocation in the compiler. Once the library
// code is written it can be used fairly simply as demonstrated in the 'Usage' section below.
template <typename T>
struct JointPoolSizeTraits;
struct JointPool {
explicit JointPool(size_t totalBytes)
: m_jointBegin(new char[totalBytes]),
m_jointCurrent(m_jointBegin.get()),
m_jointEnd(m_jointBegin.get() + totalBytes) {}
unique_ptr<char[]> m_jointBegin;
char* m_jointCurrent = nullptr;
char* m_jointEnd = nullptr;
void* allocate(size_t bytes) {
if (m_jointCurrent + bytes <= m_jointEnd) {
auto p = m_jointCurrent;
m_jointCurrent += bytes;
return p;
}
assert(false);
return nullptr;
}
};
template <typename... Ts>
size_t GetJointPoolSize() {
return 0;
}
template <typename T, typename... Ts, typename U, typename... Us>
size_t GetJointPoolSize(U&& arg, Us&&... args) {
return JointPoolSizeTraits<T>::size(arg) + GetJointPoolSize<Ts...>(args...);
}
template <class T>
struct JointAllocator {
typedef T value_type;
JointAllocator(JointPool* pool) : m_pool(pool) {}
JointAllocator(const JointAllocator&) = default;
template <class U>
JointAllocator(const JointAllocator<U>& other)
: m_pool(other.m_pool) {}
T* allocate(std::size_t n) { return reinterpret_cast<T*>(m_pool->allocate(n * sizeof(T))); }
void deallocate(T* p, std::size_t n) {}
JointPool* m_pool = nullptr;
};
template <typename T>
using JointVector = vector<T, JointAllocator<T>>;
template <typename T>
struct JointPoolSizeTraits<JointVector<T>> {
static constexpr size_t size(size_t n) { return sizeof(T*) + sizeof(T) * n; }
};
// Usage - with library support for joint allocation, usage might look something like this:
struct Vector3 {
float x, y, z;
};
struct Mesh {
private:
JointPool pool;
public:
template <typename ItPs, typename ItIs>
Mesh(ItPs firstP, ItPs lastP, ItIs firstI, ItIs lastI)
: pool(GetJointPoolSize<decltype(positions), decltype(indices)>(distance(firstP, lastP),
distance(firstI, lastI))),
positions(firstP, lastP, &pool),
indices(firstI, lastI, &pool) {}
Mesh(initializer_list<Vector3> ps, initializer_list<int> is)
: Mesh(begin(ps), end(ps), begin(is), end(is)) {}
JointVector<Vector3> positions;
JointVector<int> indices;
};
ostream& operator<<(ostream& os, const Mesh& m) {
for (const auto& pos : m.positions) os << "(" << pos.x << ", " << pos.y << ", " << pos.z << "), ";
for (const auto& index : m.indices) os << index << ", ";
return os << endl;
}
int main() {
// initialize a Mesh with explicit verts and indices
Mesh myMesh{{{0.f, 0.f, 0.f}, {1.0f, 0.0f, 0.0f}, {0.0f, 1.0f, 0.0f}}, {0, 1, 2}};
// initialize a Mesh with iterator pairs
Mesh mySecondMesh{begin(myMesh.positions), end(myMesh.positions), begin(myMesh.indices),
end(myMesh.indices)};
cout << myMesh << mySecondMesh;
}
I2luY2x1ZGUgPGFsZ29yaXRobT4KI2luY2x1ZGUgPGNhc3NlcnQ+CiNpbmNsdWRlIDxpbml0aWFsaXplcl9saXN0PgojaW5jbHVkZSA8aW9zdHJlYW0+CiNpbmNsdWRlIDxpdGVyYXRvcj4KI2luY2x1ZGUgPG1lbW9yeT4KI2luY2x1ZGUgPHZlY3Rvcj4KCnVzaW5nIG5hbWVzcGFjZSBzdGQ7CgovLyBBbGwgdGhlIEpvaW50UG9vbCAvIEpvaW50QWxsb2NhdG9yIGNvZGUgd291bGQgYmUgJ2xpYnJhcnknIGNvZGUgaW4gcHJhY3RpY2UgYW5kIHNob3VsZCBiZQovLyBjb21wYXJlZCB0byB0aGUgY29kZSByZXF1aXJlZCB0byBpbXBsZW1lbnQgam9pbnQgYWxsb2NhdGlvbiBpbiB0aGUgY29tcGlsZXIuIE9uY2UgdGhlIGxpYnJhcnkKLy8gY29kZSBpcyB3cml0dGVuIGl0IGNhbiBiZSB1c2VkIGZhaXJseSBzaW1wbHkgYXMgZGVtb25zdHJhdGVkIGluIHRoZSAnVXNhZ2UnIHNlY3Rpb24gYmVsb3cuCgp0ZW1wbGF0ZSA8dHlwZW5hbWUgVD4Kc3RydWN0IEpvaW50UG9vbFNpemVUcmFpdHM7CgpzdHJ1Y3QgSm9pbnRQb29sIHsKICAgIGV4cGxpY2l0IEpvaW50UG9vbChzaXplX3QgdG90YWxCeXRlcykKICAgICAgICA6IG1fam9pbnRCZWdpbihuZXcgY2hhclt0b3RhbEJ5dGVzXSksCiAgICAgICAgICBtX2pvaW50Q3VycmVudChtX2pvaW50QmVnaW4uZ2V0KCkpLAogICAgICAgICAgbV9qb2ludEVuZChtX2pvaW50QmVnaW4uZ2V0KCkgKyB0b3RhbEJ5dGVzKSB7fQogICAgdW5pcXVlX3B0cjxjaGFyW10+IG1fam9pbnRCZWdpbjsKICAgIGNoYXIqIG1fam9pbnRDdXJyZW50ID0gbnVsbHB0cjsKICAgIGNoYXIqIG1fam9pbnRFbmQgPSBudWxscHRyOwoKICAgIHZvaWQqIGFsbG9jYXRlKHNpemVfdCBieXRlcykgewogICAgICAgIGlmIChtX2pvaW50Q3VycmVudCArIGJ5dGVzIDw9IG1fam9pbnRFbmQpIHsKICAgICAgICAgICAgYXV0byBwID0gbV9qb2ludEN1cnJlbnQ7CiAgICAgICAgICAgIG1fam9pbnRDdXJyZW50ICs9IGJ5dGVzOwogICAgICAgICAgICByZXR1cm4gcDsKICAgICAgICB9CiAgICAgICAgYXNzZXJ0KGZhbHNlKTsKICAgICAgICByZXR1cm4gbnVsbHB0cjsKICAgIH0KfTsKCnRlbXBsYXRlIDx0eXBlbmFtZS4uLiBUcz4Kc2l6ZV90IEdldEpvaW50UG9vbFNpemUoKSB7CiAgICByZXR1cm4gMDsKfQoKdGVtcGxhdGUgPHR5cGVuYW1lIFQsIHR5cGVuYW1lLi4uIFRzLCB0eXBlbmFtZSBVLCB0eXBlbmFtZS4uLiBVcz4Kc2l6ZV90IEdldEpvaW50UG9vbFNpemUoVSYmIGFyZywgVXMmJi4uLiBhcmdzKSB7CiAgICByZXR1cm4gSm9pbnRQb29sU2l6ZVRyYWl0czxUPjo6c2l6ZShhcmcpICsgR2V0Sm9pbnRQb29sU2l6ZTxUcy4uLj4oYXJncy4uLik7Cn0KCnRlbXBsYXRlIDxjbGFzcyBUPgpzdHJ1Y3QgSm9pbnRBbGxvY2F0b3IgewogICAgdHlwZWRlZiBUIHZhbHVlX3R5cGU7CgogICAgSm9pbnRBbGxvY2F0b3IoSm9pbnRQb29sKiBwb29sKSA6IG1fcG9vbChwb29sKSB7fQogICAgSm9pbnRBbGxvY2F0b3IoY29uc3QgSm9pbnRBbGxvY2F0b3ImKSA9IGRlZmF1bHQ7CgogICAgdGVtcGxhdGUgPGNsYXNzIFU+CiAgICBKb2ludEFsbG9jYXRvcihjb25zdCBKb2ludEFsbG9jYXRvcjxVPiYgb3RoZXIpCiAgICAgICAgOiBtX3Bvb2wob3RoZXIubV9wb29sKSB7fQoKICAgIFQqIGFsbG9jYXRlKHN0ZDo6c2l6ZV90IG4pIHsgcmV0dXJuIHJlaW50ZXJwcmV0X2Nhc3Q8VCo+KG1fcG9vbC0+YWxsb2NhdGUobiAqIHNpemVvZihUKSkpOyB9CiAgICB2b2lkIGRlYWxsb2NhdGUoVCogcCwgc3RkOjpzaXplX3Qgbikge30KCiAgICBKb2ludFBvb2wqIG1fcG9vbCA9IG51bGxwdHI7Cn07Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgVD4KdXNpbmcgSm9pbnRWZWN0b3IgPSB2ZWN0b3I8VCwgSm9pbnRBbGxvY2F0b3I8VD4+OwoKdGVtcGxhdGUgPHR5cGVuYW1lIFQ+CnN0cnVjdCBKb2ludFBvb2xTaXplVHJhaXRzPEpvaW50VmVjdG9yPFQ+PiB7CiAgICBzdGF0aWMgY29uc3RleHByIHNpemVfdCBzaXplKHNpemVfdCBuKSB7IHJldHVybiBzaXplb2YoVCopICsgc2l6ZW9mKFQpICogbjsgfQp9OwoKLy8gVXNhZ2UgLSB3aXRoIGxpYnJhcnkgc3VwcG9ydCBmb3Igam9pbnQgYWxsb2NhdGlvbiwgdXNhZ2UgbWlnaHQgbG9vayBzb21ldGhpbmcgbGlrZSB0aGlzOgoKc3RydWN0IFZlY3RvcjMgewogICAgZmxvYXQgeCwgeSwgejsKfTsKCnN0cnVjdCBNZXNoIHsKcHJpdmF0ZToKICAgIEpvaW50UG9vbCBwb29sOwoKcHVibGljOgogICAgdGVtcGxhdGUgPHR5cGVuYW1lIEl0UHMsIHR5cGVuYW1lIEl0SXM+CiAgICBNZXNoKEl0UHMgZmlyc3RQLCBJdFBzIGxhc3RQLCBJdElzIGZpcnN0SSwgSXRJcyBsYXN0SSkKICAgICAgICA6IHBvb2woR2V0Sm9pbnRQb29sU2l6ZTxkZWNsdHlwZShwb3NpdGlvbnMpLCBkZWNsdHlwZShpbmRpY2VzKT4oZGlzdGFuY2UoZmlyc3RQLCBsYXN0UCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpc3RhbmNlKGZpcnN0SSwgbGFzdEkpKSksCiAgICAgICAgICBwb3NpdGlvbnMoZmlyc3RQLCBsYXN0UCwgJnBvb2wpLAogICAgICAgICAgaW5kaWNlcyhmaXJzdEksIGxhc3RJLCAmcG9vbCkge30KCiAgICBNZXNoKGluaXRpYWxpemVyX2xpc3Q8VmVjdG9yMz4gcHMsIGluaXRpYWxpemVyX2xpc3Q8aW50PiBpcykKICAgICAgICA6IE1lc2goYmVnaW4ocHMpLCBlbmQocHMpLCBiZWdpbihpcyksIGVuZChpcykpIHt9CgogICAgSm9pbnRWZWN0b3I8VmVjdG9yMz4gcG9zaXRpb25zOwogICAgSm9pbnRWZWN0b3I8aW50PiBpbmRpY2VzOwp9OwoKb3N0cmVhbSYgb3BlcmF0b3I8PChvc3RyZWFtJiBvcywgY29uc3QgTWVzaCYgbSkgewogICAgZm9yIChjb25zdCBhdXRvJiBwb3MgOiBtLnBvc2l0aW9ucykgb3MgPDwgIigiIDw8IHBvcy54IDw8ICIsICIgPDwgcG9zLnkgPDwgIiwgIiA8PCBwb3MueiA8PCAiKSwgIjsKICAgIGZvciAoY29uc3QgYXV0byYgaW5kZXggOiBtLmluZGljZXMpIG9zIDw8IGluZGV4IDw8ICIsICI7CiAgICByZXR1cm4gb3MgPDwgZW5kbDsKfQoKaW50IG1haW4oKSB7CiAgICAvLyBpbml0aWFsaXplIGEgTWVzaCB3aXRoIGV4cGxpY2l0IHZlcnRzIGFuZCBpbmRpY2VzCiAgICBNZXNoIG15TWVzaHt7ezAuZiwgMC5mLCAwLmZ9LCB7MS4wZiwgMC4wZiwgMC4wZn0sIHswLjBmLCAxLjBmLCAwLjBmfX0sIHswLCAxLCAyfX07CgogICAgLy8gaW5pdGlhbGl6ZSBhIE1lc2ggd2l0aCBpdGVyYXRvciBwYWlycwogICAgTWVzaCBteVNlY29uZE1lc2h7YmVnaW4obXlNZXNoLnBvc2l0aW9ucyksIGVuZChteU1lc2gucG9zaXRpb25zKSwgYmVnaW4obXlNZXNoLmluZGljZXMpLAogICAgICAgICAgICAgICAgICAgICAgZW5kKG15TWVzaC5pbmRpY2VzKX07CgogICAgY291dCA8PCBteU1lc2ggPDwgbXlTZWNvbmRNZXNoOwp9Cg==