Frage

Seit C ++ 11 die Standardbibliotheksbehälter und die Standardbibliotheksbehälter und std::string Konstrukteure nehmen eine Initialisiererliste ein. Dieser Konstruktor hat Vorrang vor anderen Konstruktoren (auch, wie @Johannesschaub-LitB in den Kommentaren hervorgeht, sogar andere "beste Übereinstimmung" -Kriterien ignoriert). Dies führt zu einigen bekannten Fallstricken bei der Umwandlung aller Klammern () Formen von Konstruktoren zu ihren versperrten Versionen {}

#include <algorithm>
#include <iostream>
#include <iterator>
#include <vector>
#include <string>

void print(std::vector<int> const& v)
{
    std::copy(begin(v), end(v), std::ostream_iterator<int>(std::cout, ","));
    std::cout << "\n";
}

void print(std::string const& s)
{
    std::cout << s << "\n";
}

int main()
{
    // well-known 
    print(std::vector<int>{ 11, 22 });  // 11, 22, not 11 copies of 22
    print(std::vector<int>{ 11 });      // 11,     not 11 copies of 0

    // more surprising
    print(std::string{ 65, 'C' });      // AC,     not 65 copies of 'C'
}

Ich konnte das dritte Beispiel auf dieser Seite nicht finden, und das Ding kam in der Lounge aufu003CC++> Chat (in der Diskussion mit @rightfold, @AByx und @jerrycoffin) ist das etwas überraschende Ding, das die Konvertierung der Konvertierung std::string Konstruktor, der eine Zählung und einen Charakter verwendet, um sie zu verwenden {} Anstatt von (), verändert seine Bedeutung von n Kopien des Charakters in die n-D -Zeichen (typischerweise aus der ASCII -Tabelle) gefolgt von dem anderen Charakter.

Dies wird nicht durch das übliche Klammerverbot bei der Verengung von Konvertierungen erfasst, da 65 ein konstanter Ausdruck ist, der als Zeichen dargestellt werden kann und seinen ursprünglichen Wert beibehält, wenn sie wieder in INT konvertiert werden (§8.5.4/7, Bullet 4) (danke an @jerrycoffin).

Frage: Gibt es weitere Beispiele, die in der Standardbibliothek lauern, in der ein Konvertieren a () Stilkonstruktor zu {} Stil, wird gierig von einem Initializer-List-Konstruktor übereinstimmt?

War es hilfreich?

Lösung

Ich nehme an, mit Ihren Beispielen für std::vector<int> und std::string Sie wollten auch die anderen Behälter abdecken, z. B. std::list<int>, std::deque<int>, usw., die offensichtlich das gleiche Problem haben wie std::vector<int>. Ebenso das int ist nicht der einzige Typ, wie es auch gilt char, short, long und ihre unsigned Version (möglicherweise auch einige andere integrale Typen).

Ich denke es gibt es auch std::valarray<T> Aber ich bin mir nicht sicher, ob T darf integraler Typ sein. Eigentlich denke ich, dass diese unterschiedliche Semantik haben:

std::valarray<double>(0.0, 3);
std::valarray<double>{0.0, 3};

Es gibt einige andere Standard -C ++ - Klassenvorlagen, die eine annehmen std::initializer_list<T> als Argument, aber ich glaube nicht, dass einer davon einen überlasteten Konstruktor hat, der bei der Verwendung von Klammern anstelle von Klammern verwendet wird.

Andere Tipps

Nur nach dem Auftreten von initializer_list.

  • Alle Sequenzen haben die Konstruktoren wie die von Vector:

    • Deque
    • Dynarray
    • vorwärts_list
    • aufführen
    • Vektor
  • Valarray

  • Basic_String

  • Unbestrahlte Sammlungen gibt es einen Konstruktor, der eine Ganzzahl braucht, um die anfängliche Eimerzahl zu bestimmen.

    • Under Ordered_set
    • unbestraftet_multiset

Ich denke, das ist alles.

#include <unordered_set>
#include <iostream>

int main() {
    std::unordered_set<int> f (3);
    std::unordered_set<int> g {3};
    std::cout << f.size() << "/" << g.size() << std::endl; // prints 0/1.
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top