Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create a constexpr array with a sequence of string_views at compile time?

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:

"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;
}

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.

How can we get such an array to work? Either based on this initial solution or something similar?

like image 739
Armin Montigny Avatar asked Jan 11 '21 09:01

Armin Montigny


People also ask

When does a constexpr function produce a compile-time constant?

When its arguments are constexpr values, a constexpr function produces a compile-time constant. When called with non- constexpr arguments, or when its value isn't required at compile time, it produces a value at run time like a regular function.

When does a non-constexpr function produce a value at compile time?

When called with non- constexpr arguments, or when its value isn't required at compile time, it produces a value at run time like a regular function. (This dual behavior saves you from having to write constexpr and non- constexpr versions of the same function.) A constexpr function or constructor is implicitly inline.

What is constexpr function in C++?

constexpr functions. A constexpr function is one whose return value can be computed at compile time when consuming code requires it. Consuming code requires the return value at compile time, for example, to initialize a constexpr variable or provide a non-type template argument.

What is not initialized in constexpr?

Not initialized int j = 0; constexpr int k = j + 1; //Error! j not a constant expression A constexpr function is one whose return value is computable at compile time when consuming code requires it. Consuming code requires the return value at compile time to initialize a constexpr variable, or to provide a non-type template argument.


1 Answers

UPDATE: Another solution through STL.

The below solution is through boost's preprocessing macros.


Well, it took me three hours, but I still couldn't do it successfully through STL, so I gave up and eventually I went back to the macro.

If you don't want to import the whole boost library, you can just separate out these BOOST_PP macros into your project, although they are still very large, so it might take a bit of your time.

Here is the code (link to godbolt):

#include <iostream>
#include <string_view>
#include <experimental/array>

#include <boost/preprocessor/punctuation/comma_if.hpp>
#include <boost/preprocessor/repetition/repeat.hpp>


int main()
{
    constexpr auto strs_array = std::experimental::make_array<std::string_view>
    (
#define ADD_STRING(z, index, data)    BOOST_PP_COMMA_IF(index) data # index
        BOOST_PP_REPEAT(20, ADD_STRING, "test")
#undef ADD_STRING
    );

    for (const std::string_view &str : strs_array) {
        std::cout << str << '\n';
    }
}

The maximum number allowed to be generated is BOOST_PP_LIMIT_REPEAT (currently is 256), which means you can currently generate up to "test255", I guess that's enough.

Output:

Program returned: 0
Program stdout
test0
test1
test2
test3
test4
test5
test6
test7
test8
test9
test10
test11
test12
test13
test14
test15
test16
test17
test18
test19
like image 186
Sprite Avatar answered Oct 21 '22 15:10

Sprite