Le programme suivant est-il bien formé?
#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());
}
Selon C ++ 17 [sequence.reqmts], l'exigence de
X u(i, j);
où X
est un conteneur de séquence, est:
T
doit êtreEmplaceConstructible
àX
partir de*i
.
Cependant, au paragraphe précédent, il est indiqué que:
i
etj
désignent des itérateurs satisfaisant aux exigences des itérateurs d'entrée et font référence à des éléments implicitement convertibles envalue_type
,
Ainsi, il me semble que les deux exigences devraient être remplies: le type de valeur de la plage doit être implicitement convertible en type de valeur du conteneur, et EmplaceConstructible
doit être satisfait (ce qui signifie que l'allocateur doit pouvoir effectuer l'initialisation requise) . Puisqu'il int
n'est pas implicitement convertible en A
, ce programme devrait être mal formé.
Cependant, étonnamment, il semble compiler sous GCC .
Réponses:
Il suffit que les conteneurs de séquences prennent en charge la construction à partir d'itérateurs qui satisfont aux critères de convertibilité implicite.
Cela ne permet pas en soi d'interdire aux conteneurs de séquence de soutenir cette construction à partir d'itérateurs qui ne satisfont pas à ces critères pour autant que je sache 1 . Il y a une règle explicite à ce sujet:
On ne sait pas exactement ce que "qualifier d'itérateur d'entrée" signifie exactement dans le contexte. Est-ce un moyen informel d'exprimer Cpp17InputIterator ou tente-t-il de se référer aux exigences de i et j? Je ne sais pas. Qu'elle soit autorisée ou non, la norme n'a pas d'exigence stricte pour la détecter:
Avec l'interprétation que tout Cpp17InputIterator "se qualifie comme un itérateur d'entrée", le programme d'exemple n'aurait pas besoin d'être mal formé. Mais il n'est pas non plus garanti d'être bien formé.
1 Dans ce cas, il peut être considéré comme un problème de qualité de mise en œuvre d'avertir lorsque vous vous y fiez. En revanche, cette limitation aux conversions implicites peut être considérée comme un défaut .
PS Cela compile sans avertissements dans Clang (avec libc ++) et Msvc également.
PPS Cette formulation semble avoir été ajoutée en C ++ 11 (ce qui est naturel, tout comme les constructeurs explicites ont également été introduits).
la source
Cpp17InputIterator
, il n'est donc pas clair pour moi si "et faire référence à des éléments implicitement convertibles envalue_type
" est inclus dans "itérateur d'entrée". Si c'est le cas, le constructeur ne doit pas participer à la résolution de surcharge et le programme doit être mal formé.Cpp17InputIterator
ou tente-t-elle de se référer aux exigences dei
etj
? Je ne sais pas.