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
source to share
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();
source to share
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.
source to share
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:
-
constexpr
lambda - modified
operator[]
notconstexpr
until C ++ 17
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();
source to share
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.
source to share