Привязка к ссылке на классификаторы типов отбрасывает - PullRequest
0 голосов
/ 10 мая 2018

Я имею дело с курсом cpp в моем университете, и я столкнулся с проблемой, которую сам не смог решить.Файл main.cpp предоставляется лектором, и вы должны сделать заголовочный файл для его работы.В этом случае функция

Tedge &operator()(const Tnode &first, const Tnode &sec)

должна вернуть Tedge для перезаписи, но я получаю ошибку

error: binding 'const std::__cxx11::basic_string<char>' to reference of type 'std::__cxx11::basic_string<char>&' discards qualifiers

.Почему это происходит, когда ничего не константно, и как я могу это решить?Когда я удаляю оператор & перед оператором (), он работает, но затем программа не может установить значение переменной.

О, и нам нужно программировать на C ++ 98.

main.cpp

#include "lgraph.h"
#include <iostream>
#include <string>

int main()
{
    int yourMark = 1;

    LGraph<int, std::string, true> dg;
    dg.add(1);
    dg.add(2);
    dg.add(3);
    dg.add(8);
    dg.add(2,1, "Baker street");
    dg.add(1, 3, "Big street");
    dg.add(2, 3, "Small street");
    dg.add(8, 3, "Dog street");
    const LGraph<int, std::string, true> cdg = dg;
    LGraph<char, std::string, false> ug;
    ug.add('A');
    ug.add('G');
    ug.add('H');
    ug.add('A', 'H', "Stackoverflow street");

    yourMark += cdg.is_directed() + ug.is_directed();

    if(!cdg.has("Nowheretobefound") && "Big street" == cdg(1,3)){
        yourMark = ug.countNodes();
    }

    dg(2, 3) = "Flower street";

    std::cout<<dg(2,3) << std::endl;

    if(4 == cdg.countEdges() && !dg.has("Small street")) {
        dg.remove(1);
        yourMark = ug.countEdges() + dg.countNodes();
    }
    std::cout << "Your mark is " << yourMark << std::endl;
    return 0;
}

lgraph.h

#ifndef LGRAPH_H_INCLUDED
#define LGRAPH_H_INCLUDED

#include <vector>
#include <iostream>
#include <map>


template<typename Tnode, typename Tedge, bool isDir>

class LGraph {
    typename std::vector<Tnode> nodes;
    typename std::map<Tedge, std::pair<Tnode, Tnode>> edges;
    bool isdir;
public:
    LGraph():isdir(isDir){};

    void add(Tnode value) {
        nodes.push_back(value);
    }

    void add(Tnode n, Tnode n2, Tedge e) {
        edges.insert(std::pair<Tedge, std::pair<Tnode, Tnode>>(e, std::pair<Tnode, Tnode>(n, n2)));
    }

    bool is_directed() const{
        return isdir;
    }

    bool has(Tedge edge) const{
        bool l = false;
        for(typename std::map<Tedge, std::pair<Tnode, Tnode>>::const_iterator it = edges.begin(); it != edges.end() && !l; it++) {
            l = it -> first == edge;
        }

        return l;
    }

    int countNodes() {
        return nodes.size();
    }

    const Tedge operator()(const Tnode &first, const Tnode &sec) const {
        for(typename std::map<Tedge, std::pair<Tnode, Tnode>>::const_iterator it = edges.begin(); it != edges.end(); it++) {
            if(it->second.first == first && it->second.second == sec) {
                return it->first;
            }
        }
        return nullptr;
    }

    Tedge &operator()(const Tnode &first, const Tnode &sec){
        for(typename std::map<Tedge, std::pair<Tnode, Tnode>>::iterator it = edges.begin(); it != edges.end(); it++) {
            if(it->second.first == first && it->second.second == sec) {
                return it->first;
            }
        }
    }

    const int countEdges() const {
        return edges.size();
    }

    void remove(const Tnode &node) {
        for(int i = 0; i < nodes.size(); i++) {
            if(nodes[i] == node) {
                int currentSize = nodes.size();
                nodes.erase(nodes.begin() + i);
                nodes.resize(currentSize-1);
            }
        }
    }

};

#endif // LGRAPH_H_INCLUDED

1 Ответ

0 голосов
/ 10 мая 2018

std::map делает его ключи неизменяемыми, поэтому ссылки на изменяемые версии его ключей невозможны без нарушения const -корректности.Если вы уверены, что эта версия карты, в которой вы выполняете поиск по значению, верна, то вам нужно будет свернуть свою собственную структуру данных, чтобы этот код работал.

В качестве альтернативы, поскольку у меня возникли трудностиполагая, что это на самом деле правильная версия вашей программы, учтите следующее: во всех случаях, когда вы ищите значения в edges, вы ищете std::string, связанный с двумя Tnode объектами.Кажется довольно ясным, что правильная структура данных для этого кода не std::map<Tedge, std::pair<Tnode, Tnode>>, а std::map<std::pair<Tnode, Tnode>, Tedge>.Tnode в этом случае представляет половину ключа, ищущего объект Tedge, как вы его используете.

Кроме того, вы не можете вернуть nullptr для ссылок.Вам нужно либо сгенерировать исключение, либо предоставить какую-то обработку для представления сценария, в котором вы не можете вернуть объект.

void add(Tnode n, Tnode n2, Tedge e) {
    edges.insert(std::make_pair(std::make_pair(n, n2), e));
}

bool has(Tedge edge) const{
    bool l = false;
    for(typename std::map<Tedge, std::pair<Tnode, Tnode>>::const_iterator it = edges.begin(); it != edges.end() && !l; it++) {
        l = it -> second == edge;
    }

    return l;
}

const Tedge operator()(const Tnode &first, const Tnode &sec) const {
    std::map<std::pair<Tnode, Tnode>, Tedge>::const_iterator it = edges.find(std::pair<Tnode, Tnode>(first, sec));
    if(it != edges.end()) 
        return it-> second;
    else
        throw std::runtime_error("No such element found");
}

Tedge & operator()(const Tnode &first, const Tnode &sec) {
    std::map<std::pair<Tnode, Tnode>, Tedge>::iterator it = edges.find(std::pair<Tnode, Tnode>(first, sec));
    if(it != edges.end()) 
        return it-> second;
    else
        throw std::runtime_error("No such element found");
}

Я не знаю, почему у вас есть ограничение на пребывание вПодмножество C ++ 98 (если это ограничение наложено вашим профессором, значит, ваш профессор не очень хорош в своей работе, я думаю), но если это ограничение можно снять, то вы можете значительно упростить этот код:

void add(Tnode n, Tnode n2, Tedge e) {
    edges.emplace(std::make_pair(n, n2), e);
}

bool has(Tedge const& edge) const{
    for(auto const& entry : edges) 
        if(entry.second == edge) 
            return true;
    return false;
}

const Tedge operator()(const Tnode &first, const Tnode &sec) const {
    if(auto it = edges.find(std::make_pair(first, sec)); it != edges.end())
        return it->second;
    else
        throw std::runtime_error("No such element found");
}

Tedge & operator()(const Tnode &first, const Tnode &sec) {
    if(auto it = edges.find(std::make_pair(first, sec)); it != edges.end())
        return it->second;
    else
        throw std::runtime_error("No such element found");
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...