S
Simon G Best
Hello!
The C++ standard library provides facilities for finding out the sizes
(and other such stuff) of numeric types :std::numeric_limits<>, for
example).
What I would like to do is to select a type on the basis of its traits.
More specifically, I would like to select an unsigned integer type on
the basis of the number of bits I need it to have. (This is because
there are particularly efficient ways of implementing the Advanced
Encryption Standard (AES) block ciphers using 32 bit words.)
I *could* do some template metaprogramming to find a suitable type - but
I'd rather not. It seems rather klunky, and is the sort of thing that
makes me think, 'There must be a better way!'
I *could*, I suppose, use the macros in the relevant headers inherited
from C - but, again, I'd rather not. Macros feel kludgy for this sort
of thing, and I much prefer doing things within the language itself.
So, what I was wondering is if there is a good, general way of selecting
types on the basis of desired traits, and, if so, what that general way
is. (I won't be surprised if it involves a little bit of template
metaprogramming, but I'd prefer it to be as little as possible.)
Or, if there isn't a good, general way for doing that, if there's a good
way of doing the more specific thing of selecting an integer type on the
basis of the desired size.
At the moment, the best idea I've got (for the more specific thing I
want to do) is to combine templates with constant expressions, something
like this:-
#include <limits>
namespace {
template< class T >
Y f_implementation( X x ) {
/* f implemented in terms of T. */
}
class last_resort;
/* A class that implements 32 bit unsigned integers
if none of the built in types are 32 bits.
*/
};
Y f( X x ) {
if( ::std::numeric_limits<unsigned int>::digits == 32 )
return f_implementation<unsigned int>(x);
if( ::std::numeric_limits<unsigned int>::digits > 32 ) {
if( ::std::numeric_limits<unsigned short>::digits == 32 )
return f_implementation<unsigned short>(x);
if( ::std::numeric_limits<unsigned char>::digits == 32 )
return f_implementation<unsigned char>(x);
}
if( ::std::numeric_limits<unsigned long>::digits == 32 )
return f_implementation<unsigned long>(x);
return f_implementation<last_resort>(x);
}
That's obviously not a truly generic way of doing it, as it explicitly
goes through some explicit possibilities. A truly generic way would be
a lot nicer! (But I suspect there isn't one, as two different types
might have an identical trait.)
Any thoughts?
Simon
The C++ standard library provides facilities for finding out the sizes
(and other such stuff) of numeric types :std::numeric_limits<>, for
example).
What I would like to do is to select a type on the basis of its traits.
More specifically, I would like to select an unsigned integer type on
the basis of the number of bits I need it to have. (This is because
there are particularly efficient ways of implementing the Advanced
Encryption Standard (AES) block ciphers using 32 bit words.)
I *could* do some template metaprogramming to find a suitable type - but
I'd rather not. It seems rather klunky, and is the sort of thing that
makes me think, 'There must be a better way!'
I *could*, I suppose, use the macros in the relevant headers inherited
from C - but, again, I'd rather not. Macros feel kludgy for this sort
of thing, and I much prefer doing things within the language itself.
So, what I was wondering is if there is a good, general way of selecting
types on the basis of desired traits, and, if so, what that general way
is. (I won't be surprised if it involves a little bit of template
metaprogramming, but I'd prefer it to be as little as possible.)
Or, if there isn't a good, general way for doing that, if there's a good
way of doing the more specific thing of selecting an integer type on the
basis of the desired size.
At the moment, the best idea I've got (for the more specific thing I
want to do) is to combine templates with constant expressions, something
like this:-
#include <limits>
namespace {
template< class T >
Y f_implementation( X x ) {
/* f implemented in terms of T. */
}
class last_resort;
/* A class that implements 32 bit unsigned integers
if none of the built in types are 32 bits.
*/
};
Y f( X x ) {
if( ::std::numeric_limits<unsigned int>::digits == 32 )
return f_implementation<unsigned int>(x);
if( ::std::numeric_limits<unsigned int>::digits > 32 ) {
if( ::std::numeric_limits<unsigned short>::digits == 32 )
return f_implementation<unsigned short>(x);
if( ::std::numeric_limits<unsigned char>::digits == 32 )
return f_implementation<unsigned char>(x);
}
if( ::std::numeric_limits<unsigned long>::digits == 32 )
return f_implementation<unsigned long>(x);
return f_implementation<last_resort>(x);
}
That's obviously not a truly generic way of doing it, as it explicitly
goes through some explicit possibilities. A truly generic way would be
a lot nicer! (But I suspect there isn't one, as two different types
might have an identical trait.)
Any thoughts?
Simon