admin管理员组

文章数量:1124691

I want to create a collection of ASCII characters, at compile time, containing the alphabet.
Something like this works fine:

consteval std::string_view get_alphabet()
{
    std::string_view sv = "ABCDE ... XYZ";

    return sv;
}

However, to avoid typos, I would like to use iota to create the collection.
Is there a way I can populate some character collection, at compile time, and wrap it in a std::string_view ?

This is the idea, but it only works at runtime.

std::string_view get_alphabet()
{
    static std::string s(26, 0);

    std::iota(s.begin(), s.end(), 'A');

    return s;
}

I want to create a collection of ASCII characters, at compile time, containing the alphabet.
Something like this works fine:

consteval std::string_view get_alphabet()
{
    std::string_view sv = "ABCDE ... XYZ";

    return sv;
}

However, to avoid typos, I would like to use iota to create the collection.
Is there a way I can populate some character collection, at compile time, and wrap it in a std::string_view ?

This is the idea, but it only works at runtime.

std::string_view get_alphabet()
{
    static std::string s(26, 0);

    std::iota(s.begin(), s.end(), 'A');

    return s;
}
Share Improve this question asked 2 days ago TootsieTootsie 7753 silver badges12 bronze badges 4
  • 3 Using std::integer_sequence<...> it should be possible to create a sequence of integers corresponding to the ASCII encoded letters. It's not an array though, but perhaps it can be used to initialize one? – Some programmer dude Commented 2 days ago
  • 6 I'd suggest it would probably take less effort to type a string literal "ABCDEFGHIJKLMNOPQRSTUVWXYZ" and check/verify its correctness before using/reusing it than alternatives (e.g. use of library functions, data structures, loops, etc). – Peter Commented 2 days ago
  • 2 Range 'A'-'Z' is not guaranteed to be contiguous in C++ BTW (With EBCDIC as counter example). – Jarod42 Commented 2 days ago
  • 1 @Jarod42 • ASCII was specified as a given. That being the case, ought to be okay. – Eljay Commented 2 days ago
Add a comment  | 

3 Answers 3

Reset to default 5

You can define a const array holding the alphabet like this:

#include <array>

constexpr auto get_alphabet()
{
    return []<std::size_t...Is>(std::index_sequence<Is...>){
        return std::array<char,26>{{ 'A'+ Is... }};
    }(std::make_index_sequence<26>());
}

static_assert (get_alphabet() == std::array<char,26> { 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z' });

int main()
{
}

DEMO

Note that I made no typo while writing the static_assert ;)

update

As Konrad Rudolph pinpointed, one can also go directly for a std::string_view (requires c++23 though while the snippet above requires c++20 only)

#include <array>
#include <string_view>

constexpr auto get_alphabet ()
{
    static constexpr std::array<char,26> arr =  []<std::size_t...Is>(std::index_sequence<Is...>){
        return std::array<char,26>{{ 'A'+ Is... }};
    } (std::make_index_sequence<26>());
    
    return std::string_view (arr.begin(),arr.end()); 
}

static_assert (get_alphabet().size() == 26);
static_assert (get_alphabet() == std::string_view { "ABCDEFGHIJKLMNOPQRSTUVWXYZ" });

int main() {}

With C++20/23 this is less complex:

template<auto start, auto stop>
consteval auto make_iota()
{
    std::array<decltype(start), size_t{stop} - size_t{start} + 1> result;
    std::iota(result.begin(), result.end(), start);
    return result;
}

https://godbolt.org/z/8Kh4ocMcn
https://godbolt.org/z/Txaqj3KaK

edrezen's answer inspired me to look at the lambda approach...
I believe it can be slightly simplified by using std::iota:

consteval auto get_alphabet()
{
    static constexpr std::array<char, 26> arr = []()
    {
        auto tmp = std::array<char,26>{};
        std::iota(tmp.begin(),  tmp.end(), 'A');
        return tmp;
    }();

    return std::string_view {arr.begin(), arr.end()};
}

This requires C++23

本文标签: cCreate alphabet string at compile timeStack Overflow