Правильно ли сформирована следующая программа?
#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());
}
Согласно C ++ 17 [sequence.reqmts], требование для
X u(i, j);
где X
контейнер последовательности, это:
T
должен бытьEmplaceConstructible
вX
от*i
.
Однако в предыдущем абзаце указано, что:
i
иj
обозначают итераторы, удовлетворяющие требованиям входных итераторов, и ссылаются на элементы, неявно преобразуемые вvalue_type
,
Таким образом, мне кажется, что оба требования должны быть выполнены: тип значения диапазона должен быть неявно конвертируемым в тип значения контейнера и EmplaceConstructible
должен быть удовлетворен (что означает, что распределитель должен быть в состоянии выполнить требуемую инициализацию) , Поскольку эта программа не может быть int
преобразована в неявно A
, она должна быть некорректной.
Однако, что удивительно, похоже, что компилируется в GCC .
Ответы:
Для контейнеров последовательностей требуется только поддержка конструкции из итераторов, которые удовлетворяют критериям неявной конвертируемости.
Это само по себе не запрещает контейнерам последовательности поддерживать эту конструкцию от итераторов, которые не соответствуют этим критериям, насколько я могу судить 1 . Существует явное правило об этом:
Неясно, что именно «квалифицировать как входной итератор» означает именно в контексте. Это неофициальный способ выражения Cpp17InputIterator, или он пытается сослаться на требования i и j? Я не знаю. Независимо от того, разрешено это или нет, стандарт не имеет строгих требований для его обнаружения:
С интерпретацией, что любой Cpp17InputIterator «квалифицируется как входной итератор», примерная программа не должна быть плохо сформированной. Но это также не гарантирует, что он будет хорошо сформирован.
1 В таком случае это может считаться проблемой качества реализации, о которой следует предупреждать, полагаясь на нее. С другой стороны, это ограничение неявных преобразований можно считать недостатком .
PS Это компилируется без предупреждений в Clang (с libc ++) и Msvc.
PPS Эта формулировка, кажется, была добавлена в C ++ 11 (что естественно, так как тогда были также введены явные конструкторы).
источник
Cpp17InputIterator
, поэтому мне не ясно, включен ли «и относится к элементам, неявно преобразуемым вvalue_type
», во «входной итератор». Если это так, то конструктор не должен участвовать в разрешении перегрузки, и программа должна быть некорректной.Cpp17InputIterator
, или он пытается сослаться на требованияi
иj
? Я не знаю.