Компилятор вызывает оператор копирования вместо оператора перемещения - PullRequest
2 голосов
/ 30 января 2020

Я нашел точный вопрос здесь заранее, но у меня нет той же причины проблемы (или, по крайней мере, я так думаю). Мой класс AnimatedSprite имеет член Timer, который не подлежит копированию (явно удалены как копия ctor, так и operator =). Тем не менее, когда я пытаюсь инициализировать спрайт в ctor другого класса, я получаю сообщение об ошибке, в котором говорится, что я ссылаюсь на оператор удаленного копирования =.

Timer.h:

#pragma once
#include <set>

class Timer
{
public:
    Timer() :
        currentTime_{0},
        expirationTime_{0}
    {}
    Timer(unsigned expirationTime) :
        currentTime_{ expirationTime },
        expirationTime_{ expirationTime }
    {
        timers_.insert(this);
    }

    ~Timer() {
        timers_.erase(this);
    }
    // Here
    Timer(const Timer& other) = delete;
    Timer& operator=(const Timer& other) = delete;

    Timer(Timer&& other) = default;
    Timer& operator=(Timer&& other) = default;


    //   Assumes the user knows if |this| is active or not
    unsigned currentTime() const { return currentTime_; }

    bool active() const { return currentTime_ < expirationTime_; }
    bool expired() const { return !active(); }
    void reset() { currentTime_ = 0; }
    void disable() { currentTime_ = expirationTime_; }


    static void updateAll(unsigned elapsedTime);

private:

    void update(unsigned elapsedTime) {
        if (active()) {
            currentTime_ += elapsedTime;
        }
    }


    static std::set<Timer*> timers_;
    unsigned currentTime_;
    const unsigned expirationTime_;

};

AnimatedSprite. h

#pragma once
#include <vector>
#include <map>
#include "Globals.h"
#include "Sprite.h"
#include "Timer.h"


class Sprite;
class Graphics;

class AnimatedSprite : public Sprite
{
public:
    AnimatedSprite() = default;
    AnimatedSprite(Graphics& graphics, const std::string& filePath,
        int sourceX, int sourceY, int width, int height,
        unsigned frameLength, unsigned frameCount);

    void update(bool once = false);
    const bool completedOnce() const { return once_; }

private:

    Timer frameTimer_;
    unsigned currentFrame_{ 0 };
    unsigned totalFrames_;
    bool once_{ false };    //  if true, plays animation once
};

И тогда я делаю это:

sprite_ = AnimatedSprite( graphics, "Resource/NpcSym.png", 0, 1, 16, 16, 50, 5 );

Разве здесь не должен вызываться оператор перемещения? Разве моя RHS не находится в строке выше значения?

1 Ответ

4 голосов
/ 30 января 2020

Что-то в вашем AnimatedSprite мешает его подвижности. Как только это устранено, оно пытается скопировать. И вы получите свою ошибку.

Возможно, что-то в Sprite блокирует его перемещение. Или что-то в Timer; =default может стать =delete, если вы не можете переместить вещь.

Одна из техник, которую я использую, заключается в том, чтобы ввести stati c о таких предположениях.

static_assert( std::is_move_assignable<Sprite>{}, "Cannot move Sprite" );
static_assert( std::is_move_constructible<Sprite>{}, "Cannot move Sprite" );
static_assert( std::is_move_assignable<Timer>{}, "Cannot move Timer" );
static_assert( std::is_move_constructible<Timer>{}, "Cannot move Timer" );

Теперь, используя мой я вижу:

const unsigned expirationTime_;

заблокирует назначение перемещения на Timer.

Резервное копирование в дизайн:

sprite_ = AnimatedSprite( graphics, "Resource/NpcSym.png", 0, 1, 16, 16, 50, 5 );

делает это имеет смысл назначить один текущий анимирующий спрайт поверх другого?

Я сомневаюсь в этом.

Я бы =delete operator=(&&).

Заменить sprite_ с std::optional<AnimatedSprite> и выполните:

sprite_.emplace( graphics, "Resource/NpcSym.png", 0, 1, 16, 16, 50, 5 );

, что часто намного более разумно, чем наличие "спрайта, который находится в состоянии, которое не является спрайтом".

...