2

I have this definitions:

typedef uint8_t myType[16];

constexpr myType x0 = {1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6};
constexpr myType x1 = {11,12,13,14,15,16,17,18,19,10,11,12,13,14,15,16};
constexpr myType x2 = {21,22,23,24,25,26,27,28,29,20,21,22,23,24,25,26};

constexpr myType AllX[] = {x0,x1,x2};

compiling this in VS 2015, give me this error:

An internal error has occurred in the compiler. 

The intelisense report this error:

a value of type "const uint8_t *" cannot be used to initialize an entity of type "const uint8_t"

How can I fix this problem?

Deduplicator
  • 44,692
  • 7
  • 66
  • 118
mans
  • 17,104
  • 45
  • 172
  • 321
  • If you absolutely have to have things flattened, there's [this](https://stackoverflow.com/a/25089095/8120642). – hegel5000 May 22 '18 at 15:05

3 Answers3

2

You can use std::array to get around the problem.

#include <array>

using myType = std::array<uint8_t, 16>;

int main()
{
   constexpr myType x0={1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6};
   constexpr myType x1={11,12,13,14,15,16,17,18,19,10,11,12,13,14,15,16};
   constexpr myType x2={21,22,23,24,25,26,27,28,29,20,21,22,23,24,25,26};

   constexpr std::array<myType, 3> AllX = {x0,x1,x2};
}

In a comment, you said,

But I can not use this method as x0 and x1 and x2 and .. is already defined in that way in code and I can not change it.

In that case, your only option is to copy the elements of those objects to AllX. You can use std::copy to streamline that. The only problem is that you can't use constexpr AllX.

   std::array<myType, 3> AllX = {};
   std::copy(begin(x0), end(x0), AllX[0].data());
   std::copy(begin(x1), end(x1), AllX[1].data());
   std::copy(begin(x2), end(x2), AllX[2].data());
R Sahu
  • 204,454
  • 14
  • 159
  • 270
  • `AllX` can then be treated as a single flat C-style array with `AllX.data()`, right? – hegel5000 May 22 '18 at 15:08
  • @hegel5000 That works for a single `std::array` object. I am not sure about a nested `std::array` object. I'll have to try it out to be sure. – R Sahu May 22 '18 at 15:10
0

An array can only be initialized with a brace-enclosed initializer, not with another array. See aggregate initialization for more details.

A fix:

constexpr myType AllX[] = {
    {1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6},
    {11,12,13,14,15,16,17,18,19,10,11,12,13,14,15,16},
    {21,22,23,24,25,26,27,28,29,20,21,22,23,24,25,26}
};

constexpr auto& x0=AllX[0];
constexpr auto& x1=AllX[1];
constexpr auto& x2=AllX[2];
Maxim Egorushkin
  • 131,725
  • 17
  • 180
  • 271
  • Thanks, But I can not use this method as x0 and x1 and x2 and .. is already defined in that way in code and I can not change it. As they are constexpr, they are resolved during compile time. Is there any way that we can extract them for initializing the all array? – mans May 22 '18 at 14:57
0

In C, you can declare AllX[] as an array of pointers to the underlying members. This will lose the compiler knowledge that they are of size 16, but I don't know how important that is to you. And of course you /can/ do that in c++:

constexpr uint8_t *AllX[]={x0,x1,x2};

To demonstrate the loss, you could write it as:

constexpr uint8_t *AllX[]={&x0[0],&x1[0],&x2[0]};

You would index this using 2 sets of [], e.g. AllX[1][5]

Alternatively, you could declare a lightweight object that takes references to a fixed number of myType objects in its constructor, and provides an operator overload to perform the outer indexing. Internally that object might as well have a C-array or std::array of pointers to mytype, and step through that pointer. You could probably extend this to a template function that generates a template class to allow the two arrays to have compile-time determined sizes.

This object could also take ownership of the child arrays, calling some destruction method on the members from its own destruction.

When you are talking about a single flat array, are you saying you want AllX[25 to find X1[9]? If so, you could do that with the lightweight wrapper object operator. It could perform the necessary trivial math on the index to get the outer and inner indices, and return a (const) reference to the relevant member.

Gem Taylor
  • 5,381
  • 1
  • 9
  • 27