Use template
s and generic programming wherever possible. Don't rely on any types if you don't have to!
If you have a function that takes a number and returns it multiplied by 2, write it like this:
template <typename Number>
inline Number doubleNum(Number n) {
return 2*n;
}
Or even this:
template <typename RetType, typename NumberType>
inline RetType doubleNum(NumberType n) {
return 2*n;
}
This way, if you have a library that uses int
s, double
s, uint64_t
s - you name it - you can work with it, without rewriting your code. If you need to work with binary files or network programming, you can work with fixed-size types, without rewriting your code. And if you need arbitrary precision numbers, you can work with a class which implements the same interface as a primitive integer or float type via operator overloading, such as a GMP wrapper, without rewriting your code.
And you can specialize templated functions or classes, to optimize specific cases or work with classes (or C struct
s) that don't conform to the relevant interface:
/*
* optimization:
* primitive integers can be bit-shifted left to
* achieve multiplication by powers of 2
* (note that any decent compiler will do this
* for you, behind the hood.)
*/
template <>
inline int doubleNum<int>(int n) {
return n<<1;
}
/*
* optimization:
* use assembly code
*/
template <>
inline int32_t doubleNum<int32_t>(int32_t n) {
asm {
...
}
}
/*
* work with awkward number class
*/
template <>
inline AwkwardNumber doubleNum<AwkwardNumber>(AwkwardNumber n) {
n.multiplyBy(2);
return n;
}
uint32_t
and friends are POD; they aretypedef
's inherited from C99. – Belongingint, unsigned int, char
, etc. – Flewsuint32_t
and friends are also "primitive" types. We probably need a term like "classic" or "K&R" to describe the historically available types. – Ludhianaunsigned
anduint32_t
in terms of classification; I only meant to criticize incorrect usage of 'POD'. – Excerptalong long
fall into? ;-P – Excerptanullptr_t
– Ludhianatypedef decltype(nullptr) nullptr_t;
. – Excerpta