Is it possible to set the value of elements in a constexpr array after a declaration?

Is it possible to declare an array const (perhaps constexpr

) at one point, then define it elsewhere, one element at a time?

eg.

extern constexpr int myArray[100];


myArray[0] = myConstexprFunction(0);
myArray[1] = myConstexprFunction(1);
// ...
myArray[100] = myConstexprFunction(100);

      

What I'm trying to do would need something like this. Perhaps this is possible with things like: http://b.atch.se/posts/constexpr-counter/

But if this method is illegal in the next C ++ standard (hopefully not), I would like to use a safer one.

[EDIT] how about relaxing some of the requirements .. let's say I want to do something like this:

constexpr int myConstExprFunction(int arg) { return arg + 100;}
// other code...
constexpr int a = myConstExprFunctionBegin(10);
constexpr int b = myConstExprFunction(20);
constexpr int c = myConstExprFunction(30);
constexpr int d = myConstExprFunctionEnd(40);

      

what I would like to have is that myConstExprFunctionEnd can generate a final array with the values ​​created by the previous functions. At compile time, of course.

[EDIT2] C ++ 11 solutions are very welcome

+3


source to share


5 answers


Looking at your changes, I simply say no, because the compiler cannot convert a group of variables to an array. It just doesn't work that way. There is no construct in C ++ that could take a bunch of declarations, remove them, and replace them with another declaration. A preprocessor or source code generator can resolve the syntax you are looking for.

If you're interested in a solution that doesn't require external tools, you can create a function constexpr

that returns an array:

constexpr auto makeMyArray() {
    std::array<int, 100> myArray;

    myArray[0] = myConstExprFunction(10);
    myArray[1] = myConstExprFunction(20);
    // ...

    return myArray;
}

      



Then, initialize your array:

constexpr auto myArray = makeMyArray();

      

+2


source


constexpr

declares that the value of a function or variable can be evaluated at compile time .

So the only way to use it with an array is:

constexpr int myArray[100]{1 , 2 , 3 ,.........};

      



such as the

myArray[0] = myConstexprFunction(0);

      

can only be evaluated at runtime. So this is not possible.

+4


source


The constexpr

recent C ++ requirement is very relaxed, so you can simply write:

// requires C++17:
constexpr auto myArray = [] {
    std::array<int, 100> result {};
    for (size_t i = 0; i < 100; ++ i) {
        result[i] = i * i;
    }
    return result;
}();

      

Note. I used std::array<int, 100>

instead int[100]

because the function cannot return a C array.

The above code requires C ++ 17 for two reasons:

Problem 1 can be easily handled with a separate constexpr function. Problem 2 can only be solved by defining your own wrapper around the array.

// requires C++14:

template <typename T, size_t n>
struct ConstexprArray {
    T data[n];
    constexpr ConstexprArray() : data{} {}
    constexpr T& operator[](size_t i) { return data[i]; }
};

constexpr auto initialize_my_array() -> ConstexprArray<int, 100> {
    ConstexprArray<int, 100> result {};
    for (size_t i = 0; i < 100; ++ i) {
        result[i] = i * i;
    }
    return result;
}

constexpr auto myArray = initialize_my_array();

      

+4


source


If you want to declare an array constexpr

and initialize it to a value using a function constexpr

... the best I can think of is to wrap the array in a struct / array and initialize it with a delegate constructor.

Below is a complete working C ++ 14 example

#include <utility>
#include <iostream>

constexpr int myConstexprFunction (int i)
 { return i << 1; } // return 2*i

template <std::size_t S>
struct wrapArray
 {
   int const myWrappedArray[S];

   template <int ... Is>
   constexpr wrapArray (std::integer_sequence<int, Is...> const &)
      : myWrappedArray { myConstexprFunction(Is)... }
    { }

   constexpr wrapArray ()
      : wrapArray(std::make_integer_sequence<int, S>())
    { }
 };


int main ()
 {
   constexpr wrapArray<100>  wa100;

   for ( auto i : wa100.myWrappedArray )
      std::cout << i << ", ";

   std::cout << std::endl;
 }

      

If you want C ++ 11 code, you must implement replacements for std::integer_sequence

and for std::make_integer_sequence()

. This is not difficult.

+3


source


+1


source







All Articles