Function to represent an integer in a base This function represents an integral type and represents it in a base.

#include &lt;type_traits&gt;
#include &lt;limits&gt;
#include &lt;array&gt;
#include &lt;iterator&gt;

namespace detail {

template &lt;class Integral&gt;
char n_to_digit(Integral n) {
    static const char * digits = "0123456789abcdefghijklmnopqrstuvwxyz";
    return digits[n];
}

/// This implementation is called if Integral is unsigned
template &lt;unsigned Base, class Integral, class OutputIterator&gt;
std::size_t integral_to_base_impl(Integral n, OutputIterator dst_it, std::true_type) {
    /// Length of str is the minimum number of bits to store Integral which is
    /// the number of chars required to store the maximum value of in base 2
    /// representation
    std::array&lt;char, (sizeof(Integral) &lt;&lt; 3)&gt; str;
    auto it = str.begin();

    do {
        *it++ = n_to_digit(n % Base);
        n /= Base;
    } while (n != 0);

    while (it != str.begin()) {
        *dst_it++ = *(--it);
    }

    return std::distance(str.begin(), it);
}

/// This implementation is called if Integral is signed
template &lt;unsigned Base, class Integral, class OutputIterator&gt;
std::size_t integral_to_base_impl(Integral n, OutputIterator dst_it, std::false_type) {
    std::size_t length = 0;

    if (n &lt; 0) {
        *dst_it++ = '-';
        ++length;
    }

    length += integral_to_base_impl&lt;Base&gt;(std::abs(n), dst_it, std::true_type());
    return length;
}

}

/// Represents an integral in a certain base
///
/// @tparam Base The base that the integral will be represented as
///
/// @param n The number that will be represented
/// @param dst_it A char OutputIterator that the representation will be written to
///
/// @return The length of the representation
template &lt;unsigned Base, class Integral, class OutputIterator&gt;
std::size_t integral_to_base(Integral n, OutputIterator dst_it) {
    static_assert(2 &lt;= Base &amp;&amp; Base &lt;= 36, "Base must be &gt;= 2 and &lt;= 36");
    static_assert(std::is_integral&lt;Integral&gt;::value, "n must be an integral type");

    return detail::integral_to_base_impl&lt;Base&gt;(n, dst_it,
        std::integral_constant&lt;bool, std::is_unsigned&lt;Integral&gt;::value&gt;());
}


My implementation is like the C's non standard function itoa however it takes the base is taken as a template parameter which allow the compiler to make optimizations with operations involving the base such as modulo and divide however it must be known at compile time. This allows integrals to represented as binary and hexadecimal with the Base template parameter being 2 and 16 respectively.

The function integral_to_base has implementation specializiations for unsigned and signed integral types and has static assertions to check that the base is valid at compile time for safety.

Example usage:

int main() {
    std::string test;

    integral_to_base&lt;10&gt;(123343, std::back_inserter(test));
    std::cout &lt;&lt; test &lt;&lt; std::endl; //prints 123343
}
n_to_digit doesn't really need to be a template, since its argument n can only ever be in the range 0 to 35. I'd just make it

char n_to_digit(int n) {
    static const char digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
    return digits[n];
}


Notice also the replacement of *digits with digits[]; the optimizer will likely generate the same code either way, but without the optimizer's help, making digits the name of the array itself instead of the name of a pointer to the array will remove one level of pointer dereferencing.



YMMV, but I would find

std::array&lt;char, (sizeof(Integral) &lt;&lt; 3)&gt; str;


easier to read if it were just

char str[sizeof(Integral) * 8];


Of course then you'd have to use std::begin(str) instead of str.begin(). But you could make up for it by using it - str instead of std::distance(str.begin(), it).

Actually, hang on —

while (it != str.begin()) {
    *dst_it++ = *(--it);
}

return std::distance(str.begin(), it);


The loop never exits unless it == str.begin(), which means std::distance(str.begin(), it) == 0 by definition! This is certainly a bug.



Since you're trying to make this fully generic: note that *dst_it++ is going to be inefficient for a lot of iterator types. If you were writing this for a popular library, you'd write

*dst_it = '-';
++dst_it;


If you consistently avoid postfix operators, your users might even thank you, because your code will work even with their incompletely belled-and-whistled iterator types.



In the signed version, your use of std::abs(n) is a red flag. abs is never appropriate in generic code. For one thing, if Integral n is some clever fixed-point type, std::abs(n) won't compile; what you meant is more like

using std::abs;
... abs(n) ...


to pick up the correct abs through ADL. (But this opens the whole customization-point can of worms, which is still a mess even in C++17.)

No, the real reason abs is a red flag is because std::abs(-1 - 2147483647) invokes undefined behavior (source). You should never call abs on untrusted input.

The usual hack in this domain is to say

if (n &lt; 0) {
    *dst_it = '-'; ++dst_it;
} else {
    n = -n;
}


and then print the negative of n.



std::integral_constant&lt;bool, std::is_unsigned&lt;Integral&gt;::value&gt;()


could conceivably be written

typename std::is_unsigned&lt;Integral&gt;::type{}


but honestly, only the most evil and sadistic library implementation in the universe would make is_unsigned not derived from boolean_constant already. So you can just write

std::is_unsigned&lt;Integral&gt;{}


and be assured that your tag-dispatch code will work at least as well as your neighbor's. :)