I have come across this particular snippet of code many times in solutions of competitive programming contests. I understand the basic use of this code to beat time limits b
In the PrintUint
function, he's basically just unrolling a loop by hand. Unrolling loops are sometimes a good thing to do -- however the compiler already does it, and will do it better than you, most of the time.
To plug my favorite language feature, it would be better implemented using templates: a simple implementation (more clever probably exist) would look like:
// I'm sure the compiler can figure out the inline part, but I'll add it anyways
template
inline void print_uint_inner(uint32_t v) {
m_data[m_dataOffset + N] = v - v / 10 * 10 + 48;
print_uint_inner(v / 10);
}
// For situations just like this, there's a trick to avoid having to define the base case separately.
inline void print_uint_inner<0>(uint32_t v) {
m_data[m_dataOffset] = v - v / 10 * 10 + 48;
}
template
inline void print_uint_helper(uint32_t v) {
print_uint_inner(v);
m_dataOffset += N;
}
// We could generate the compile-time binary search with templates too, rather than by hand.
void PrintUint(uint32_t v, char d) {
if (m_dataOffset + 11 > sizeof(m_data)) Flush();
if (v < 100000) {
if (v < 1000) {
if (v < 10) {
print_uint_helper<1>(v);
} else if (v < 100) {
print_uint_helper<2>(v);
} else {
print_uint_helper<3>(v);
}
} else {
if (v < 10000) {
print_uint_helper<4>(v);
} else {
print_uint_helper<5>(v);
}
}
} else {
if (v < 100000000) {
if (v < 1000000) {
print_uint_helper<6>(v);
} else if (v < 10000000) {
print_uint_helper<7>(v);
} else {
print_uint_helper<8>(v);
}
} else {
if (v < 1000000000) {
print_uint_helper<9>(v);
} else {
print_uint_helper<10>(v);
}
}
}
m_data[m_dataOffset++] = d;
}
Is doing things like this good coding practice in general? Yes, but only if all of the following criteria are satisfied:
Also, you should probably retain the ability to switch back to the simple version, either using compile-time constants or pre-processor directives. This will be important for two reasons: