如何在编译时使用string_views序列创建constexpr数组? [英] How to create a constexpr array with a sequence of string_views at compile time?

查看:78
本文介绍了如何在编译时使用string_views序列创建constexpr数组?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想创建一个 constexpr std :: array< std :: string_view,ConstexprNumber> .例如,它应包含 constexpr std :: strings_view的,如下所示:

I would like to create a constexpr std::array<std::string_view, ConstexprNumber>. It should for example contain constexpr std::strings_view's like this:

文本0",文本1",文本2",.....文本"

"text0", "text1", "text2", ..... "textn"

我想出了以下初步解决方案:

I came up with the following initial solution:

#include <iostream>
#include <array>
#include <utility>
#include <string>
#include <string_view>

// Number of strings that we want to generate
constexpr size_t NumberOfTextsToGenerate = 10u;

// constexpr function to build a string
constexpr std::string_view makeString(unsigned int i) {
    return std::string_view("text");
}

// Helper: constexpr function that will create an array of string_views and initialize it
template <unsigned int... ManyIntegers>
constexpr auto generateTextHelper(std::integer_sequence<unsigned int, ManyIntegers...>) {
    return std::array<std::string_view, sizeof...(ManyIntegers)>{ {makeString(ManyIntegers)...}};
}

// Helper: constexpr function that will return an array of string_views as shown above with a specified number of texts
constexpr auto generateTextArray() {
    return generateTextHelper(std::make_integer_sequence<unsigned int, NumberOfTextsToGenerate>());
}

// This is a definition of a std::array<std::string_view,UpperBound> initialized with some text
constexpr auto text = generateTextArray();

int main() {
    for (size_t i{}; i < NumberOfTextsToGenerate; ++i)
        std::cout << text[i] << '\n';
    return 0;
}

但是,当然,"makeString"功能不能满足我的要求.或者,更好的说,我不知道如何实施正确的解决方案.

But, of course the "makeString" function does not do what I want. Or, better said, I do not know how to implement the correct solution.

我们如何使这样的数组起作用?是基于此初始解决方案还是类似的方案?

推荐答案

我现在找到了最终满足我需求的解决方案.

I now found a solution that finally satisfies my needs.

由于SO用户提供了许多很好的答案,以及我的问题的其他答案

Because of many good answers by SO users and additional answers to my question here,

我现在将使用以下代码.

I will now use the following code.

#include <iostream>
#include <algorithm>
#include <iterator>
#include <array>
#include <string>

// Specification for the output that we want to generate
constexpr const char BaseString[]{ "text" };    // Some example text
constexpr size_t StartIndex = 1u;               // Start index. So first array element will be "Text1"
constexpr size_t NumberOfElements = 20u;        // Number of elements to create. Last array element will be "Text20"

// These templates are used to generate a std::array
namespace ConstexprGenerator {
    // To create something like "text123" as constexpr
    template <const size_t numberToConvert, const char* Text>
    class Converter {
    public:
        // Some helper variables for calculating sizes
        static constexpr size_t TextLength{ std::char_traits<char>::length(Text) };
        static constexpr size_t NumberOfDigits{ ([]() constexpr noexcept {size_t result = 0; int temp = numberToConvert; for (; temp != 0; temp /= 10) ++result; return result; }()) };
        static constexpr size_t ArrayLength{ (numberToConvert ? 1u : 2u) + NumberOfDigits + TextLength };

        // Here we will store the string
        std::array<char, ArrayLength> internalString{};

        // Constructor: Copy text and Convert number to character digits
        constexpr Converter() noexcept {
            size_t i{ 0 };  for (; i < TextLength; ++i) internalString[i] = Text[i]; // Copy text
            if (numberToConvert == 0) internalString[i] = '0';  // In case that the given number is 0, then simply copy '0' character   
            else {
                i = NumberOfDigits + TextLength - 1;            // Convert number to character digits
                int number = numberToConvert; for (; number; number /= 10)
                    internalString[i--] = number % 10 + '0';
            }
        }
        constexpr std::array<char, ArrayLength> get() const { return *this; };              // getter
        constexpr operator std::array<char, ArrayLength>() const { return internalString; } // type cast
    };

    // Templated variable. Will have always a different type, depending on the template parameters
    template<const size_t numberToConvert, const char* Text>
    constexpr auto Converted = Converter<numberToConvert, Text>{}.get();

    // Generate a std::array with n elements that consist of const char *, pointing to Textx...Texty
    template <int... ManyIntegers>
    constexpr auto generateTextHelper(std::integer_sequence<size_t, ManyIntegers...>) noexcept {
        return std::array<const char*, sizeof...(ManyIntegers)>{ {Converted<ManyIntegers + StartIndex, BaseString>.data()...}};
    }
    // Generate the required number of texts
    constexpr auto generateTextArray()noexcept {
        return generateTextHelper(std::make_integer_sequence<size_t, NumberOfElements>());
    }
}
// This is a constexpr array
constexpr auto text = ConstexprGenerator::generateTextArray();

int main() {
    std::copy(text.begin(), text.end(), std::ostream_iterator<const char*>(std::cout, "\n"));
    return 0;
}

经过MSVC,Clang和gcc的测试

Tested with MSVC, Clang and gcc

这篇关于如何在编译时使用string_views序列创建constexpr数组?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆