C2280 = попытка сослаться на удаленную функцию - PullRequest
0 голосов
/ 06 августа 2020

Я вижу, что есть еще один пост с почти таким же названием, прочитав его, я не понимаю ответа, может ли кто-нибудь мне помочь?

У меня есть проект, который изначально был разработан с использованием MSV C 2008, мне было поручено перенести его на MSV C 2017.

Я получаю следующую ошибку:

Severity    Code    Description Project File    Line    Suppression State
Error   C2280   'Fraenkel::CommandDataField &Fraenkel::CommandDataField::operator =(const Fraenkel::CommandDataField &)': attempting to reference a deleted function    Master Communications Service Group c:\fraenkelsoftware-millikan\core\service groups\master communications\code\command.cpp 125 

Это функция, которая встречается в:

bool Command::getParameter(Fraenkel::CommandDataFieldIndex pos, Fraenkel::CommandDataField& param) const
{
    // lock our list
    std::lock_guard<std::mutex> lock(m_parametersMutex);

    if (pos >= m_parameters.size())
    {
        return false;
    }
    param = m_parameters[pos]; //This is line 125
    return true;
}

Fraenkel - это пространство имен, CommandDataField - это класс:

    class CommandDataField
    {
    public:
        /// Default c'tor
        CommandDataField(void) {}
        /// Default d'tor. No clean up is required.
        ~CommandDataField(void) {}
        /// Copy constructor. Forwards to the universal constructor.
        CommandDataField(const CommandDataField& source) : CommandDataField(source.m_val) {}
        /// Move constructor. Forwards to the universal constructor.
        CommandDataField(CommandDataField&& source) : CommandDataField(std::move(source.m_val)) {}
        /// Constructor from byte vector. Forwards to ByteArray.
        CommandDataField(std::vector<uint8_t> source) : CommandDataField(ByteArray(std::move(source))) {}
        /// Templated c'tor. Sets the variant with the given value.
        /// Note that T&& here is what Scott Myers calls a "universal reference".
        /// You can't reliably overload a function once you've got a universal
        /// reference in the mix, for reasons which are too involved to go into
        /// here. So following a suggestion of Myers, we forward rvalue and lvalue
        /// references separately to private constructors and do the specialisation
        /// there.
        template<typename T> explicit CommandDataField(T&& t) : CommandDataField(std::forward<T>(t), std::is_rvalue_reference<T&&>()) {}

        /// Test whether the command data field is of a given type.
        /// \return True if held variant's type matches the template argument
        template<typename T>
        bool isType(void) const
        {
            return (which() == CDFIndexOf<T>::value);
        }

        /// Test whether the command data field is of the same type as some other.
        /// \param other Another CommandDataField to check
        /// \return True if the two command data fields contain the same type
        bool isType(const CommandDataField& other) const
        {
            return (which() == other.which());
        }

        /// Array and scalar conversion are sufficiently different that we can't
        /// specialise directly, but we can dispatch through a mini-traits class.
        template<typename T> struct Getter
        {
            static T get(const CommandDataField& cdf) { return cdf.get_s<T>(); }
        };
        /// It is sometimes convenient to get the CommandDataField itself as a
        //  no-op.
        template<> struct Getter<CommandDataField>
        {
            static CommandDataField get(const CommandDataField& cdf) { return cdf; }
        };
        /// Variant list is really a scalar, since it corresponds to the value
        /// stored directly in the data field.
        template<> struct Getter<CDFVariantList>
        {
            static CDFVariantList get(const CommandDataField& cdf) { return cdf.get_s<CDFVariantList>(); }
        };
        /// And the vector version.
        template<typename T> struct Getter<std::vector<T> >
        {
            static std::vector<T> get(const CommandDataField& cdf) { return cdf.get_v<T>(); }
        };
        /// Generic get method that works with array or scalar parameters.
        template<typename T> T get(void) const { return Getter<T>::get(*this); }

        /// get template method returns the value of the variant.
        /// \return The value of the variant
        template <typename T>
        T get_s(void) const
        {
            if (typeid(T) != m_val.type())
            {
                throw std::logic_error("CommandDataField: wrong type for get");
            }
            const T *pX = boost::get<T>(&m_val);
            return *pX;
        }

        /// Specialisation of get() for array types. WARNING slow for large arrays.
        template<typename T> std::vector<T> get_v(void) const
        {
            const CDFVariantList* vs = boost::get<CDFVariantList>(&m_val);
            assert(vs != nullptr);
            std::vector<T> result;
            result.reserve(vs->size());
            for (auto const& v : *vs)
            {
                const T* val = boost::get<T>(&v);
                assert(val != nullptr);
                result.push_back(*val);
            }
            return result;
        }


        /// Set template method changes the value of the variant.
        /// \param t Data to set. Must be one of the variant's supported types.
        template <typename T> void set(const T& t) { m_val = t; }

        /// returns the size of the stored array (and will assert if there is no array stored)
        /// \return size
        size_t getArraySize(void) const
        {
            assert(m_val.type() == typeid(ByteArray));
            return get_s<ByteArray>().size();
        }

        /// Overload of set for handling lumps of binary data
        /// which we will treat as lists of uint8_t's
        /// \param pData Pointer to binary data
        /// \param size Size in bytes of pData
        void set(const uint8_t* pData, const size_t size)
        {
            ByteArray temp(size);
            memcpy(temp.m_data.data(), pData, size);
            m_val = std::move(temp);
        }

        /// Specialisation for array types (slow for large arrays)
        template<typename T> void set(const std::vector<T>& t)
        {
            CDFVariantList temp;
            temp.reserve(t.size());
            std::copy(t.begin(), t.end(), std::back_inserter(temp));
            m_val = temp;
        }

        /// Uber-specialisation for CDFVariantList, which can be set directly.
        void set(const CDFVariantList& t) { m_val = t; }
        /// Move version of the variant-list setter.
        void set(CDFVariantList&& t) { m_val = std::move(t); }

        /// Comparison operator: compares the underlying variants.
        /// Boost will provide operator!= automatically thanks to the
        /// equality_comparable template.
        /// \param  rhs Comparand.
        /// \return true if the two fields are equal (type and value).
        bool operator==(const CommandDataField& rhs) const
        {
            return (m_val == rhs.m_val);
        }

        /// Provides a means of accessing the underlying variant so that the visitor
        /// pattern can be used. See boost::apply_visitor.
        /// \param visitor A boost::static_visitor
        /// \return Visitor-appropriate return value
        template <typename Visitor>
        typename Visitor::result_type applyVisitor(Visitor& visitor) const
        {
            return boost::apply_visitor(visitor, m_val);
        }
        /// Visitor, const version.
        /// \param visitor A boost::static_visitor
        /// \return Visitor-appropriate return value
        template<typename Visitor>
        typename Visitor::result_type applyVisitor(const Visitor& visitor) const
        {
            return boost::apply_visitor(visitor, m_val);
        }

    private:
        /// Generic constructor for lvalue references; copies into the underlying
        /// variant.
        template<typename T> explicit CommandDataField(const T& t, std::false_type) : m_val(t) {}
        /// Generic constructor for rvalue references; moves into the underlying
        /// variant.
        template<typename T> explicit CommandDataField(T&& t, std::true_type) : m_val(std::forward<T>(t)) {}
        /// Vector constructor; forwards to set().
        template<typename T> explicit CommandDataField(const std::vector<T>& v, std::false_type) { set(v); }
        /// Rvalue vector constructor; forwards to set() (this won't be any
        /// different from the lvalue version except in the case of a variant list,
        /// which can be set directly).
        template<typename T> explicit CommandDataField(std::vector<T>&& v, std::true_type) { set(std::move(v)); }
        /// Alternative copy constructor for copy operations that were erroneously
        /// caught by the universal constructor, because C++.
        explicit CommandDataField(const CommandDataField& rhs, std::false_type) : m_val(rhs.m_val) {}
        /// Get the type as an index into the list. Not for user consumption: is
        /// used for type checking.
        /// \return The list index of the given variant type
        int which(void) const { return m_val.which(); }

        CDFVariant m_val; ///< The variant that this class wraps.
    };

1 Ответ

4 голосов
/ 06 августа 2020

Похоже, вы добавили конструктор перемещения к этому типу как часть этого портирования. Неявный оператор присваивания копии удаляется, если вы объявляете конструктор перемещения.

Если стандартная реализация поэлементного копирования приемлема, вы можете просто восстановить этот оператор:

CommandDataField & operator=(CommandDataField const &) = default;

Однако вы не нужно этого делать - вам даже не нужно объявлять свои конструкторы копирования / перемещения, поскольку реализация по умолчанию, по-видимому, хорошо сформирована! Ваша реализация выполняет поэлементное копирование / перемещение, что и делает созданный компилятором. Следовательно, простое удаление конструкторов копирования и перемещения из типа должно решить проблему.

Компилятор сгенерирует для вас конструкторы копирования / перемещения и операторы присваивания копирования / перемещения, и все они должны поступай правильно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...