实现emplace_back()二进制' =':没有发现操作员的错误,该操作员的右手操作数是类型' t *'

发布于 2025-01-18 11:50:55 字数 7653 浏览 3 评论 0原文

下面的代码用于我的链表实现,特别是下面的 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);
}

Code below, for my linked list implementation and specifically emplace_back below. What am I doing wrong and how to fix?

Error I am getting is:

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 implementation:

#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 to exercise:

#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);
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

残花月 2025-01-25 11:50:55

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

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 为我编译的。

Your issue is that node is trying to construct a President, but President doesn't have a default constructor. You'll need to construct a node with a President, like in this constructor:

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

Because emplace_back tries to construct an object in place, you'll also need to add a constructor to construct value using the arguments that are passed in.

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

Lastly, update your emplace_back function to forward arguments at construction time.

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

This is compiling for me with gcc and clang.

ζ澈沫 2025-01-25 11:50:55

问题(如错误中所述)是:

  1. list :: node :: node :: node()没有默认构造函数,因为它是 隐式删除

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

  3. 没有operator = 总统

solve 这些问题您需要添加以下内容:

  1. node喜欢node()= default()= default(); insem ins for node节点
  2. 总统的默认构造函数类似总统()= default; 总统。
  3. 定义(过载)总统的分配操作员。

The problems(as reflected in the errors) are:

  1. There is no default constructor for list::node::node() because it is implicitly deleted.

  2. President has no default constructor because you've user defined constructors for President and so compiler will not synthesize the default constructor for you.

  3. There is no operator= for President.

To solve these problems you need to add the following things:

  1. Default constructor for node like node() = default(); inside node.
  2. Default constructor for President like President() = default; inside President.
  3. Define(overload) the assignment operator for President.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文