Use templates 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 ints, doubles, uint64_ts - 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 structs) 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;
}