It seems that you're using an outdated browser. Some things may not work as they should (or don't work at all).
We suggest you upgrade newer and better browser like: Chrome, Firefox, Internet Explorer or Opera

×
low rated
Just one question that I've come up with, about a situation that I personally haven't encountered, but which seems realistic.

Suppose that we're developing software for an embedded system, and we have a C++ compiler that, while, functional, is a bit outdated; in particular, it does not support constexpr. (Let's just say it supports the C++98 standard, if you want a specific version.) For the software being developed, it has been determined that we need to pre-compute some values at compile time. (Doing this at run-time is not feasible, as the target CPU is rather weak and computing the values at run-time would take too long.) So, looking at the situation, we have found two reasonable options. Which of these options would be a better choice?

1. Use template metaprogramming to compute the values at compile-time. This, while clever, can be a pain for C++ programmers who aren't used to it to understand, and it is a bit ugly.

2. Write a program on the host system that, when executed, would generate a C++ source file containing the computed values, and work it into our build system. This means we can use any language available on the host, but it does make the build a bit more complicated.

So, which would be the better option in this situation?

Edit: Fix a missing negative.
Post edited February 22, 2019 by dtgreene
(2) unless you want your developers to spend the next 6 months learning how to properly write templates... not to mention spending a lot of time double-checking that they work as intended...
avatar
IFW: (2) unless you want your developers to spend the next 6 months learning how to properly write templates... not to mention spending a lot of time double-checking that they work as intended...
Ditto... option 2 would be what I would go with too. For pretty much the exact same reasons.
I'll add my voice to option no. 2 as well, with the same reasons as IFW. Furthermore haven written few a lot of non-trivial template-heavy code, I've stumbled upon bugs in GCC (mostly 4.8.1), where it refused to compile valid code, so if you have an outdated compiler (even if it isn't GCC), you may run into trouble with the first approach. Another issue might be if you don't enable optimisations, the resulting executable may become quite large (and possibly also slower). Of course, there's also the problem with template error messages which are notoriously bad, which again detracts from option 1.
2 for sure.
Out of those options, 2 hands down. But...

How about 3) Use a better compiler?

You said the situation is realistic. Could you give an example of a situation where 3 is not feasible?
Regarding option 2, wouldn't the generation and execution of said CPP source files demand those calculations anyway? If that is the case wouldn't that make it just a longer route to impose the same task exactly on the processor you wanted to spare?

I think that option (2) can be better-ish as long as the answer to my question above is "No", but even the drawbacks raised against (1) can be circumvented without much extra work.

Edit: I'm with ZFR too, the ideal solution appears to be "Get a better compiler"
Post edited February 21, 2019 by joppo
avatar
ZFR: How about 3) Use a better compiler?

You said the situation is realistic. Could you give an example of a situation where 3 is not feasible?
The target is some obscure embedded microchip, and the only compiler that can target it is the one supplied by the vendor, which happens to only support the only compiler. Switching to a more modern compiler would require changing the hardware on which the final product will run, and that might not be so simple, especially if the hardware has already been deployed and the software needs updating.
avatar
joppo: Regarding option 2, wouldn't the generation and execution of said CPP source files demand those calculations anyway? If that is the case wouldn't that make it just a longer route to impose the same task exactly on the processor you wanted to spare?
Yes, but the calculation would be done on the host, not the target. (We're talking about developing for an embedded system.) As a result, we are using the host's CPU cycles to spare the target's CPU. (Also, if there's no free persistent storage on the target, this avoids having to do the calculations on each reset.)
Post edited February 21, 2019 by dtgreene
Hmmm... I have to agree with the others, #2 is preferred. Which would likely simply be a separate program making the table you want ahead of time. Which could be as simple as adding a #ifdef in which declares a main for use in creating said tables and outputting to a text file.

Course with D and CTFE the difference is literally just making it an immutable object (enum works too) and it handles compile-time to make the value ahead of time.

CTFE assumes no system specific assembly code, or memory trickery in getting the work done.
avatar
rtcvb32: Course with D and CTFE the difference is literally just making it an immutable object (enum works too) and it handles compile-time to make the value ahead of time.
I believe C++'s constexpr is supposed to allow that sort of thing, but it requires at least C++11, and there are limitations on what you can put in such a function (that were relaxed in C++14).

There's also const fn in rust, which might allow a similar optimization.
avatar
dtgreene: Just one question that I've come up with, about a situation that I personally encountered, but which seems realistic.
Can I come live with you in fantasy Oz Neverland some time? ;)
2) 2) and more 2)
you do not want your source code to be not understood

this is the paradigm all the ancient coders and hipsters do wrong. a new employee being able to read the code comes first. most of all today as we are fast enough.

for the record, i haven't coded c++ in decades and frankly this wisdom is not dependent on a specific language.
Post edited February 22, 2019 by AlienMind
avatar
dtgreene: Just one question that I've come up with, about a situation that I personally encountered, but which seems realistic.
avatar
Ixamyakxim: Can I come live with you in fantasy Oz Neverland some time? ;)
Oops! Thanks for pointing that out. (The missing negative has been fixed.)
avatar
dtgreene: I believe C++'s constexpr is supposed to allow that sort of thing, but it requires at least C++11, and there are limitations on what you can put in such a function (that were relaxed in C++14).

There's also const fn in rust, which might allow a similar optimization.
C++ has so much old baggage though, while D2 had ideas built into it from the start. Only problem is D isn't quite as popular to use just yet. Though some talks have real world applications where D is used.

Reminds me, gotta finish my FixedInt types (mostly add asm code using special instructions usually reserved for crypto).
avatar
rtcvb32: C++ has so much old baggage though, while D2 had ideas built into it from the start. Only problem is D isn't quite as popular to use just yet. Though some talks have real world applications where D is used.
Is D useful for embedded programming?

In particular, for embedded, here are the sort of features that are important:
* Not needing a garbage collector, and not need a substantial runtime (garbage collectors are terrible for real-time, and apparently also need a lot of extra RAM to be efficient, which we may not have)
* Be able to run without the standard library (there may not be one available, and there may not be enough space for one); this includes not having the usual start files
* Be able to call routines written in assembly language, or allow for inline assembly (this may be occasionally necessary to access features of the hardware that are not exposed by a higher level language, like I/O ports on x86, or the SPM instruction on the AVR)
* Be able to read and write to arbitrary memory locations (this may be used to access hardware registers that are mapped into the address space, or for DMA if the system supports it) (In C, this can be done easily by casting an integer to a pointer)

So, how does D fare in this respect?