boost::变体对仅移动类型的处理中的奇怪行为

Strange behavior in boost::variant's handling of move-only types

本文关键字:处理 类型 移动 boost      更新时间:2023-10-16

给定以下情况:

#if __cplusplus >= 201703L
    #include <variant>
    using std::variant;
#else
    #include <boost/variant.hpp>
    using boost::variant;
#endif

考虑这个片段。这在C 17的std::variant<>boost::variant<>

下编译
struct B
{
    B() = default;
    B(const B&) = delete;
    B(B&&) {}
    B& operator=(const B&&) = delete;
    B& operator=(B&&) {}
};
int main()
{
    variant<B, int> v;
    v = B{};
}

但是,另一个示例仅使用C 17的std::variant<>编译,因为boost::variant<>尝试执行复制分配。

struct A
{
    A(int) {}
};
struct B
{
    B(int) {}
    B(const B&) = delete;
    B(B&&) {}
    B& operator=(const B&) = delete;
    B& operator=(B&&) {}
};
int main()
{
    variant<A, B> v{A{42}};
    v = B{42}; // This line doesn't compile with Boost
}

两个示例之间唯一值得注意的区别是struct A和默认构造函数的存在与服用int的构造函数。我还发现,如果第二种情况下class B的移动构造函数和分配运算符是= default ED,则可以使用Boost进行编译。我是做错了什么还是这是boost.variant的问题?尝试使用Boost 1.65和GCC 7.2.0的两个示例。

问题是move-constructor并不是不适合的,这使其不合适:

https://godbolt.org/g/368cjj

B(B&&) noexcept {};

您也可以写:

B(B&&) = default;

在这种情况下,编译器隐式生成noexcept移动构造函数。