Things like: what information does the compiler have at this point? What information would it need to do this transformation? What border cases does it have to handle? This leads to consequences such that it has to generate an exception handling frame here because it cannot prove that this trivial function never throws, that it has to instantiate (and thus has to see) this template here because it cannot assume anything about it being instantiated elsewhere, or that 'std::string s = a+b+c+d;' creates an uncomfortable number of temporaries whereas 'std::string s = a; s += b; s += c; s += d;' does not.
Call it "what happens under the hood" or "how does the compiler think", the idea is the same.
Why not? C++ at least makes it a language feature and a library feature to make my own allocator.
But if I cannot use 'new' and 'delete' the answer simply becomes: "I cannot use the language features 'new' and 'delete'" :-) I also cannot use most of the STL, but that's not a core language feature.
Because on some compilers this is the matter of just flipping a switch, so I can use my already-written classes; on others I'd have to write special exception-less code to avoid that the compiler generates code I do not want.
What else are you expecting? Other memory saving techniques like using bitfields ("enum {...} foo : 8" to save 3 bytes) are not C++-specific, and apply to C as well.
In this particular case, the class went roughly like this: template class Queue { void post(const T& t) { m_elems[m_head++ % N] = t; } T get() { return m_elems[m_tail++ % N]; }
T m_elems[N]; size_t m_head, m_tail; }; (details omitted) where each function generates a few machine instructions only. Adding a void* and a size_t would only have made matters more complicated.
Well, I did that before using it in the next project, where we finally hat infrastructure for making unit tests in the build system :)
Stefan