9

Is it possible to write a construct that turns any C string literal "XY..." into a type std::integer_sequence<char, 'X', 'Y', ...> at compile time? I really want a character pack, not a std::array.

Something like

using MyStringType = magic_const_expr("MyString");

A nice approach using the literal operator was demonstrated here but unfortunately it requires a non-standard compiler extension.

Richard W
  • 631
  • 4
  • 15
  • Would you be okay using the syntax `using MyStringType = decltype(MyString_some_ud_suffix);` – NathanOliver Feb 02 '22 at 21:53
  • Another option is to use something like [this](https://stackoverflow.com/questions/37029886/how-to-construct-a-tuple-from-an-array) to convert the array to a tuple and then you can use the tuple to build an `integer_sequence` – NathanOliver Feb 02 '22 at 21:58
  • The accepted answer to the question you linked contains a link [here](https://stackoverflow.com/questions/15858141/conveniently-declaring-compile-time-strings-in-c) which seems to have some solutions, such as [this one](https://stackoverflow.com/a/15863804/189205) (it predates `std::integer_sequence` but the idea is the same). – interjay Feb 02 '22 at 21:58
  • @interjay, that solution you linked relies on storing the literal as a global constant and feeding the address into a class template. I am looking for a solution that keeps the literal on the stack and compiles it eventually away. – Richard W Feb 02 '22 at 22:14
  • @NathanOliver you mean `using MyStringType = decltype("MyString"_some_ud_suffix)` (note the ")? That would be fine as long it works with plain C++17 without extensions. – Richard W Feb 02 '22 at 22:17
  • @RichardW The C++ language does not support `"MyString"_some_ud_suffix` You would have to do it without the `"` like `MyString_some_ud_suffix`. – NathanOliver Feb 02 '22 at 22:39
  • I started hacking around a bit and came up with [this](https://godbolt.org/z/bMGqGrzro). You need to declare a variable with this though to get the integer sequence type, so it's not as nice, but could be useful. – IlCapitano Feb 02 '22 at 23:31

1 Answers1

3

Something like this might do it:

template <size_t N, typename F, size_t... indexes>
constexpr auto make_seq_helper(F f, std::index_sequence<indexes...> is) {
    return std::integer_sequence<char, (f()[indexes])...>{};
}

template <typename F>
constexpr auto make_seq(F f) {
    constexpr size_t N = f().size();
    using indexes = std::make_index_sequence<N>;
    return make_seq_helper<N>(f, indexes{});
};


template<const char* str>
struct IntegerSequenceFromString {
    
    private:
    constexpr static auto value = make_seq([](){return std::string_view{str}; });
    
    public:
    using type = decltype(value);
};

Usage would then be:

 constexpr static const char str[] = "lala";
 IntegerSequenceFromString<str>::type i{};

Here is a live example of it working.

I am sure, there is a way to reduce some of this extra stuff as well, but from the assembly, it looks like we don't generate any real runtime variables: https://godbolt.org/z/f65cjGfzn

Fantastic Mr Fox
  • 32,495
  • 27
  • 95
  • 175