使用 gcc 和 clang 在 C++ std::vector 构造中的不同行为

Different behaviour in C++ std::vector construction with gcc and clang

在下面的示例中,我期望 v 有 1 个元素,whos var 将是 Vector 类型并且将包含两个“int” Variants 10 和 20。 这是我在 gcc 中看到的行为。

使用 clang,'v' 包含两个元素,即两个“int”Variants 10 和 20。

我认为 gcc 的向量是通过 initializer_list 构造函数创建的,而 clang 的向量是通过移动构造函数创建的

这是某个编译器中的错误吗?我是否需要使 Variant 的构造函数成为 explicit(这将迫使我像 Variant::Vector v{Variant{Variant::Vector{10, 20}}}; 一样使用它。如果我想保留构造函数,是否还有其他方法可以避免此问题不明确?

https://wandbox.org/ and it behaves the same. Here are some links to try it directly: 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;
}

这是CWG 2137,目前只有gcc实现

Clang 错误:https://github.com/llvm/llvm-project/issues/24186

另见 - 这稍微复杂一些,因为初始化列表元素 可从 其参数(被初始化的类型)构造,但诊断一样的,我也做不到比T.C更好的了。的描述:

Clang implemented DR 1467 (brace-initializing a T from a T behaves as if you didn't use braces) but has yet to implement DR 2137 (on second thought, do that only for aggregates).

如果您可以稍微更改程序语法,则可以添加另一层大括号:

Variant::Vector v{{Variant::Vector{10, 20}}};

或加括号:

Variant::Vector v({Variant::Vector{10, 20}});