GuillaumeDua / CppShelf

Collection of powerfuls - C++ Single-Header Libraries Files
https://guillaumedua.github.io/CppShelf/
MIT License
9 stars 1 forks source link

[?] Compile-time string_view concatenation #211

Open GuillaumeDua opened 4 months ago

GuillaumeDua commented 4 months ago

csl::mp::algorithm::ranges

1 - https://godbolt.org/z/4ndbqMnY9 2 - https://godbolt.org/z/9zeh6Ms5d

Extension: use B10 conversion for std::integral_sequence<T, T...>


#include <type_traits>
#include <concepts>
#include <string_view>
#include <functional>
#include <tuple>
#include <iostream>
#include <utility>
#include <optional>
#include <exception>
#include <span>
#include <iomanip>
#include <unordered_map>
#include <variant>
#include <any>
#include <iterator>
#include <iostream>
#include <tuple>
#include <type_traits>
#include <ranges>
#include <algorithm>

#define fwd(arg) std::forward<decltype(arg)>(arg)

namespace mp {
    template <typename T, T ... values>
    struct sequence{};
}

namespace details {
static constexpr inline auto default_separator = std::string_view{","};
}

template <
    typename T,
    std::string_view const& separator = details::default_separator
>
class join;

template <
    std::string_view const& ... values,
    std::string_view const& separator
>
class join<
    mp::sequence<std::string_view const&, values...>,
    separator
>
{
    static constexpr auto impl() noexcept -> auto // concepts::std_array_of<char>
    {
        constexpr std::size_t separators_length = sizeof...(values) == 0
            ? 0
            : std::size(separator) * (sizeof...(values) - 1)
        ;
        constexpr std::size_t buffer_lenght = (std::size(values) + ... + 0) + separators_length;
        std::array<char, buffer_lenght + 1> buffer{};
        auto append = [i = std::size_t{0}, &buffer](auto const& value) mutable {
            for (auto c : value)
                buffer[i++] = c;
            if (i == buffer_lenght)
                return;
            for (auto c : separator)
                buffer[i++] = c;
        };

        (append(values), ...);
        buffer[buffer_lenght] = 0;
        return buffer;
    }
    static constexpr auto storage = impl();
public:
    static constexpr std::string_view value {storage.data(), storage.size() - 1};
};

template <typename sequence, std::string_view const& separator = details::default_separator>
static constexpr auto join_v = join<sequence, separator>::value;

// ---
template <typename t>
constexpr static inline std::string_view name_v = "T";
template <>
constexpr static inline std::string_view name_v<int> = "int";
template <>
constexpr static inline std::string_view name_v<char> = "char";

template <std::string_view const & join_sequence, typename ... Ts>
static constexpr auto join_names = join_v<
    mp::sequence<std::string_view const &, name_v<Ts>...>,
    join_sequence
>;

auto main() -> int {
    constexpr static auto join_seq = std::string_view{" | "};
    std::cout << join_names<join_seq, int>;
}