¿El siguiente programa está bien formado?
#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());
}
Según C ++ 17 [secuencia.reqmts], el requisito para
X u(i, j);
donde X
es un contenedor de secuencia, es:
T
seráEmplaceConstructible
enX
de*i
.
Sin embargo, en el párrafo anterior se afirma que:
i
yj
denotan iteradores que satisfacen los requisitos de iterador de entrada y hacen referencia a elementos implícitamente convertibles avalue_type
,
Por lo tanto, me parece que ambos requisitos tendrían que cumplirse: el tipo de valor del rango debe ser implícitamente convertible al tipo de valor del contenedor y EmplaceConstructible
debe cumplirse (lo que significa que el asignador debe poder realizar la inicialización requerida) . Como int
no es implícitamente convertible a A
, este programa debe estar mal formado.
Sin embargo, sorprendentemente, parece compilarse bajo GCC .
Respuestas:
Es solo un requisito que los contenedores de secuencia admitan la construcción a partir de iteradores que satisfacen los criterios de convertibilidad implícita.
Esto por sí solo no permite que los contenedores de secuencias apoyen esa construcción desde iteradores que no satisfacen ese criterio hasta donde puedo decir 1 . Hay una regla explícita sobre eso:
No está claro qué significa "calificar como iterador de entrada" exactamente en el contexto. ¿Es una forma informal de expresar Cpp17InputIterator o intenta referirse a los requisitos de i y j? No lo sé. Ya sea que esté permitido o no, el estándar no tiene un requisito estricto para detectarlo:
Con la interpretación de que cualquier Cpp17InputIterator "califica como un iterador de entrada", no se requerirá que el programa de ejemplo esté mal formado. Pero tampoco se garantiza que esté bien formado.
1 En tal caso, podría considerarse un problema de calidad de implementación para advertir al confiar en él. Por otro lado, esta limitación a las conversiones implícitas puede considerarse un defecto .
PD: esto también se compila sin advertencias en Clang (con libc ++) y Msvc.
PPS Esta redacción parece haberse agregado en C ++ 11 (lo cual es natural, ya que también se introdujeron los constructores explícitos).
fuente
Cpp17InputIterator
, por lo que no me queda claro si "y se refieren a elementos implícitamente convertibles avalue_type
" están incluidos en "iterador de entrada". Si es así, entonces el constructor no debería participar en la resolución de sobrecarga y el programa debería estar mal formado.Cpp17InputIterator
o intenta referirse a los requisitos dei
yj
? No lo sé.