Ist das folgende Programm gut formuliert?
#include <vector>
struct A {
explicit A(int) {}
};
int main() {
std::vector<int> vi = {1, 2, 3, 4, 5};
std::vector<A> va(vi.begin(), vi.end());
}
Gemäß C ++ 17 [sequence.reqmts] ist die Anforderung für
X u(i, j);
Wo X
ist ein Sequenzcontainer, ist:
T
sollEmplaceConstructible
inX
von sein*i
.
Im vorhergehenden Absatz heißt es jedoch:
i
undj
bezeichnen Iteratoren, die die Anforderungen an Eingabe-Iteratoren erfüllen, und beziehen sich auf Elemente, die implizit konvertierbar sind invalue_type
:
Daher scheint es mir, dass beide Anforderungen erfüllt sein müssten: Der Werttyp des Bereichs muss implizit in den Werttyp des Containers konvertierbar sein und EmplaceConstructible
erfüllt sein (was bedeutet, dass der Allokator in der Lage sein muss, die erforderliche Initialisierung durchzuführen). . Da int
es nicht implizit konvertierbar ist, A
sollte dieses Programm schlecht geformt sein.
Überraschenderweise scheint es jedoch unter GCC zu kompilieren .
Antworten:
Sequenzcontainer müssen lediglich die Konstruktion von Iteratoren unterstützen, die die Kriterien der impliziten Konvertierbarkeit erfüllen.
Dies verhindert nicht, dass Sequenzcontainer diese Konstruktion von Iteratoren unterstützen, die diese Kriterien nicht erfüllen, soweit ich das beurteilen kann 1 . Es gibt eine explizite Regel dazu:
Es ist unklar, was "als Eingabe-Iterator qualifizieren" genau im Kontext bedeutet. Ist es eine informelle Möglichkeit, Cpp17InputIterator auszudrücken, oder wird versucht, auf die Anforderungen von i und j zu verweisen? Ich weiß es nicht. Unabhängig davon, ob dies zulässig ist oder nicht, stellt der Standard keine strengen Anforderungen an die Erkennung:
Mit der Interpretation, dass ein Cpp17InputIterator "als Eingabe-Iterator qualifiziert", müsste das Beispielprogramm nicht fehlerhaft sein. Aber es ist auch nicht garantiert, dass es gut geformt ist.
1 In diesem Fall kann es als Qualitätsproblem bei der Implementierung angesehen werden, wenn Sie sich darauf verlassen. Andererseits kann diese Beschränkung auf implizite Konvertierungen als Fehler angesehen werden .
PS Dies wird auch in Clang (mit libc ++) und Msvc ohne Warnungen kompiliert.
PPS Dieser Wortlaut scheint in C ++ 11 hinzugefügt worden zu sein (was natürlich ist, da damals auch explizite Konstruktoren eingeführt wurden).
quelle
Cpp17InputIterator
, daher ist mir nicht klar, ob "und auf Elemente verweisen, die implizit in konvertierbar sindvalue_type
" in "Eingabe-Iterator" enthalten ist. Wenn dies der Fall ist, sollte der Konstruktor nicht an der Überlastungsauflösung teilnehmen und das Programm sollte fehlerhaft sein.Cpp17InputIterator
, oder versucht es, sich auf die Anforderungen voni
und zu beziehenj
? Ich weiß es nicht.