【问题标题】:No viable overloaded '=' on a c++ programc++ 程序上没有可行的重载'='
【发布时间】:2015-06-26 04:04:27
【问题描述】:

我有一些 C++ 代码来查找 xml 和打印中的差异,使用地图重命名节点标签。这是完整的代码:

#include "pugi/pugixml.hpp"

#include <iostream>
#include <string>
#include <map>

int main()
{
    // Define mappings, default left - map on the right
    const std::map<std::string, std::string> tagmaps
    {
        {"id", "id"}, {"description", "content"}
    };

    pugi::xml_document doca, docb;
    pugi::xml_node found, n;
    std::map<std::string, pugi::xml_node> mapa, mapb;

    if (!doca.load_file("a.xml") || !docb.load_file("b.xml")) { 
        std::cout << "Can't find input files";
        return 1;
    }

    for (auto& node: doca.child("data").children("entry")) {
        const char* id = node.child_value("id");
        mapa[id] = node;
    }

    for (auto& node: docb.child("data").children("entry")) {
    const char* idcs = node.child_value("id");
        if (!mapa.erase(idcs)) {
            mapb[idcs] = node;
        }
    }

    for (auto& ea: mapa) {
        std::cout << "Removed:" << std::endl;
        ea.second.print(std::cout);
        // CURL to remove entries from ES
    }

    for (auto& eb: mapb) {
        // change node name if mapping found
        found = tagmaps.find(n.name());
        if((found != tagmaps.end()) {
        n.set_name(found->second.c_str());
        }
    }

}

这是我尝试编译时遇到的错误。我是 C++ 新手,我很难修复它。任何帮助或意见将不胜感激。

src/main.cpp:49:8: error: no viable overloaded '='
        found = tagmaps.find(n.name());

【问题讨论】:

    标签: c++ c++11


    【解决方案1】:

    那是因为你分配了错误的类型:

    found = tagmaps.find(n.name());
    

    std::map&lt;K,V&gt;::find const 返回一个std::map&lt;K,V&gt;::const_iterator,并且pugi::xml_node 没有赋值运算符在右侧接受这样的事情。

    您需要使found 的类型正确:

    std::map<std::string, std::string>::const_iterator found = tagmaps.find(n.name());
    

    或者,如果 C++11,强烈首选:

    auto found = tagmaps.find(n.name());
    

    实际上,查看xml_node 的引用,我根本没有看到任何operator=...

    【讨论】:

    • 感谢巴里的回复。虽然你帮助我理解了这个问题,但我不太清楚我如何前进。 xml_node上应该有赋值运算符的问题吗?
    • @JamesWillson 不。只是你误解了这个类的使用方式。您不创建xml_nodes。图书馆里的其他东西给你。例如,给定xml_node pp.child("James") 会给你相应的孩子xml_node。我会阅读参考资料。
    • 我对此并不擅长,但我已尝试阅读。我正在尝试查找该标签是否存在,如果存在,请重命名它。因此,这段代码 sn-p 是否更接近我应该使用的代码? pugi::xml_node xclient = xjack.child(sclient.c_str()); 我从这里得到的 stackoverflow.com/questions/17355024/…
    • 这是我得到检查代码的地方:stackoverflow.com/a/29730037/2729481
    • @JamesWillson 您只需要使found 具有正确的类型。要么完全拼写const_iterator 类型,要么使用auto
    【解决方案2】:

    注意:这更像是一个扩展评论,而不是对您提出的问题的直接回答。

    至少如果我猜对了意图,这段代码:

    for (auto& node: doca.child("data").children("entry")) {
        const char* id = node.child_value("id");
        mapa[id] = node;
    }
    
    for (auto& node: docb.child("data").children("entry")) {
    const char* idcs = node.child_value("id");
        if (!mapa.erase(idcs)) {
            mapb[idcs] = node;
        }
    }
    

    ...旨在将两组对象的交集生成mapa,并将两组对象的差异生成mapb。既然如此,我宁愿更直接地表达这些意图:

    auto by_id = [](pugi::xml_node const &a, pugi::xml_node const &b) {
        return strcmp(a.get_child("id"), b.get_child("id")) == 1;
    };
    
    auto const &a = doca.child("data").children("entry");
    auto const &b = docb.child("data").children("entry");
    
    std::set_intersection(a.begin(), a.end(), 
                          a.begin(), b.end(),
                          std::inserter(mapa, mapa.end()),
                          by_id);
    
    std::set_difference(a.begin(), a.end(),
                        b.begin(), b.end(),
                        std::inserter(mapb, mapb.end()),
                        by_id);
    

    虽然稍微长了一点,但我认为这更清楚地表达了预期的结果,可以轻松证明额外的长度是合理的。

    至于最初给你带来困难的部分:

    for (auto& eb: mapb) {
        // change node name if mapping found
        found = tagmaps.find(n.name());
        if((found != tagmaps.end()) {
        n.set_name(found->second.c_str());
        }
    }
    

    我承认我对你真正打算实现的目标感到困惑。您遍历mapb,但从不在循环内部使用eb。同时,您搜索n.name(),但您尚未初始化n 以首先实际包含任何内容。

    我猜你真的打算包含以下内容:

    auto &n = eb.second;
    

    ...作为循环内的第一条语句(在这种情况下,您显然根本不需要在循环外定义现有的n)。

    有了这个,我们看到tagmaps 中的部分内容显然是多余的——拥有{"id", "id"} 条目并不会更改这些条目的名称,因此将它放在那里没有任何意义完全没有。

    这给我们留下了:

    const std::map<std::string, std::string> tagmaps {
        {"description", "content"}
    };
    
    // ...
    
    for (auto& eb: mapb) {
        auto &n = eb.second;
        auto found = tagmaps.find(n.name());
        if((found != tagmaps.end()) 
            n.set_name(found->second.c_str());
    }
    

    至少对我来说,这看起来至少有一些机会做一些至少有点有用的事情。这可以更改为使用std::transform,但我怀疑你会获得很多(如果有的话),但这样做。

    【讨论】:

    • 非常感谢您提供所有这些信息。我需要一段时间才能理解和理解,但我非常感谢您的帮助。
    【解决方案3】:

    巴里是对的。您正在声明 found 不是它。我认为您只需要删除顶部的声明并编写

    auto found = tagmaps.find(n.name());
    

    【讨论】:

      猜你喜欢
      • 2015-06-27
      • 2018-08-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-03-01
      • 2020-10-16
      • 1970-01-01
      相关资源
      最近更新 更多