Czy następujący program jest dobrze sformułowany?
#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());
}
Zgodnie z C ++ 17 [sekwencja.reqmts] wymóg dotyczący
X u(i, j);
gdzie X
jest kontenerem sekwencji, jest:
T
będzieEmplaceConstructible
doX
z*i
.
Jednak w poprzednim akapicie stwierdzono, że:
i
ij
oznaczają iteratory spełniające wymagania iteratora wejściowego i odnoszą się do elementów domyślnie konwertowalnychvalue_type
,
Wydaje mi się zatem, że oba wymagania musiałyby zostać spełnione: typ wartości zakresu musi być domyślnie konwertowany na typ wartości kontenera i EmplaceConstructible
musi być spełniony (co oznacza, że alokator musi być w stanie wykonać wymaganą inicjalizację) . Ponieważ int
nie można go domyślnie przekonwertować A
, ten program powinien być źle sformułowany.
Jednak, co zaskakujące, wydaje się , że kompiluje się w GCC .
Odpowiedzi:
Jest to tylko wymóg, aby kontenery sekwencji wspierały konstrukcję z iteratorów, które spełniają kryteria niejawnej wymienialności.
To samo w sobie nie uniemożliwia kontenerom sekwencji wspierania tej konstrukcji z iteratorów, które nie spełniają tych kryteriów, o ile mogę powiedzieć 1 . Istnieje wyraźna zasada:
Nie jest jasne, co „kwalifikować się jako iterator wejściowy” oznacza dokładnie w kontekście. Czy to nieformalny sposób wyrażenia Cpp17InputIterator, czy też próbuje odwoływać się do wymagań i i j? Nie wiem Niezależnie od tego, czy jest to dozwolone, czy nie, standard nie ma ścisłego wymogu wykrywania:
Przy interpretacji, że jakikolwiek Cpp17InputIterator „kwalifikuje się jako iterator wejściowy”, przykładowy program nie wymagałby nieprawidłowego kształtowania. Ale nie ma też gwarancji, że będzie dobrze uformowany.
1 W takim przypadku można uznać za problem z jakością wdrożenia ostrzeżenie, gdy się na nim opiera. Z drugiej strony to ograniczenie do konwersji niejawnych można uznać za wadę .
PS Kompiluje się bez ostrzeżeń w Clang (z libc ++) i Msvc.
PPS Wydaje się, że to sformułowanie zostało dodane w C ++ 11 (co jest naturalne, ponieważ wprowadzono także jawne konstruktory).
źródło
Cpp17InputIterator
, więc nie jest dla mnie jasne, czy „i odnoszą się do elementów domyślnie konwertowalnych navalue_type
” jest zawarte w „iteratorze wejściowym”. Jeśli tak, to konstruktor nie powinien brać udziału w rozwiązywaniu problemów z przeciążeniem, a program powinien być źle sformułowany.Cpp17InputIterator
, czy też próbuje odwoływać się do wymagańi
ij
? Nie wiem