EEVblog Electronics Community Forum

Products => Computers => Programming => Topic started by: westfw on March 04, 2022, 11:09:41 pm

Title: Compile time C++ constructors?
Post by: westfw on March 04, 2022, 11:09:41 pm
Can I coerce C++ construction of objects to happen at compile time, even for relatively complex objects?
In particular, suppose I want to build a linked list of keywords:
Code: [Select]
keyword *listhead = NULL;
keyword _if(listhead, "if", process_if);keyword _else(listhead, "else", process_else);keyword _while(listhead, "while", process_while);
And I have constructor/object code that looks somewhat like:
Code: [Select]
class keyword {

public:
  const char *text;
  void (*func)(char *);
  keyword *next;
 
  keyword(keyword *&head, const char *t, void(*f)(char *)) {
    text = t;
    func = f;
    next = head;
    head = this;  // add to beginning of linked list
  }
};
In theory, that could all happen at compile time, leaving me with a linked list that could theoretically be "const" and stuck in ROM instead of precious RAM.

Is there a way to make this happen?


Title: Re: Compile time C++ constructors?
Post by: magic on March 05, 2022, 08:25:54 am
I suppose constexpr constructors may work, but not if the constructor writes to a global variable.

You would need to provide a new constructor which takes the next pointer to embed in the given list element explicitly, start constructing your objects from the tail and finally initialize listhead with the last object constructed.

Same thing could be achieved with manually initialized ordinary structs or, if there is no need to add elements dynamically, just make it an array instead of a list.
Title: Re: Compile time C++ constructors?
Post by: retiredfeline on March 05, 2022, 10:35:35 am
Write a script to generate an array of structs/classes and their initializers.
Title: Re: Compile time C++ constructors?
Post by: TheCalligrapher on March 05, 2022, 05:46:26 pm
Can I coerce C++ construction of objects to happen at compile time, even for relatively complex objects?

Easily achievable in C with its compound literals. C++ is trickier.
Title: Re: Compile time C++ constructors?
Post by: SiliconWizard on March 05, 2022, 06:07:12 pm
if there is no need to add elements dynamically, just make it an array instead of a list.

That would be the most reasonable approach.
Or, even if you need a dynamic list, but initialized with some items, just implement a constructor for the list object that takes an array as a parameter to initialize values.
I have a hard time seeing the benefit of going through hoops here, but hey, what do I know.
Title: Re: Compile time C++ constructors?
Post by: TheCalligrapher on March 05, 2022, 07:03:03 pm
if there is no need to add elements dynamically, just make it an array instead of a list.

Well, you can declare an array and still interlink the elements in order to make it conform to list interface

Using the current class declaration

Code: [Select]
class keyword {

public:
  const char *text;
  void (*func)(char *);
  keyword *next;
 
  keyword(keyword *&head, const char *t, void(*f)(char *)) {
    text = t;
    func = f;
    next = head;
    head = this;  // add to beginning of linked list
  }
};

keyword *listhead = nullptr;
keyword keywords[] = { { listhead, "if", process_if }, { listhead, "else", process_else }, { listhead, "while", process_while } };

Sequencing rules guarantee that array elements are constructed left-to-right.

Or you can use a POD-class instead and do this

Code: [Select]
class keyword {
public:
  const char *text;
  void (*func)(char *);
  keyword *next;
};

keyword keywords[] = { { "if", process_if, nullptr }, { "else", process_else, &keywords[0] }, { "while", process_while, &keywords[1] } };
keyword *listhead = &keywords[2];

This feels even more "compile-timeish" although in reality both variants are virtually the same.
Title: Re: Compile time C++ constructors?
Post by: westfw on March 05, 2022, 10:35:33 pm
Quote
keyword keywords[] = { { "if", process_if, nullptr }, { "else", process_else, &keywords[0] }, { "while", process_while, &keywords[1] } };
What was clear from my original message (especially after the forum software mangled my newlines) was that I want to AVOID having a single declaration of a big keyword table.  I want to intersperse the keyword definitions with the code that implements each keyword like:

Code: [Select]
keyword _if(listhead, "if", process_if);
void process_if() {
  // code to process if
}

keyword _else(listhead, "else", process_else);void process_else() {
  // code to process else
}
This makes it easy to add keywords, or leave them out vs conditional compilation, and would make for a cleaner-looking source code (although harder to look at and see which commands are implemented.)

C++ run-time constructors would do this just fine, and they build a data structure that is essentially complete and static that COULD have been built at compile-time.


Quote
just make it an array instead of a list.
I could settle for that, if there is a way to initialize individual elements of an array at different points of the source code...

(I'm pretty sure I could also do this with inline assembly, since assembly macros tend to be much more powerful than C macros.  But... eww.)
Title: Re: Compile time C++ constructors?
Post by: DiTBho on March 05, 2022, 10:49:47 pm
what are you trying to achieve? An interpreter?  :o
Title: Re: Compile time C++ constructors?
Post by: westfw on March 07, 2022, 08:42:07 am
Quote
what are you trying to achieve?
A memory-efficient CLI parser, actually.

Something where if you want to add a new command (keyword), it is relatively easy at the source level, rather than requiring careful editing of complex data structures, tables, and/or case statements.
Title: Re: Compile time C++ constructors?
Post by: retiredfeline on March 07, 2022, 09:23:48 am
Write a script to scan the file containing the bodies of your functions to generate an array of structs/classes and their initializers to another file. Use a distinctive macro for the function header to make it easy for your script.