When working with an aggregate class, passing in an initializer list for an array member is not problem. For example:
class color_def
{
public:
const u8 color_passes;
const u8 red_shift[MAX_COLOR_PASSES];
const u8 red_bitcount[MAX_COLOR_PASSES];
const u8 green_shift[MAX_COLOR_PASSES];
const u8 green_bitcount[MAX_COLOR_PASSES];
const u8 blue_shift[MAX_COLOR_PASSES];
const u8 blue_bitcount[MAX_COLOR_PASSES];
};
const static color_def snk_neogeo_color = {
3, {15, 14, 8}, {1, 1, 4}, {15, 13, 4}, {1, 1, 4}, {15, 12, 0}, {1, 1, 4}};
This works without any issue. However, when I add an explicit constructor, it won't work. For example, from a similar class:
class chr_def
{
public:
chr_def(u16 width, u16 height, u8 bitplanes, u32 planeoffset[MAX_GFX_PLANES],
u32 xoffset[MAX_GFX_SIZE], u32 yoffset[MAX_GFX_SIZE],
const u8 *(*converter)(const chr_def *chrdef, const u8 *data))
: width(width),
height(height),
bitplanes(bitplanes),
planeoffset{planeoffset},
xoffset(xoffset),
yoffset(yoffset),
converter(converter),
datasize(width * height * bitplanes){};
const u8 *convert(const u8 *data) { return this->converter(this, data); }
const u16 width; // pixel width of each element
const u16 height; // pixel height of each element
const u8 bitplanes; // number of color bitplanes
const u32 *planeoffset; // bit offset of each bitplane
const u32 *xoffset; // bit offset of each horizontal pixel
const u32 *yoffset; // bit offset of each vertical pixel
const u32 datasize; // size of one chr in bits
const u8 *(*converter)(const chr_def *, const u8 *);
};
const static chr_def nintendo_sfc = {
8,
8,
4,
{0, 8, 128, 136},
{0, 1, 2, 3, 4, 5, 6, 7},
{0 * 16, 1 * 16, 2 * 16, 3 * 16, 4 * 16, 5 * 16, 6 * 16, 7 * 16},
get_chr};
The fails, complaining that the arguments don't match the constructor. The issue seems to be that it is taking the first value of the array init list as the pointer to the array:
note: candidate constructor not viable: cannot convert initializer list argument to 'u32 *' (aka 'unsigned int *')
If I pull the array init lists out and initialize them beforehand into their own variables like so:
u32 temp1[4] = {0, 8, 128, 136};
u32 temp2[8] = {0, 1, 2, 3, 4, 5, 6, 7};
u32 temp3[8] = {0 * 16, 1 * 16, 2 * 16, 3 * 16, 4 * 16, 5 * 16, 6 * 16, 7 * 16};
const static chr_def nintendo_sfc = {
8,
8,
4,
temp1,
temp2,
temp3,
get_chr};
Things work fine. I'd just really prefer not to do it this way if at all possible.
So... why does this work in the aggregate form but not with my explicit constructor? Is there some way to make this work? Appreciate any insight anyone can offer.
The problem you are having is that you are trying to initialize pointer members with std::initializer_list
, which is simply not possible.
You can, however, use std::array
(since c++ 11). Here is a simplified example:
#include <iostream>
#include <array>
#define MAX_GFX_PLANES (4U)
struct chr_def {
// Constructor
chr_def(size_t size, const std::array<unsigned int, MAX_GFX_PLANES>& planeoffset) :
size(size), planeoffset(planeoffset) { };
// Data Members
const size_t size;
const std::array<unsigned int, MAX_GFX_PLANES> planeoffset;
};
const static chr_def nintendo_sfc{ 8U, {0U, 1U, 2U, 3U} };
int main() {
// std::array can be used with range-based for
for (auto i : nintendo_sfc.planeoffset) {
std::cout << i << " ";
}
return 0;
}