Warum kann ich eine Warteschlange / einen Stapel mit geschweiften Initialisierungslisten nicht erstellen? (C ++ 11)

7

Programm 1:

%Vor%

Programm 2:

%Vor%

Fehlermeldung:

%Vor%

Frage:
Warum können Warteschlangen nicht wie Vektoren initialisiert werden? Ich nehme an, sie sind keine Sequenzcontainer, aber warum sollte das wichtig sein? Ich bin mir sicher, dass es einen guten Grund gibt, aber ich kann keine Erklärungen finden.

gcc (Ubuntu / Linaro 4.6.1-9ubuntu3) 4.6.1

    
Trevor Hickey 24.04.2012, 07:10
quelle

3 Antworten

18

Ich glaube nicht, dass es wirklich etwas mit Container-Adaptern zu tun hat, anstatt mit Containern (obwohl ich zugeben muss, dass ich nicht genau weiß, warum der korrekte Konstruktor weggelassen wird).

Wenn Sie eine starre Initialisierungsliste mit std::vector verwenden, verwenden Sie diesen Konstruktor (neu in C ++ 11):

%Vor%

Betrachtet man die Definition von std::queue , sind die verfügbaren Konstruktoren:

%Vor%

Ein Konstruktor, der eine Initialisierungsliste verwendet, ist auffallend abwesend.

Ich bin ziemlich sicher, dass ein solcher Konstruktor, obwohl er ein Container-Adapter ist, trivial wäre, wenn er gewünscht würde. Nur zum Beispiel:

%Vor%

g ++ 4.7 akzeptiert dies ohne Probleme und produziert genau die Ausgabe, die Sie erwarten:

%Vor%

Obwohl ich nicht mit anderen Compilern getestet habe, kann ich keinen Grund sehen, warum andere Compiler nicht gut damit arbeiten würden (vorausgesetzt, sie implementieren natürlich die notwendigen Funktionen).

Edit: Ich habe gerade ein wenig durch die Komiteepapiere geschaut, die das Hinzufügen von initalisizer_listen zu C ++ vorschlagen (z. B. N1890, N1919, N2100, N2215, N2220) und es sieht für mich wie eine einfache Aufsicht aus. Viele der früheren Arbeiten sind eher konzeptuell, aber N2220 enthält eine beträchtliche Menge an vorgeschlagenen Sprachen für das Arbeitspapier. Für std::array (für ein Beispiel) wird ausdrücklich darauf hingewiesen, dass keine Änderung erforderlich ist. Es geht dann durch deque , vector , [unordered_][multi_](set|map) und zeigt Änderungen an, die für jeden benötigt werden - aber es wird überhaupt kein Stapel oder eine Warteschlange in irgendeiner Richtung erwähnt. Kein Vorschlag, Unterstützung für std::initializer_list hinzuzufügen, noch (wie std::array ) Begründung für ihre Auslassung.

Ich würde daraus schließen, dass es ein einfaches Versehen war, das wahrscheinlich aus zwei Gründen durchging: 1) die Adapter sind fast, aber nicht ganz Container, und 2) die Adapterklassen scheinen nicht viel benutzt zu werden Es war wahrscheinlich ziemlich einfach, sie zu vergessen (und natürlich der allgegenwärtige dritte Grund: Die meisten der aktiven Ausschussmitglieder sind schrecklich überarbeitet).

Edit2: Ich sollte wahrscheinlich ein weiteres Detail hinzufügen: Da stack und queue beide einen anderen Container für die Initialisierung akzeptieren können, können Sie ziemlich einfach Folgendes tun:

%Vor%

Dies ist etwas ausführlich, aber es ist unwahrscheinlich, dass es zu einem Effizienzverlust kommt (der Container wird als rvalue-Referenz übergeben, so dass seine Darstellung "gestohlen" anstatt kopiert wird). Es gibt jedoch einen Vorbehalt: Wenn der verwendete Containertyp nicht mit dem Container übereinstimmt, der dem Containeradapter zugrunde liegt, erhalten Sie eine Kopie und nicht eine Verschiebung (und verlieren dadurch möglicherweise an Effizienz).

    
Jerry Coffin 24.04.2012, 07:48
quelle
8
%Vor%     
Jon 14.12.2014 05:50
quelle
6

std::queue und std::stack sind eigentlich keine Container , sie sind sogenannte Containeradapter , die einen Container verwenden (standardmäßig std::deque ). Daher können Sie es nicht als andere Container initialisieren.

Bearbeiten

Damit ein Container eine Initialisierungsliste verwenden kann, muss ein Konstruktor über eine std::initializer_list als Argument. Die Containeradapter tun das nicht. Wenn es absichtlich oder eine Aufsicht des Normenausschusses ist, ist es jedermanns Interpretation überlassen.

    
Some programmer dude 24.04.2012 07:14
quelle