Передача списка инициализации члену массива в C ++ - PullRequest
0 голосов
/ 04 октября 2019

При работе с агрегатным классом передача списка инициализатора для члена массива не является проблемой. Например:

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

Это работает без каких-либо проблем. Однако, когда я добавлю явный конструктор, он не будет работать. Например, из аналогичного класса:

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

Сбой, жалуясь, что аргументы не соответствуют конструктору. Кажется, проблема в том, что в качестве указателя на массив берется первое значение списка инициализации массива:

note: candidate constructor not viable: cannot convert initializer list argument to 'u32 *' (aka 'unsigned int *')

Если я извлекаю списки инициализации массива и заранее инициализирую их в их собственные переменные, такие какитак:

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

Все отлично работает. Я бы просто предпочел , а не делать это таким образом, если это вообще возможно.

Итак ... почему это работает в агрегатной форме, а не с моим явным конструктором? Есть ли способ сделать эту работу? Цените любые идеи, которые может предложить каждый.

Ответы [ 2 ]

0 голосов
/ 04 октября 2019

Проблема, с которой вы столкнулись, заключается в том, что вы пытаетесь инициализировать элементы указателя с помощью std::initializer_list, что просто невозможно.

Однако вы можете использовать std::array (начиная с с ++ 11). Вот упрощенный пример:

#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;
}
0 голосов
/ 04 октября 2019

Вам мешает не явный конструктор, а указатели, которые вы используете вместо массивов:

Следующие объявления переменных:

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];

Become:

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

Указатели не совпадают с массивами.

Вы можете прочитать о разнице между ними: Является ли имя массива указателем?

Чтобы включить этиуказатели, в вашем конструкторе вы должны получить тип, который принимает initializer_list, затем внутри функции вы должны выделить новое место в памяти для ваших указателей, а затем скопировать значения из массивов в ваши новые выделенные указатели.

...