Ich komme mit C++0x auf den neuesten Stand und teste Dinge mit g++ 4.6
Ich habe gerade den folgenden Code ausprobiert und dachte, er würde funktionieren, aber er lässt sich nicht kompilieren. Ich bekomme den Fehler:
incompatible types in assignment of ‘std::initializer_list<const int>’ to ‘const int [2]’
struct Foo
{
int const data[2];
Foo(std::initializer_list<int const>& ini)
: data(ini)
{}
};
Foo f = {1,3};

JohannesD
Sie können einen variadischen Vorlagenkonstruktor anstelle eines Initialisierungslistenkonstruktors verwenden:
struct foo {
int x[2];
template <typename... T>
foo(T... ts) : x{ts...} { // note the use of brace-init-list
}
};
int main() {
foo f1(1,2); // OK
foo f2{1,2}; // Also OK
foo f3(42); // OK; x[1] zero-initialized
foo f4(1,2,3); // Error: too many initializers
foo f5(3.14); // Error: narrowing conversion not allowed
foo f6("foo"); // Error: no conversion from const char* to int
}
BEARBEITEN: Wenn du ohne Beständigkeit leben kannst, Eine andere Möglichkeit wäre, die Initialisierung zu überspringen und das Array im Funktionskörper zu füllen:
struct foo {
int x[2]; // or std::array<int, 2> x;
foo(std::initializer_list<int> il) {
std::copy(il.begin(), il.end(), x);
// or std::copy(il.begin(), il.end(), x.begin());
// or x.fill(il.begin());
}
}
Auf diese Weise verlieren Sie jedoch die Kompilierzeitgrenzen, die die vorherige Lösung bietet.

Kartoffelklatsche
Soweit ich das beurteilen kann, sollte die Verwendung der Listeninitialisierung des Funktionsarguments des Konstruktors (8.5.4/1) legal sein und viele der oben genannten Probleme lösen. GCC 4.5.1 auf ideone.com stimmt jedoch nicht mit dem Konstruktor überein und lehnt ihn ab.
#include <array>
struct Foo
{
std::array< int, 2 > const data;
Foo(std::array<int, 2> const& ini) // parameter type specifies size = 2
: data( ini )
{}
};
Foo f( {1,3} ); // list-initialize function argument per 8.5.4/1
Wenn Sie wirklich darauf bestehen initializer_list
, können Sie verwenden reinterpret_cast
um das zugrunde liegende Array der zu drehen initializer_list
in ein Array im C-Stil.
Foo(std::initializer_list<int> ini) // pass without reference- or cv-qualification
: data( reinterpret_cast< std::array< int, 2 > const & >( * ini.begin() )
Laut Diskussion Hier:
Die richtige Syntax für die zweite Lösung von Potatoswatter lautet:
Foo f( {{1,3}} ); //two braces
ein bisschen hässlich, nicht im Einklang mit dem allgemeinen Sprachgebrauch

Ivan Aksamentov – Tropfen
Nur eine kleine Ergänzung zur großartigen Antwort von JohannesD.
Falls keine Argumente übergeben werden foo
Konstruktor, Array wird standardmäßig initialisiert. Aber manchmal möchten Sie das zugrunde liegende Array nicht initialisiert lassen (vielleicht aus Leistungsgründen). Sie können den Standardkonstruktor nicht zusammen mit einem variadic-templated hinzufügen. Die Problemumgehung ist ein zusätzliches Argument für den Konstruktor mit Variadic-Vorlage, um ihn vom Konstruktor mit null Argumenten zu unterscheiden:
template<class T, size_t rows, size_t cols>
class array2d
{
std::array<T, rows * cols> m_Data;
public:
array2d() {}
template <typename T, typename... Types>
array2d(T t, Types... ts) : m_Data{ { t, ts... } } {}
};
Jetzt können Sie das Objekt mit Klammern initialisieren oder nicht initialisieren:
array2d<int, 6, 8> arr = { 0, 1, 2, 3 }; // contains 0, 1, 2, 3, 0, 0, 0, ...
array2d<int, 6, 8> arr2; // contains garbage
Aktualisierung 31.07.2016
Drei Jahre sind schnell vergangen, und Compiler-Implementierer haben die Standardkonformität ihrer Produkte bis zu dem Niveau verbessert, auf dem der Standardkonstruktor in Gegenwart eines variadischen Konstruktors nicht mehr als mehrdeutig angesehen wird. In der Praxis brauchen wir also keine zusätzlichen T t
Argument für den variadischen Konstruktor, um Konstruktoren eindeutig zu machen.
Beide
array2d() {}
und
array2d() = default;
lässt das Array nicht initialisiert, wenn das Objekt ohne Argumente konstruiert wird. Dieses Verhalten ist bei allen wichtigen Compilern konsistent. Vollständiges Beispiel (Rexester):
#include <array>
#include <iostream>
template<class T, size_t rows, size_t cols>
class array2d
{
public:
std::array<T, rows * cols> m_Data;
array2d() = default;
template <typename... Types>
array2d(Types... ts) : m_Data{ { ts... } } {}
};
int main()
{
array2d<int, 6, 8> arr_init = { 0, 1, 2, 3 };
array2d<int, 6, 8> arr_default;
std::cout << "Initialized: n";
for(const auto& a : arr_init.m_Data)
std::cout << a << " ";
std::cout << "n";
std::cout << "Default: n";
for(const auto& a : arr_default.m_Data)
std::cout << a << " ";
std::cout << "n";
}
Ausgabe:
Initialized:
0 1 2 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
Default:
2 0 -519559849 32558 1 32558 0 0 -519634912 32558 -526739248 32558 1 0 2 0 6295032 0 -519531243 32558 0 0 -1716075168 32765 6295648 0 4196192 0 6295648 0 -526527271 32558 1 0 2 0 6295032 0 4196845 0 124 0 0 0 4196768 0 4196518 0
Das Entfernen des Standardkonstruktors führt immer noch dazu, dass der variadische Konstruktor aufgerufen und das Array standardmäßig initialisiert wird (in unserem Fall nur mit Nullen).
Danke @Alek, dass du diesen Thread gepusht hast und auf diese Fakten aufmerksam gemacht hast, und auch danke an alle Leute, die hart an der Compiler-Entwicklung arbeiten.

Bo Persson
Sie können nicht, Arrays sind nicht wie andere Typen (und haben keine Konstruktoren, die eine std::initializer_list verwenden).
Versuchen Sie stattdessen Folgendes:
struct Foo
{
const std::vector<int> data;
Foo(std::initializer_list<int> ini) : data(ini)
{}
};

Erik Schnetter
You can define a constexpr
function that converts an initializer list to an array. The last (third) function is the one you call. The other create recursively a template parameter pack from the initializer list, and create the array once sufficiently many list elements have been read.
template <typename T, size_t N, typename... Ts>
constexpr enable_if_t<(sizeof...(Ts) == N), array<T, N> >
array_from_initializer_list(const T *const beg, const T *const end,
const Ts... xs) {
return array<T, N>{xs...};
}
template <typename T, size_t N, typename... Ts>
constexpr enable_if_t<(sizeof...(Ts) < N), array<T, N> >
array_from_initializer_list(const T *const beg, const T *const end,
const Ts... xs) {
return array_from_initializer_list<T, N>(beg + 1, end, *beg, xs...);
}
template <typename T, size_t N>
constexpr array<T, N> array_from_initializer_list(initializer_list<T> l) {
return array_from_initializer_list<T, N>(l.begin(), l.end());
}

franjesus
While this does not work:
#include <initializer_list>
struct Foo
{
const int data[2]; constexpr Foo(const std::initializer_list& ini): data{ini} {} }; Foo f = {1,3};
Ich fand diesen einfachen Ansatz gut zu funktionieren:
struct Foo
{
const int data[2];
constexpr Foo(const int a, const int b): data{a,b} {}
};
Foo f = {1,3};
Natürlich ist der variadische Template-Ansatz wahrscheinlich besser, wenn Sie viele Elemente haben, aber in diesem einfachen Fall wird dies wahrscheinlich ausreichen.
Das heißt, wenn Sie den Konstruktor explizit aus Initialisierungslisten definieren möchten. Für die meisten POD-Fälle ist dies in Ordnung und gut:
struct Foo
{
const int data[2];
};
Foo f = {1,3};
.
7840500cookie-checkWie initialisiere ich ein Member-Array mit einer initializer_list?yes