C++ convert integer to string at compile time

boost, boost-mpl, c++, string, templates

Solution

This can be done using C++14 without any external dependencies. The key addition to the standard is the ability to have non-trivial `constexpr` constructors, allowing the functionality to be contained within a simple class.

Given an integer template parameter, the constructor can carry out the integer-to-string conversion. This is stored in a member character buffer whose size is determined by an additional `constexpr` function. Then, a user-defined conversion provides access to the buffer:

#include <cstdint>

template<std::intmax_t N>
class to_string_t {

    constexpr static auto buflen() noexcept {
        unsigned int len = N > 0 ? 1 : 2;
        for (auto n = N; n; len++, n /= 10);
        return len;
    }

    char buf[buflen()] = {};

public:
    constexpr to_string_t() noexcept {
        auto ptr = buf + buflen();
        *--ptr = '\0';

        if (N != 0) {
            for (auto n = N; n; n /= 10)
                *--ptr = "0123456789"[(N < 0 ? -1 : 1) * (n % 10)];
            if (N < 0)
                *--ptr = '-';
        } else {
            buf[0] = '0';
        }
    }

    constexpr operator const char *() const { return buf; }
};

Finally, a variable template (another C++14 addition) simplifies the syntax:

template<std::intmax_t N>
constexpr to_string_t<N> to_string;

puts(to_string<62017>); // prints "62017"

The functionality can be extended to support other bases (e.g. hexadecimal), wide character types, and the common container interface; I've packed this all into a single header and put it on GitHub at tcsullivan/constexpr-to-string.

With C++20, this can also be extended to support floating-point numbers. A container type is needed for the floating-point literal, which previously could not be a template parameter. See the `f_to_string.hpp` header in the GitHub repo for the implementation.

Problem

I want to do something like this: ``` template<int N> char* foo() { // return a compile-time string containing N, equivalent to doing // ostringstream ostr; // ostr << N; // return ostr.str().c_str(); } ``` It seems like the boost MPL library might allow this but I couldn't really figure out how to use it to accomplish this. Is this possible?

Original source

Related problems