C ++ / XCode - 类型' const double'的绑定值引用类型' double'滴' const'预选赛

时间:2017-11-26 04:53:41

标签: c++ xcode

我已经将节点类和序列类实现为模板类。他们的测试程序运行良好,但是当我尝试使用我提供的测试程序时,我收到了这个错误。

类型' const double'的绑定值引用类型' double'滴' const'限定符

错误指向我代码中的几个不同位置:

在main.cpp中,它指向下面的if语句:

if (*itr != i)
        {
            // Our iterators have not ended with us on the correct value.
            cout << "\nIncorrect value found.\n";
            cout << "Expected: " << i << ". Found: " << *itr << "." << endl;
            return 0;
        }

在node2.h中,它指向下面的return语句:

Item& operator *( ) 
    { return current->data( ); }

我已经包含了我的node2.h和node2.cxx。我不能100%确定这个错误意味着什么以及它如何适用于我的程序。非常感谢任何帮助。

node2.h:

#ifndef COEN_79_NODE_H
#define COEN_79_NODE_H
#include <cstdlib> // Provides size_t and NULL
#include <iterator>
#include <cassert>


namespace coen79_lab8
{
    template <class Item>
    class node
    {
    public:
        // TYPEDEF
        typedef Item value_type;

        // CONSTRUCTOR
        node(const Item& init_data = Item( ), node* init_link = NULL)
        {
            data_field = init_data;
            link_field = init_link;
        }

        // Member functions to set the data and link fields:
        void set_data(const Item& new_data) { data_field = new_data; }
        void set_link(node* new_link) { link_field = new_link; }

        // Constant member function to retrieve the current data:
        const Item& data( ) const { return data_field; }

        // Two slightly different member functions to retreive
        // the current link:
        const node* link( ) const { return link_field; }
        node* link( ) { return link_field; }

    private:
        Item data_field;
        node* link_field;
    };

    // FUNCTIONS for the linked list toolkit
    template <class Item>
    size_t list_length(const node<Item>* head_ptr);

    template <class Item>
    void list_head_insert(node<Item>*& head_ptr, const Item& entry);

    template <class Item>
    void list_insert(node<Item>* previous_ptr, const Item& entry);

    template <class NodePtr, class Item>
    NodePtr list_search(NodePtr head_ptr, const Item& target);

    template <class NodePtr, class SizeType>
    NodePtr list_locate(NodePtr head_ptr, SizeType position);

    template <class Item>
    void list_head_remove(node<Item>*& head_ptr);

    template <class Item>
    void list_remove(node<Item>* previous_ptr);

    template <class Item>
    void list_clear(node<Item>*& head_ptr);

    template <class Item>
    void list_copy(const node<Item>* source_ptr, node<Item>*& head_ptr, node<Item>*& tail_ptr);
    // YOU NEED TO IMPLEMENT THE FOLLOWING FUNCTIONS

    template <class NodePtr, class Item>
    void list_piece(NodePtr start_ptr, NodePtr end_ptr, node<Item>*& head_ptr, node<Item>*& tail_ptr);

    template <class Item>
    size_t list_occurrences(node<Item>* head_ptr, const Item& target);

    template <class Item>
    void list_insert_at(node<Item>*& head_ptr, const Item& entry, size_t position);

    template <class Item>
    Item list_remove_at(node<Item>*& head_ptr, size_t position);

    template <class NodePtr, class Item>
    NodePtr list_copy_segment(node<Item>* head_ptr, size_t start, size_t finish);

// FORWARD ITERATORS to step through the nodes of a linked list
// A node_iterator of can change the underlying linked list through the
// * operator, so it may not be used with a const node. The
// node_const_iterator cannot change the underlying linked list
// through the * operator, so it may be used with a const node.
// WARNING:
// This classes use std::iterator as its base class;
// Older compilers that do not support the std::iterator class can
// delete everything after the word iterator in the second line:


//You need to change these to template classes and implement the functions for these classes

template <class Item>
class node_iterator
: public std::iterator<std::forward_iterator_tag, Item>
{
public:
    node_iterator(node<Item>* initial = NULL)
    { current = initial; }
    Item& operator *( ) 
    { return current->data( ); }
    node_iterator& operator ++( )
    {
        current = current->link( );
        return *this;
    }
    node_iterator operator ++(int)
    {
        node_iterator original(current);
        current = current->link( );
        return original;
    }
    bool operator ==(const node_iterator other) const
    { return current == other.current; }
    bool operator !=(const node_iterator other) const
    { return current != other.current; }
private:
    node<Item>* current;
};

template <class Item>
class const_node_iterator
: public std::iterator<std::forward_iterator_tag, const Item>
{
public:
    const_node_iterator(const node<Item>* initial = NULL)
    { current = initial; }
    const Item& operator *( ) const
    { return current->data( ); }
    const_node_iterator& operator ++( )
    {
        current = current->link( );
        return *this;
    }
    const_node_iterator operator ++(int) 
    {
        const_node_iterator original(current);
        current = current->link( );
        return original;
    }
    bool operator ==(const const_node_iterator other) const
    { return current == other.current; }
    bool operator !=(const const_node_iterator other) const
    { return current != other.current; }

    private:
        const node<Item>* current;
    };
}
#include "node2.cxx"
#endif

node2.cxx:

// FILE: node.cxx
// IMPLEMENTS: The functions of the node class and the
// linked list toolkit (see node2.h for documentation).
// INVARIANT for the node class:
//   The data of a node is stored in data_field
//   and the link to the next node is stored in link_field.

#include <cassert>    // Provides assert
#include <cstdlib>    // Provides NULL and size_t

namespace coen79_lab8
{
    template <class Item>
    size_t list_length(const node<Item>* head_ptr)
    // Library facilities used: cstdlib
    {
        const node <Item> *cursor;
        size_t answer;

        answer = 0;
        for (cursor = head_ptr; cursor != NULL; cursor = cursor->link( ))
            ++answer;

        return answer;
    }

    template <class Item>
    void list_head_insert(node<Item>*& head_ptr, const Item& entry)
    {
        head_ptr = new node<Item>(entry, head_ptr);
    }

    template <class Item>
    void list_insert(node<Item>* previous_ptr, const Item& entry)
    {
        node<Item> *insert_ptr;

        insert_ptr = new node<Item>(entry, previous_ptr->link( ));
        previous_ptr->set_link(insert_ptr);
    }

    template <class NodePtr, class Item>
    NodePtr list_search(NodePtr head_ptr, const Item& target)
    // Library facilities used: cstdlib
    {
        NodePtr cursor;

        for (cursor = head_ptr; cursor != NULL; cursor = cursor->link( ))
            if (target == cursor->data( ))
                return cursor;
        return NULL;
    }

    template <class NodePtr, class SizeType>
    NodePtr list_locate(NodePtr head_ptr, SizeType position)
    // Library facilities used: cassert, cstdlib
    {
        NodePtr cursor;
        SizeType i;

        assert(0 < position);
        cursor = head_ptr;
        for (i = 1; (i < position) && (cursor != NULL); ++i)
            cursor = cursor->link( );
        return cursor;
    }

    template <class Item>
    void list_head_remove(node<Item>*& head_ptr)
    {
        node<Item> *remove_ptr;

        remove_ptr = head_ptr;
        head_ptr = head_ptr->link( );
        delete remove_ptr;
    }

    template <class Item>
    void list_remove(node<Item>* previous_ptr)
    {
        node<Item> *remove_ptr;

        remove_ptr = previous_ptr->link( );
        previous_ptr->set_link(remove_ptr->link( ));
        delete remove_ptr;
    }

    template <class Item>
    void list_clear(node<Item>*& head_ptr)
    // Library facilities used: cstdlib
    {
        while (head_ptr != NULL)
            list_head_remove(head_ptr);
    }

    template <class Item>
    void list_copy(const node<Item>* source_ptr, node<Item>*& head_ptr, node<Item>*& tail_ptr)
    // Library facilities used: cstdlib
    {
        head_ptr = NULL;
        tail_ptr = NULL;

        // Handle the case of the empty list
        if (source_ptr == NULL)
            return;

        // Make the head node for the newly created list, and put data in it
        list_head_insert(head_ptr, source_ptr->data( ));
        tail_ptr = head_ptr;

        // Copy rest of the nodes one at a time, adding at the tail of new list
        source_ptr = source_ptr->link( );
        while (source_ptr != NULL)
        {
            list_insert(tail_ptr, source_ptr->data( ));
            tail_ptr = tail_ptr->link( );
            source_ptr = source_ptr->link( );
        }
    }

    template <class NodePtr, class Item>
    void list_piece(const NodePtr start_ptr, const NodePtr end_ptr, node<Item>*& head_ptr, node<Item>*& tail_ptr)
    {
        head_ptr = NULL;
        tail_ptr = NULL;
        // Handle the case of the empty list.
        if (start_ptr == NULL)
        {
            return;
        }
        // Make the head node for the newly created list, and put data in it.
        list_head_insert(head_ptr, start_ptr->data( ));
        tail_ptr = head_ptr;
        // Copy the rest of the nodes one at a time, adding at the tail of new list.
        start_ptr = start_ptr->link( );
        while (start_ptr != end_ptr)
        {
            list_insert(tail_ptr, start_ptr->data( ));
            tail_ptr = tail_ptr->link( );
            start_ptr = start_ptr->link( );
        }
        return;
    }

    template <class Item>
    size_t list_occurrences(node<Item>* head_ptr, const Item& target)
    {
        size_t answer = 0;

        for (head_ptr = list_search(head_ptr, target);
             head_ptr != NULL;
             head_ptr = list_search(head_ptr->link(), target))
        answer++;

        return answer;
    }

    template <class Item>
    void list_insert_at(node<Item>*& head_ptr, const Item& entry, size_t position)
    {
        assert(position > 0);
        node<Item> *precursor;

        if (position == 1)
           list_head_insert(head_ptr, entry);
        else
        {
            precursor = list_locate(head_ptr, position-1);
            assert(precursor != NULL);
            list_insert(precursor, entry);
        }
    }

    template <class Item>
    Item list_remove_at(node<Item>*& head_ptr, size_t position)
    {
        assert(position > 0);
        node<Item> *precursor;
        Item answer;

        if (position == 1)
        {
            assert(head_ptr != NULL);
            answer = head_ptr->data();
            list_head_remove(head_ptr);
        }
        else
        {
            precursor = list_locate(head_ptr, position-1);
            assert(precursor != NULL);
            assert(precursor->link() != NULL);
            answer = precursor->link()->data();
            list_remove(precursor);
        }
        return answer;
    }

    template <class NodePtr, class Item>
    NodePtr list_copy_segment(node<Item>* head_ptr, size_t start, size_t finish)
    {
        node<Item> *start_ptr;
        node<Item> *finish_ptr;
        node<Item> *new_head;
        node<Item> *new_tail;

        assert((1 <= start) && (start <= finish) && (finish <= list_length(head_ptr)));
        ++finish;


        start_ptr = list_locate(head_ptr, start);
        assert(start_ptr != NULL);
        finish_ptr = list_locate(start_ptr, finish-start+1);
        list_piece(start_ptr, finish_ptr, new_head, new_tail);
        return new_head;
    }
}

1 个答案:

答案 0 :(得分:1)

关键是这一行:

collections.defaultdict

在此声明data()方法返回对Item的const引用。由于您要返回引用,因此您不会复制该项,而是可以访问变量data_field。通常,如果您可以访问此数据,则可以对其进行修改。但是,您将引用声明为const引用,这意味着您禁止对其进行修改。

到目前为止这很好,但是你有了这个:

from collections import defaultdict

d = {k : type(v) for k, v in builtins.__dict__.items()}

d2 = defaultdict(list)    
for k, v in d.items():
    d2[v].append(k)

这将返回一个普通引用,而不是一个const引用,这意味着您说它可以被修改。但是current-&gt; data()返回一个const&amp;,所以这是“删除const限定符”,你违反了你声明data()返回const&amp;时所做的承诺。

有几种可能的解决方案:

  1. 让data()返回引用而不是const&amp; (只需删除const)

  2. 声明operator *()返回一个const Item&amp;而不是项目&amp;

  3. 更改

    const Item& data( ) const { return data_field; }
    

    Item& operator *( ) 
        { return current->data( ); }
    
  4. 这将告诉编译器您是故意丢弃const限定符,而不是抱怨