std::vector 范围构造函数可以调用显式转换吗?

Can the std::vector range constructor invoke explicit conversions?

本文关键字:调用 显式转换 vector 范围 构造函数 std      更新时间:2023-10-16

以下程序格式是否正确?

#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应从*iEmplaceConstructibleX

但是,在前一段中指出:

ij表示满足输入迭代器要求的迭代器,并引用可隐式转换为value_type的元素,

因此,在我看来,这两个要求都需要满足:范围的值类型必须隐式转换为容器的值类型,并且必须满足EmplaceConstructible(这意味着分配器必须能够执行所需的初始化)。由于int不能隐式转换为A,这个程序应该是格式错误的。

然而,令人惊讶的是,它似乎是在 GCC 下编译的。

序列容器仅要求支持从满足隐式可转换性标准的迭代器进行构造。

据我所知,这本身并不允许序列容器从不满足该标准的迭代器支持该构造1。对此有明确的规则:

如果构造函数...使用不符合输入迭代器条件的输入迭代器类型调用,则构造函数不得参与重载解析。

目前尚不清楚"有资格作为输入迭代器"在上下文中的确切含义。它是表达Cpp17InputIterator的非正式方式,还是试图引用i和j的要求?我不知道。无论是否允许,标准都没有严格的检测要求:

[容器.要求.一般]

某些容器成员函数和推导线的行为取决于类型是输入迭代器还是分配器。 未指定实现确定类型不能是输入迭代器的程度,但作为最小整数类型不应符合输入迭代器的条件。...

通过解释任何Cpp17InputIterator"有资格作为输入迭代器",示例程序不需要格式错误。但它也不能保证是良好的。

1在这种情况下,在依赖它时发出警告可能被视为实施质量问题。另一方面,对隐式转换的这种限制可能被视为缺陷。

<小时 />

附言这在Clang(使用libc ++)和Msvc中编译时也没有警告。

附言这个措辞似乎是在 C++11 中添加的(这是很自然的,因为当时也引入了显式构造函数)。