O programa a seguir está bem 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());
}
De acordo com o C ++ 17 [sequence.reqmts], o requisito para
X u(i, j);
onde X
é um contêiner de sequência, é:
T
seráEmplaceConstructible
paraX
partir*i
.
No entanto, no parágrafo anterior, afirma-se que:
i
ej
denotam iteradores que atendem aos requisitos do iterador de entrada e se referem a elementos implicitamente conversíveis emvalue_type
,
Assim, parece-me que ambos os requisitos precisariam ser atendidos: o tipo de valor do intervalo deve ser implicitamente conversível no tipo de valor do contêiner e EmplaceConstructible
deve ser atendido (o que significa que o alocador deve ser capaz de executar a inicialização necessária) . Como int
não é implicitamente conversível em A
, este programa deve ser mal formado.
No entanto, surpreendentemente, parece compilar sob o GCC .
Respostas:
É apenas um requisito para os contêineres de sequência apoiarem a construção de iteradores que atendem aos critérios de conversibilidade implícita.
Isso, por si só, não proíbe os contêineres de sequência de apoiar essa construção a partir de iteradores que não atendem a esse critério, até onde eu sei 1 . Há uma regra explícita sobre isso:
Não está claro o que "qualificar como um iterador de entrada" significa exatamente no contexto. É uma maneira informal de expressar Cpp17InputIterator ou tenta se referir aos requisitos de iej? Eu não sei. Se é permitido ou não, o padrão não tem um requisito estrito para detectá-lo:
Com a interpretação de que qualquer Cpp17InputIterator "se qualifica como um iterador de entrada", o programa de exemplo não precisa ser mal formado. Mas também não é garantido que seja bem formado.
1 Nesse caso, pode ser considerado um problema de qualidade de implementação a ser advertido ao confiar nele. Por outro lado, essa limitação às conversões implícitas pode ser considerada um defeito .
PS Isso compila sem avisos no Clang (com libc ++) e no Msvc.
PPS Esta expressão parece ter sido adicionada no C ++ 11 (o que é natural, como também foram introduzidos explicitamente construtores).
fonte
Cpp17InputIterator
, portanto, não está claro para mim se "e se referem a elementos implicitamente conversíveis emvalue_type
" estão incluídos no "iterador de entrada". Se for, o construtor não deve participar da resolução de sobrecarga e o programa deve estar mal formado.Cpp17InputIterator
ou tenta se referir aos requisitos dei
ej
? Eu não sei.