How to concatenate static strings at compile time?

I recently revisited this problem, and found that the previous answer I gave produced ridiculously long compile times when concatenating more than a handful of strings.

I have produced a new solution which leverages constexpr functions to remove the recursive templates responsible for the long compilation time.

#include <array>
#include <iostream>
#include <string_view>

template <std::string_view const&... Strs>
struct join
{
    // Join all strings into a single std::array of chars
    static constexpr auto impl() noexcept
    {
        constexpr std::size_t len = (Strs.size() + ... + 0);
        std::array<char, len + 1> arr{};
        auto append = [i = 0, &arr](auto const& s) mutable {
            for (auto c : s) arr[i++] = c;
        };
        (append(Strs), ...);
        arr[len] = 0;
        return arr;
    }
    // Give the joined string static storage
    static constexpr auto arr = impl();
    // View as a std::string_view
    static constexpr std::string_view value {arr.data(), arr.size() - 1};
};
// Helper to get the value out
template <std::string_view const&... Strs>
static constexpr auto join_v = join<Strs...>::value;

// Hello world example
static constexpr std::string_view hello = "hello";
static constexpr std::string_view space = " ";
static constexpr std::string_view world = "world";
static constexpr std::string_view bang = "!";
// Join them all together
static constexpr auto joined = join_v<hello, space, world, bang>;

int main()
{
    std::cout << joined << '\n';
}

This gives much quicker compile times, even with a large quantity of strings to concatenate.

I personally find this solution easier to follow as the constexpr impl function is akin to how this could be solved at runtime.

Edited with improvements thanks to @Jarod42

Leave a Comment

tech