Is the following program well-formed?
#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());
}
Run Code Online (Sandbox Code Playgroud)
According to C++17 [sequence.reqmts], the requirement for
X u(i, j);
Run Code Online (Sandbox Code Playgroud)
where X is a sequence container, is:
Tshall beEmplaceConstructibleintoXfrom*i.
However, in the preceding paragraph it is stated that:
iandjdenote iterators satisfying input iterator requirements and refer to elements implicitly convertible tovalue_type,
Thus it seems to me that both requirements would need to be met: the value type of the range must be implicitly convertible to the value type of the container, and EmplaceConstructible must be satisfied (which means the allocator must be able to perform the required initialization). Since int is not implicitly convertible to A, this program should be ill-formed.
However, surprisingly, it seems to compile under GCC.
仅要求序列容器支持满足隐式可转换性标准的迭代器的构造。
据我所知,这本身并不禁止序列容器支持不满足该标准的迭代器的构造1。对此有明确的规定:
如果使用不符合输入迭代器资格的类型 InputIterator 调用构造函数... ,则构造函数不应参与重载决策。
目前尚不清楚“作为输入迭代器的资格”在上下文中的确切含义。它是表达 Cpp17InputIterator 的非正式方式,还是试图引用 i 和 j 的要求?我不知道。无论是否允许,标准对于检测并没有严格的要求:
[容器.要求.一般]
某些容器成员函数和推导指南的行为取决于类型是否有资格作为输入迭代器或分配器。实现确定类型不能是输入迭代器的程度是未指定的,但作为最小整型类型不应有资格作为输入迭代器。...
根据任何 Cpp17InputIterator“有资格作为输入迭代器”的解释,示例程序不需要格式错误。但也不能保证它是格式良好的。
1在这种情况下,可能会被视为实施质量问题,需要在依赖时发出警告。另一方面,这种对隐式转换的限制可以被认为是一个缺陷。
PS 这在 Clang(使用 libc++)和 Msvc 中编译时也没有警告。
PPS 这个措辞似乎是在 C++11 中添加的(这是很自然的,因为当时还引入了显式构造函数)。