I have some function which computes an operation on numbers:
int32_t compute(int32_t x) {
// just a placeholder; the details don't matter
return ~x;
}
The full function is kind of big, and pulls in other big number functions too. I want to save every byte because it's for an 8-bit microcontroller with a tiny ROM.
In general I want to support at least 32-bit inputs, so I used int32_t, but in most builds, it won't be called with more than a 16-bit or even 8-bit input, so hard-coding the type to always be so large is usually a waste.
I could use a template type:
template <typename T>
T compute(T x) {
return ~x;
}
Now if it's only used with, for example, 8-bit types, all the 32-bit stuff disappears.
But when this is called with multiple types in a particular build, it makes things much worse because now there are multiple copies of the function. I don't need separate specializations for int32_t, int16_t, int8_t, when the int32_t version can satisfy all uses. (I'm not worried about speed, only size.)
So I want only one version of the function, but using a type that can satisfy all uses in the application.
Is there any template, macro, compiler extension, linker magic, etc., that can solve this?
Update: If I restrict the problem to a single translation unit, does that open up any new approaches?
CodePudding user response:
There isn’t, at least as flexible as you’ve asked for. The problem is, the widest type in use globally won’t be known until link time… but at that point it’s too late to do anything clever with weak symbols, because the compiled calling code is already expecting to call with a particular integer type. Put differently, the target width needs to be known in each translation unit, but may be affected by other translation units.
Have a configurable macro or typedef to determine the width in use, and turn in compiler warnings for narrowing integers to catch situations where it’s been set incorrectly.
CodePudding user response:
Managing the size of a type across a build is a compile-time issue. Set yourself a #define to fix it.
I do not recommend you redefine any existing integer type. Create your own integer type, and declare that at compile time.
For example:
integer compute(integer t) {
...
}
And in the compile command:
-Dinteger=int32_t
or:
-Dinteger=int16_t
etc.
The -D command-line flag is equivalent to a #define integer int32_t, etc somewhere in your code. If you are using a build system of some sort, set it up so that integer (or whatever you call your number type) is required to be defined in the build flags.
