Modula-2 had this interesting feature where, for example if you had a
pointer variable whose pointed-to objects were of type T
VAR
ptr : POINTER TO T;
and you had a statement like
ptr := NEW(T);
C could benefit from some similar high-level+low-level layering like this, don’t you think?
On 2024-02-09, Lawrence D'Oliveiro <ldo@nz.invalid> wrote:
Modula-2 had this interesting feature where, for example if you had a
pointer variable whose pointed-to objects were of type T
VAR
ptr : POINTER TO T;
and you had a statement like
ptr := NEW(T);
[ ... ]
C could benefit from some similar high-level+low-level layering like this, >> don’t you think?
Yes, someone thought that (and other things) and came up with C++.
T *p = new T;
If T is a class, it can have its own allocator. The new operator
ensures that the constructor is called to initialize the T object.
You can pass constructor parameters to choose different constructor overloads:
T *p = new T(4, "blah");
Modula-2 had this interesting feature where, for example if you had a
pointer variable whose pointed-to objects were of type T
VAR
ptr : POINTER TO T;
and you had a statement like
ptr := NEW(T);
then the compiler would translate the “NEW(T)” into “ALLOCATE(TSIZE(T))”,
where the “ALLOCATE” function was not actually provided by the language, but had to be defined/introduced in the current scope somehow (perhaps IMPORTed from some implementation-provided library).
This allowed for memory allocations (and also deallocations) to be
expressed in a type-safe fashion, while still leaving the low-level
details of memory management up to some library/user code that was not an integral part of the language implementation.
So you had a builtin function, NEW(), that could take a type as an
argument and return a result of the appropriate pointer type, which a
normal user-defined function could not do, but the compiler would delegate the main work to a lower-level function that didn’t need to know anything about the language type system, it only needed to know how much memory to allocate, and would return an untyped pointer, which the compiler would
then take care of turning into a pointer of the required type.
C could benefit from some similar high-level+low-level layering like this, don’t you think?
This is C23 code
#include <stdlib.h>
#include <string.h>
static inline void* allocate_and_copy(void* s, size_t n) {
void* p = malloc(n);
if (p) {
memcpy(p, s, n);
}
return p;
}
#define NEW(...) (typeof(__VA_ARGS__)*)
allocate_and_copy(&(__VA_ARGS__), sizeof(__VA_ARGS__))
#pragma expand NEW
struct X {
const int i;
};
int main() {
auto p = NEW((struct X) {});
}
Modula-2 had this interesting feature where, for example if you had a
pointer variable whose pointed-to objects were of type T
VAR
ptr : POINTER TO T;
and you had a statement like
ptr := NEW(T);
then the compiler would translate the “NEW(T)” into “ALLOCATE(TSIZE(T))”,
[...]
C could benefit from some similar high-level+low-level layering like this, don’t you think?
Sysop: | Keyop |
---|---|
Location: | Huddersfield, West Yorkshire, UK |
Users: | 546 |
Nodes: | 16 (2 / 14) |
Uptime: | 47:11:10 |
Calls: | 10,397 |
Calls today: | 5 |
Files: | 14,066 |
Messages: | 6,417,277 |
Posted today: | 1 |