std::vector 范围构造函数可以调用显式转换吗?
Can the std::vector range constructor invoke explicit conversions?
以下程序格式是否正确?
#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
应从*i
EmplaceConstructible
X
。
但是,在前一段中指出:
i
和j
表示满足输入迭代器要求的迭代器,并引用可隐式转换为value_type
的元素,
因此,在我看来,这两个要求都需要满足:范围的值类型必须隐式转换为容器的值类型,并且必须满足EmplaceConstructible
(这意味着分配器必须能够执行所需的初始化)。由于int
不能隐式转换为A
,这个程序应该是格式错误的。
然而,令人惊讶的是,它似乎是在 GCC 下编译的。
序列容器仅要求支持从满足隐式可转换性标准的迭代器进行构造。
据我所知,这本身并不允许序列容器从不满足该标准的迭代器支持该构造1。对此有明确的规则:
如果构造函数...使用不符合输入迭代器条件的输入迭代器类型调用,则构造函数不得参与重载解析。
目前尚不清楚"有资格作为输入迭代器"在上下文中的确切含义。它是表达Cpp17InputIterator的非正式方式,还是试图引用i和j的要求?我不知道。无论是否允许,标准都没有严格的检测要求:
[容器.要求.一般]
某些容器成员函数和推导线的行为取决于类型是输入迭代器还是分配器。 未指定实现确定类型不能是输入迭代器的程度,但作为最小整数类型不应符合输入迭代器的条件。...
通过解释任何Cpp17InputIterator"有资格作为输入迭代器",示例程序不需要格式错误。但它也不能保证是良好的。
1在这种情况下,在依赖它时发出警告可能被视为实施质量问题。另一方面,对隐式转换的这种限制可能被视为缺陷。
<小时 />附言这在Clang(使用libc ++)和Msvc中编译时也没有警告。
附言这个措辞似乎是在 C++11 中添加的(这是很自然的,因为当时也引入了显式构造函数)。
- 整数类型应该显式转换(例如"int"到"无符号")还是只会增加混乱?
- 如何确保调用显式构造函数并允许大括号初始化?
- std::vector 范围构造函数可以调用显式转换吗?
- 从 uint8_t 到 int 的隐式转换出错了,当显式转换进展顺利时
- 从 int 显式转换为用户定义的类 c++
- 自动(toCast)显式转换是否计划在未来C++标准?
- 为什么C++隐式转换有效,而显式转换无效?
- 使用分配进行显式转换
- 使用 static_cast、dynamic_cast 或显式转换进行派生指向 Base 指针转换的指针不会调用 base 函数
- 返回语句中的C++11显式转换运算符/构造函数
- 如何解决Visual Studio 2012不支持显式转换运算符的问题
- 通过显式转换函数初始化枚举类类型的静态constexpr类成员
- 是否可以调用显式指定模板参数的模板化强制转换运算符
- C++ 为什么我们需要从一种类型显式转换为另一种类型
- 为什么这里没有调用显式构造函数
- 当显式转换是必需的并且隐式转换将不起作用时
- C++显式转换和隐式转换
- 如何争论多个显式转换函数
- C++显式转换构造函数
- 转换为枚举类型需要显式转换(static_cast、C样式转换或函数样式转换)