有没有办法正确地 std::move const 数据?

Mal*_*rog 2 c++ constants rvalue c++14

我的问题是我必须在复制常量数据和移动非常量数据之间做出选择,而且我从概念上看不出为什么在我的情况下将常量数据移动到常量目标是不安全的。我也知道从 const 对象移动是不合逻辑的 - 所以也许还有其他一些方法可以实现我正在尝试做的事情......

我有一个 Builder 类,它设置了一个我不想复制的 BigData 对象。构建器完成后,它会将数据“发出”为常量,因为在此之后不应对其进行修改。构建器是临时的,然后可以被丢弃,但数据应该继续存在,作为可以查询它的包装类中的 const 成员。builder 是一个泛型类型(不知道数据的细节),而 wrapper 是特定于数据内容的。这是通过数据中的类型擦除实现的,但这与此问题无关,只是要明确表示不希望合并构建器和包装器。

以下代码描述了上述内容,除非您删除 BigData 的移动构造函数,否则不会编译。编译错误表明这段代码会复制数据,这是不可取的:

prog.cpp:26:57: 错误:使用已删除的函数 'constexpr BigData::BigData(const BigData&)'
     包装器(const BigData&& In):数据(std::move(In)){}
                                                         ^
class BigData
{
    // Only a builder can create data
    friend class Builder;
    BigData() = default;
public:
    // Move only
    BigData( BigData&& ) = default;
};

class Builder
{
    BigData Data;
public:
    const BigData&& Build() & { return std::move(Data); }
    // Functions to set up data go here
};

class Wrapper
{
    const BigData Data;
public:
    Wrapper( const BigData&& In ) : Data( std::move(In) ) {}
    
    // Functions to query data go here
};

std::unique_ptr<Wrapper> DoBuild()
{
    Builder b;
    // call functions on b to set up data here
    return std::make_unique<Wrapper>( b.Build() );
}
Run Code Online (Sandbox Code Playgroud)

上面的代码也可以在https://ideone.com/tFkVEd找到。

该问题可以通过将 all 更改const BigData&&为 just来解决,BigData&&但我不希望数据在从Build().

最后,这个问题也可以通过从 Build in a 返回数据来解决unique_ptr<const BigData>,并让 Wrapper 拥有它的所有权,但我的问题是指针可以为空,所以 Wrapper 中所有 Data 的使用必须首先检查数据指针是否有效。这就是为什么我想通过右值引用将 const 数据移动到包装器中,也是为什么包装器必须用数据构造。

有什么方法可以实现我想要的,还是遇到了 C++ 的限制?

非常感谢您的投入。

注意:我在尝试自己解决此问题时遇到的相关问题:

Mes*_*kon 5

没有办法std::moveaconst T因为它会改变给定的对象。(除非您创建成员mutable并创建一个T(const T&&)构造函数来执行此操作,我不建议这样做)。

在我看来,更好的解决方案是将所有变异函数设为私有,以便只有构建器可以访问它们,并返回一个T&&.