移动向量元素的分配不起作用,而是调用复制分配

Move Assignment of a Vector Element not working, Copy Assignment is called instead

我有一个 class 不可默认构造、不可复制构造或不可复制分配。它是可移动构造和可移动分配的。

struct SG_MotionState {
    frameId_t frameId;
    btTransform transform;
    vector<sgCustomFieldData_t> mCustomFields;
    sgCustomFieldLayout_t & mLayout;
    
    SG_MotionState (sgCustomFieldLayout_t & _mLayout) : mLayout(_mLayout) {}
    // Disable copy
private: // No copying allowed!
    SG_MotionState& operator = (const SG_MotionState & other);
    SG_MotionState(const SG_MotionState & other);
public: // Only moving
    inline SG_MotionState(SG_MotionState&& other) noexcept = default;
    inline SG_MotionState& operator = (SG_MotionState&& other) noexcept = default;

   ... // Impl
}

我将此 class 的实例存储在 std::vector:

data.push_back(std::move(t));

稍后我想替换数组中的值,丢弃原始值。但是当我尝试时:

data[position] = std::move(t);

编译器 (g++ 10.2) 尝试调用复制分配 SG_MotionState& operator = (const SG_MotionState & other) 而不是调用移动分配 SG_MotionState& operator = (SG_MotionState&& other)。我如何对 std::vector 元素进行移动分配?

容器相关部分class:

template<typename T, uint MAX_SIZE>
class t2_ringbuffer {
public:
    /// Stores an item in a container that grows in size
    /// until a maxiumum is reached, thereafter it overrides old values
    std::vector<T> data;
    uint zeroIndex;
    
    t2_ringbuffer() : zeroIndex(0) {}
    
    void push_back(T && t) { // Move semantics version
        if (data.size() < MAX_SIZE)
            data.push_back(std::move(t));
        else {
            data[zeroIndex] = std::move(t);
            
            zeroIndex++;
            if (zeroIndex >= MAX_SIZE)
                zeroIndex = 0;
            
            }
        }
   ... // more impl
   }

编辑: 这是准确的错误消息:

temp/rsserver/dataStructures/ringbuffer.hpp: In instantiation of ‘void t2_ringbuffer<T, MAX_SIZE>::push_back(T&&) [with T = SG_MotionState; unsigned int MAX_SIZE = 60]’:
temp/rsserver/sgNode.cpp:550:40:   required from here
temp/rsserver/dataStructures/ringbuffer.hpp:30:20: error: ‘SG_MotionState& SG_MotionState::operator=(const SG_MotionState&)’ is private within this context
   30 |    data[zeroIndex] = std::move(t);
      |    ~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~

编辑 2:class 的属性:

is_constructible: false
is_trivially_constructible: false
is_copy_constructible: false
is_nothrow_copy_constructible: false
is_move_constructible: true
is_nothrow_move_constructible: true

编辑 3:最小示例: https://godbolt.org/z/WWorP1

您的问题在于缺少移动赋值运算符。 看你的class,你默认了这个操作

不幸的是,= default 意味着您获得默认行为,而不是创建此方法。这真是令人困惑。

为了更容易发现这一点,我最近在我正在处理的代码库中启用了以下 clang 警告作为错误:https://clang.llvm.org/docs/DiagnosticsReference.html#wdefaulted-function-deleted (也许 GCC 有类似的东西)

长话短说,如果您的基础 class 或成员不允许此操作,则您的 class 不能默认此操作。

在这种情况下,您有一个引用作为成员,因为不能重新分配引用,也不能提供赋值运算符。

可能的解决方法是:存储为原始指针,或存储为 std:: reference_wrapper

PS:请将您删除的方法 public 并使用 = delete,它会给出更好的错误消息