【发布时间】:2022-03-13 02:43:46
【问题描述】:
在下面的示例中,我希望 v 有 1 个元素,而 var 的类型将是 Vector 并将包含两个“int”Variants 10 和 20。
这是我在 gcc 中可以看到的行为。
在 clang 中,'v' 包含两个元素,即两个“int”Variants 10 和 20。
我认为 gcc 的向量是通过 initializer_list 构造函数创建的,而 clang 的向量是通过 move 构造函数创建的
这是其中一个编译器的错误吗?我是否需要将Variant 的构造函数设置为explicit(这将迫使我像Variant::Vector v{Variant{Variant::Vector{10, 20}}}; 一样使用它。如果我想保持构造函数不显式,还有其他方法可以避免这个问题吗?
用https://wandbox.org/ 中的所有 gcc 和 clang 版本尝试了这段代码,它的行为相同。这里有一些链接可以直接试用:gcc,clang
#include <iostream>
#include <variant>
#include <vector>
struct Variant
{
using Vector = std::vector<Variant>;
Variant(const Vector & value)
{
var = value;
}
Variant(Vector && value)
{
var = std::move(value);
}
Variant(int value)
{
var = value;
}
std::variant<Vector, int> var;
};
int main()
{
Variant::Vector v{Variant::Vector{10, 20}};
std::cout << "v size: " << v.size() << ", index: " << v.at(0).var.index() << std::endl;
return 0;
}
【问题讨论】:
-
fyi vs2022 说'v size: 2, index: 1'
-
这意味着VS2022的行为和clang一样
-
那肯定是有人错了,或者你的代码有 UB。
-
FWIW,MSVC 和 clang-cl 都 仅 调用带有
int参数的普通构造函数(两次)。但是 GCC 然后调用你的移动构造函数。 compiler explorer