too many initializers

0

ayo, jak powinienen wygladac poprawnie ponizszy kod:

#include <iostream>
#include <array>
using namespace std;


int main(int argc, char *argv[]) {

	array<array<uint32_t, 16>, 4> arr=
	{
		{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
		{ 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 },
		{ 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 },
		{ 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 },
	};
	return 0;
}

pewnie to jakas błahostka ale wydaje mi sie ze poprawnie tworze array. kompilator podpowiada
prog.cpp2: error: too many initializers for 'std::array<std::array<unsigned int, 16u>, 4u>'
};
i pewnie ma racje ale ja nie widze mojego bledu, jakas porada?
http://ideone.com/oWjDYF

6

Wbrew pozorom problem nie jest taki banalny. std::array to agregat, który wrapuje C-array. Inicjalizując go powinieneś użyć dwóch brace initializers, jeden dla klasy std::array, drugi dla C-array. Dla przykładu:

std::array<int, 2> foo = { { 1, 2 } };

Analogicznie dla tablicy tablic:

std::array<std::array<int, 2>, 2> foo  = { // std::array
    { // C-array
        { // std::array
            { 1, 2 } // C-array
        },
        {
            { 4, 5 }
        }
    }
};

Zatem w twoim przypadku będzie to wyglądało tak:

std::array<std::array<uint32_t, 16>, 4> foo = {
    {
        { { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } },
        { { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } },
        { { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 } },
        { { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 } }
    }
};

Cały zapis można trochę upiększyć korzystając z brace elision [8.5.1.12]:

std::array<std::array<uint32_t, 16>, 4> foo = {
    {
        { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
        { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 },
        { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 },
        { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 }
    }
};

Dwie kwestie, które trzeba mieć na uwadze stosując brace elision:

  1. Jeśli kompilujesz kod z flagą -Wmissing-braces to dostaniesz sporo warningów o brakujących nawiasach ; p
  2. Do czasu C++14 brace elision miało prawo zadziałać tylko podczas copy list initialization (czyli tam gdzie występował znak =). Od C++14 występuje zarówno dla direct initialization oraz copy initialization.

No i jak nie chcesz sobie tym zawracać głowy to zrób, tak jak to pokazał @_13th_Dragon : >

1 użytkowników online, w tym zalogowanych: 0, gości: 1