Objectives:
- Objects of class Base may be static, automatic, allocated directly on the heap, and take part in composite objects allocated anywhere
- For any class Derived which has Base as an accessible ancestor, objects may be static or automatic and take part in composites, but may not be allocated directly on the heap
Example:
#include "Base.h"
#include "Derived.h"
{
static Base sb; // OK
Base ab, *hb = new Base; // OK
static Derived sd; // OK
Derived ad; // OK
Derived *pd = &ad; // OK
Derived *hd = new Derived; // Compile error, link error,
// test-unit exception, or lint gripe
struct Composite {
Base cb;
Derived cd;
} *hc = new Composite; // OK
// Edit to show side-effects of solutions which hide Base::operator new.
std::vector<Base> vb; // OK
std::vector<Derived> vd; // Error
// ...
}
How could Base be implemented to achieve this? A compile-time error is preferred to a link-time error; but although both are preferred to a test-unit exception, and a test-unit exception is preferred to a lint gripe, any solution that does not require an update to Base.h for each derivation will do.
Edit: For the purposes of this question, solutions which involve forking the compiler so that it supports arbitrary decorations are, despite the technical challenge, classified as "trivial."