实施 emplace_back() 二进制“=”时出错:未找到接受 'T *' 类型右手操作数的运算符

Error in implementing emplace_back() binary '=': no operator found which takes a right-hand operand of type 'T *'

下面的代码,用于我的链表实现,特别是下面的 emplace_back。我做错了什么以及如何解决?

我得到的错误是:

Build started...
1>------ Build started: Project: so_list_emplace, Configuration: Debug Win32 ------
1>main.cpp
1list.hpp(191,19): error C2280: 'list<President>::node::node(void)': attempting to reference a deleted function
1>list.hpp(15): message : compiler has generated 'list<President>::node::node' here
1>list.hpp(15,1): message : 'list<President>::node::node(void)': function was implicitly deleted because a data member 'list<President>::node::value' has either no appropriate default constructor or overload resolution was ambiguous
1>list.hpp(12): message : see declaration of 'list<President>::node::value'
1>main.cpp(29): message : see reference to function template instantiation 'void list<President>::emplace_back<const char(&)[15],const char(&)[13],int>(const char (&)[15],const char (&)[13],int &&)' being compiled
1>main.cpp(29): message : see reference to function template instantiation 'void list<President>::emplace_back<const char(&)[15],const char(&)[13],int>(const char (&)[15],const char (&)[13],int &&)' being compiled
1>list.hpp(192,10): error C2679: binary '=': no operator found which takes a right-hand operand of type 'T *' (or there is no acceptable conversion)
1>        with
1>        [
1>            T=President
1>        ]
1>main.cpp(22,13): message : could be 'President &President::operator =(const President &)'
1>list.hpp(190,1): message : while trying to match the argument list '(T, T *)'
1>        with
1>        [
1>            T=President
1>        ]
1>Done building project "so_list_emplace.vcxproj" -- FAILED.

list.hpp 实施:

#ifndef LIST_HPP_
#define LIST_HPP_

#include <cstddef>
#include <initializer_list>
#include <utility>

template< typename T >
class list {
public:
    struct node {
        T value;
        node* next;
        node* prior;
    };

    struct iterator {

        iterator(node* nod) : ptr_(nod) {}

        iterator& operator++() {
            if (ptr_) {
                ptr_ = ptr_->next;
            }
            return *this;
        }

        iterator operator++(T) {
            auto old = *this;
            if (ptr_) {
                ptr_ = ptr_->next;
            }
            return old;
        }

        T& operator*() const { return ptr_->value; }
        T* operator->() { return &ptr_->value;  }

        bool operator==(const iterator& other) { return ptr_ == other.ptr_;  }
        bool operator!=(const iterator& other) { return ptr_ != other.ptr_; }

        node* ptr_;
    };


    list() : head_(nullptr), tail_(nullptr), size_(0) {}

    // O(n)
    template< typename input_iterator >
    list(input_iterator first, input_iterator last) : head_(nullptr), tail_(nullptr), size_(0) {

        for (auto it = first; it != last; ++it) {
            push_back(*it);
        }
    }

    // O(n)
    list(std::initializer_list<T> init) : list<T>(init.begin(), init.end()) {}

    // O(n)
    list(const list& other) : head_(nullptr), tail_(nullptr), size_(0) {
        auto it = other.begin();
        while (it != nullptr) {
            push_back(*it);
            ++it;
        }
        size_ = other.size();
    }

    // O(n)
    list& operator=(const list& other) {
        if (this != &other) {
            clear();
            auto it = other.begin();
            while (it != nullptr) {
                push_back(*it);
                ++it;
            }
            size_ = other.size();
        }
        return *this;
    }

    list(list&& other) : head_(other.head_), tail_(other.tail_), size_(other.size()) {
        other.size_ = 0;
        other.head_ = nullptr;
        other.tail_ = nullptr;
    }

    list& operator=(list&& other) {
        head_ = other.head_;
        tail_ = other.tail_;
        size_ = other.size();

        other.clear();
        other.head_ = nullptr;
        other.tail_ = nullptr;
        other.size_ = 0;
    }

    // O(n)
    ~list() {
        clear();
    }

    // O(n)
    void clear() {
        if (head_) {
            node* current = head_;
            while (current) {
                node* next = current->next;
                delete current;
                current = next;
            }
        }
        head_ = nullptr;
        tail_ = nullptr;
        size_ = 0;
    }

    // O(1)
    bool empty() const {
        return head_ == nullptr;
    }

    // O(1)
    void push_back(const T& value) {

        node* newnode = make_node(value);

        if (tail_) {
            node* oldtail = tail_;
            oldtail->next = newnode;
            newnode->prior = oldtail;
            tail_ = newnode;
        }
        else {
            head_ = tail_ = newnode;
        }
        ++size_;
    }

    // O(1)
    size_t size() const {
        return size_;
    }

    iterator begin() {
        return iterator(head_);
    }
    const iterator begin() const {
        return iterator(head_);
    }

    iterator end() {
        return nullptr;
    }
    const iterator end() const {
        return nullptr;
    }

    // O(1)
    T& front() { return *iterator(head_); }
    const T& front() const { return *iterator(head_); }

    // O(1)
    T& back() { return *iterator(tail_); }
    const T& back() const { return *iterator(tail_); }

    // O(1)
    void pop_back() {
        if (tail_) {
            node* newtail = tail_->prior;
            if (newtail) {
                newtail->next = nullptr;
            }
            else {
                // means that head_ has also been erased
                head_ = nullptr;
            }

            delete tail_;
            tail_ = newtail;
            --size_;
        }
    }

    template<typename... P>
    void emplace_back(P&&... v)
    {
        node* newnode = new node;
        newnode->value = new T(std::forward<P>(v)...);
        newnode->next = nullptr;
        newnode->prior = nullptr;

        if (tail_) {
            node* oldtail = tail_;
            oldtail->next = newnode;
            newnode->prior = oldtail;
            tail_ = newnode;
        }
        else {
            head_ = tail_ = newnode;
        }
        ++size_;
    }

private:
    node* make_node(const T& value) {
        node* newnode = new node;
        newnode->value = value;
        newnode->next = nullptr;
        newnode->prior = nullptr;
        return newnode;
    }

    node* head_;
    node* tail_;
    size_t size_;
};

#endif // LIST_HPP_

main.cpp 锻炼:

#include "list.hpp"

#include <iostream>
#include <string>

struct President
{
    std::string name;
    std::string country;
    int year;

    President(std::string p_name, std::string p_country, int p_year)
        : name(std::move(p_name)), country(std::move(p_country)), year(p_year)
    {
        std::cout << "I am being constructed.\n";
    }
    President(President&& other)
        : name(std::move(other.name)), country(std::move(other.country)), year(other.year)
    {
        std::cout << "I am being moved.\n";
    }
    President& operator=(const President& other) = default;
};

int main() {

    list<President> elections;

    elections.emplace_back("Nelson Mandela", "South Africa", 1994);
}

您的问题是 node 正在尝试构建 President,但 President 没有默认构造函数。你需要构造一个 node 和一个 President,就像在这个构造函数中一样:

node(T const &v) : value(v) { }

因为 emplace_back 尝试就地构造一个对象,您还需要添加一个构造函数来使用传入的参数构造 value

template <typename ...Args>
node(Args &&...v) : value(std::forward<Args>(v)...) { }

最后,更新您的 emplace_back 函数以在构建时转发参数。

node* newnode = new node(std::forward<P>(v)...);

这是用 gcc 和 clang 为我编译的。

问题(反映在错误中)是:

  1. list::node::node()没有默认构造函数,因为它是implicitly deleted.

  2. President 没有默认构造函数,因为您有 用户定义的构造函数 用于 President,因此编译器将 不合成你的默认构造函数。

  3. President没有operator=

解决这些问题你需要添加以下内容:

  1. node 的默认构造函数,例如 node 中的 node() = default();
  2. President 的默认构造函数,例如 President 中的 President() = default;
  3. 定义(重载)President 的赋值运算符。