"Fred Zwarts" <F.Zwa...@KVI.nl> wrote:
> Francesco S. Carta wrote:
> > "Fred Zwarts" <F.Zwa...@KVI.nl> wrote:
> >> I have created a template function for a generic algorithm.
> >> For unsigned integer types, a small modification in the algorithm is
> >> needed,
> >> because I can't use negative values there.
> >> So, I want to make specializations for all unsigned integer types.
> >> I assume that it is not possible in C++ to write one specialization
> >> for all
> >> unsigned integer type, but that a specialization for each unsigned
> >> integer type
> >> must be created.
> >> Since this software runs on different platforms, I wonder whether it
> >> is
> >> possible to write a complete set of specializations in a platform
> >> independent way.
>
> >> I first tried to write specializations for uint8_t, uint16_t,
> >> uint32_t and uint64_t
> >> as defined in inttypes.h, but it turns out that on some platforms
> >> some
> >> unsigned integer types are still missing. (Under Windows e.g.,
> >> there is more than one 32-bit unsigned integer type.)
> >> Types like size_t and clock_t map to different types on different
> >> platforms.
> >> I wonder whether it is possible to create a complete list,
> >> without using conditional code selection in the preprocessor.
> >> Is the list "unsigned char, unsigned short, unsigned int, unsigned
> >> long and unsigned long long" complete and without overlap (as far as
> >> specializations concern) for all platforms?
> >> Should I add unsigned wchar_t, or is it covered already?
>
> >> (I know that char needs special attention. I know how to handle that
> >> case.)
>
> > Your list seems exhaustive, and "unsigned wchar_t" should be already
> > covered by your list (after all, it should be just an unsigned integer
> > somewhat bigger than char). But you'll eventually get more certain
> > answers about this.
>
> > About avoiding to create all those specializations, can you get along
> > with duplicating the body of your template to include both algorithms,
> > checking then for unsigned-ness at runtime via numeric_limits?
>
> > The compiler could then optimize away the algorithm version that
> > doesn't happen to be appropriate for each type - at least, I suppose
> > so, I'd have to check if it works but I'm not so sure I will able to.
>
> > Just an idea off the top of my head.
>
> Thanks for the suggestion. I tried something along these lines.
> It compiles and works as expected, but some compilers generate a lot
> of warnings for those lines where tests are made for the sign of the
> values during instantiations of unsigned types. Since this header is
> included in may modules, I get many warnings which I cannot suppress
> and which makes it difficult to find the more relevant warnings.
I didn't think about those warnings.
Just in case: once you're assured that unsigned types will never make
it in your signed algo, couldn't you throw away those tests for
negativeness in the signed algo? Or perhaps change them so that they
don't raise warnings, if they're really needed.
For example, a check for some value being not negative can be
expressed as:
-------
if(val > -1) { /*...*/ };
-------
But also as either:
-------
if(val >= 0) { /* ... */ };
if(!(val < 0)) { /* ... */ };
-------
The latter two shouldn't raise any warning even if applied to unsigned
types, mmm, no, the compiler will eventually warn that those tests
always evaluate "true"...
Maybe the only way to avoid those warnings and taking advantage of the
templates is wrapping those algos within template classes, but as you
have already noted with Kai-Uwe, this is going to increase complexity
- and notation, too, I suspect.
Wait: what about this:
-------
if(val == 0 || val > 0) { /* ... */ };
-------
The above should issue no warning at all! Am I correct?
Compilers cannot be _that_ clever, can they?
Ahh. If you happen to find a compiler that warns on the above, try
this:
-------
T zero = 0; /* note: non-const... could a "volatile" help too, here?
*/
if(val >= zero) { /* ... */ };
-------
Anyway, gcc 3.4.5 never warned me for "always true/false" conditionals
- with "-Wall -pedantic" would them have been needed.
To avoid the weird part of my suggestion (duplicating the code in the
template body) one could make two different templates and wrap the
decision in a third one:
-------
#include <limits>
template<class T> void signed_algo(const T& one, const T& two) {
// ...
}
template<class T> void unsigned_algo(const T& one, const T& two) {
// ...
}
template<class T> void algo(const T& one, const T& two) {
if(std::numeric_limits<T>::is_signed) {
signed_algo(one, two);
} else {
unsigned_algo(one, two);
}
}
-------
Well, you surely have considered all of this already, I'm posting it
just for the occasional reader.
--
Francesco S. Carta,
http://fscode.altervista.org