Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ Puzzle: Prevent heap allocation for derived classes, allow automatic and static

Tags:

c++

Objectives:

  1. Objects of class Base may be static, automatic, allocated directly on the heap, and take part in composite objects allocated anywhere
  2. 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."

like image 237
Thomas L Holaday Avatar asked Jul 15 '09 18:07

Thomas L Holaday


1 Answers

Hmm, Eclipse's answer is gone, but I thought it was on the right track.

class Base {
public:
    static Base *create() { return new Base; }
    static Base *create(size_t n) { return new Base[n]; }
private: 
    // Prevent heap allocation
    void *operator new(size_t s);
    void *operator new[](size_t s);
};

This isn't nice, as it obligates you to use Base::create() instead of new Base, and class Derived could still go and implement its own public operator new, but I think it's workable.

like image 144
ephemient Avatar answered Sep 27 '22 20:09

ephemient