I’m glad there is a way to get desired results.
I don’t know if trying to imitate every Interesting feature that other languages offer in fpc project is a good idea or not. It could certainly lead to bloat.
I’ve just been trying to come up with good answers to questions along the lines of ..can fpc do such and such like this other language...
Metaprogramming in a more general term (not just the C++ style Template Metaprogramming) basically allows you to extend the language without having to touch the formal definition of the grammar or the compiler. This can be really useful. For example Pascal has a lot of compiler magic. One of the most magical functions is WriteLn, it can take an arbitrary number of Parameters and print them. More importantly, unlike "array of const" or other variant based structures, this is compile time decided not runtime, and it works with all kinds of types like enums:
var
i: Integer = 42;
e: TMyEnum = meSomeValue;
d: Double = 3.14;
c: Char = 'A';
s: String 'Hello World';
begin
WriteLn(i, e, d, c, s); // Prints all those variables
This is hardcoded in the compiler, there is no way on earth to build such a function yourself using pure Pascal. But in C++ this is easy:
void WriteLn() {
std::cout << '\n';
}
template <typename T, typename ...Args>
void WriteLn(T const &first, Args... rest) {
std::cout << first;
WriteLn(rest...);
}
int main() {
WriteLn('H', "ello World", 3.14, 42);
return 0;
}
So in C++ you can rebuilt the compilermagic from pascal in language through meta programming.
That can be really useful. For one example where I used a generator script is in my STAX, there I have tasks, which run asynchronously. These Tasks in the Scheduler are Classes, but because I want to be able to simply call functions asynchronously:
s := Await(AsyncFunction(@SomeFunctionThatReturnsString, Parameters));
I somehow need to write the AsyncFunction function that turns a function pointer and a list of parameters into a Task object that internally calls the function with these parameters.
The problem is, because Pascal Generics are quite limited, I can only define one AsyncFunction definition for a specific number of arguments, so to support doing this with a function that takes one parameter requires a seperate implementation of the same taking two parameters, etc. Not to mention that there is a difference between function, method and nested function pointers, which basically tripples the effort.
So what I did was to simply write a generator that would generate all these definitions for me for functions with 0-5 parameters. The result can be seen here:
https://github.com/Warfley/STAX/blob/master/src/functional/stax.functional.pasUsing a code generator is, by the more liberal definition of "meta programming" in general a form of it. But of course it's not really practical, and if someone needs lets sa a function with 6 parameters, the generator script needs to be changed. This would all not be necessary if there was some in-language way to do this metaprogramming
Metaprogramming has it's place, for example it is undeniable that the metaprogramming that LISP provides through it's inherent design (Data is Code) and the LISP Macros, is what has kept LISP not just alive, but at it's core mostly unchanged for the past 70 years. There is this joke that LISP is actually the perfect language, because while being one of the oldest programmin languages in existance, it is still quite popular without any large changes to it's design over it's whole lifetime, and most changes that there are were made in language through metaprogramming. As comparison, even C has been under heavy change between ANSI C, C89, C99 and C11. C++ has had major updates in 2011 and 2020, and Pascal has also gone through many iterations until where we are now., because it was one of the first major programming languages, and is the only one thats still around without going throuhg major changes.
Metaprogramming can make a language future proof without having to constantly update the language and create new features. But on the other hand, if you look how it went for C++, advanced C++ with template programming is borderline undecipherable for anyone who does not have some background in C++, with new things being added regularly making it often more complex, as new features are introduced constantly.
So personally, I don't think that C++ is necessarily a model to folow