【问题标题】:call const overloaded function with std::map of std::shared_ptr用 std::shared_ptr 的 std::map 调用 const 重载函数
【发布时间】:2015-07-18 13:56:45
【问题描述】:

我正在尝试调用 const 重载函数

void process(std::map<std::string,std::shared_ptr<const Data_Struct>>);

使用我生成的数据。因为我生成数据,所以我使用非常量版本

std::map<std::string,std::shared_ptr<Data_Struct>> my_data;

当我尝试调用我的函数时

process(my_data);

我得到错误:

error C2664: 'void process(std::map<std::string,std::shared_ptr<const Data_Struct>,std::less<_Kty>,std::allocator<std::pair<const _Kty,_Ty>>>)' : cannot convert argument 1 from 'std::map<std::string,std::shared_ptr<Data_Struct>,std::less<_Kty>,std::allocator<std::pair<const _Kty,_Ty>>>' to 'std::map<std::string,std::shared_ptr<const Data_Struct>,std::less<_Kty>,std::allocator<std::pair<const _Kty,_Ty>>>'

我尝试了各种铸造变体,但都无法完成工作。任何帮助表示赞赏。

这是我的测试代码,其中包含转换变体和相关的错误代码(我使用的是 Visual C++ 社区版 2013):

struct Data_Struct
{
    int a;
    std::string b;
};

void process(std::map<std::string,std::shared_ptr<const Data_Struct>>);

void calling_function() {
    std::map<std::string,std::shared_ptr<Data_Struct>> my_data;
    my_data.emplace("test",std::shared_ptr<Data_Struct>(new Data_Struct)).first->second->a = 2;
    process(my_data);
        // error C2664: 'void process(std::map<std::string,std::shared_ptr<const Data_Struct>,std::less<_Kty>,std::allocator<std::pair<const _Kty,_Ty>>>)' : cannot convert argument 1 from 'std::map<std::string,std::shared_ptr<Data_Struct>,std::less<_Kty>,std::allocator<std::pair<const _Kty,_Ty>>>' to 'std::map<std::string,std::shared_ptr<const Data_Struct>,std::less<_Kty>,std::allocator<std::pair<const _Kty,_Ty>>>'
    process(std::map<std::string,std::shared_ptr<const Data_Struct>>(my_data));
        // error C2440: '<function-style-cast>' : cannot convert from 'std::map<std::string,std::shared_ptr<Data_Struct>,std::less<_Kty>,std::allocator<std::pair<const _Kty,_Ty>>>' to 'std::map<std::string,std::shared_ptr<const Data_Struct>,std::less<_Kty>,std::allocator<std::pair<const _Kty,_Ty>>>'
    process((std::map<std::string,std::shared_ptr<const Data_Struct>>)my_data);
        // error C2440: 'type cast' : cannot convert from 'std::map<std::string,std::shared_ptr<Data_Struct>,std::less<_Kty>,std::allocator<std::pair<const _Kty,_Ty>>>' to 'std::map<std::string,std::shared_ptr<const Data_Struct>,std::less<_Kty>,std::allocator<std::pair<const _Kty,_Ty>>>'
    process(static_cast<std::map<std::string,std::shared_ptr<const Data_Struct>>>(my_data));
        // error C2440: 'static_cast' : cannot convert from 'std::map<std::string,std::shared_ptr<Data_Struct>,std::less<_Kty>,std::allocator<std::pair<const _Kty,_Ty>>>' to 'std::map<std::string,std::shared_ptr<const Data_Struct>,std::less<_Kty>,std::allocator<std::pair<const _Kty,_Ty>>>'
    process(reinterpret_cast<std::map<std::string,std::shared_ptr<const Data_Struct>>>(my_data));
        // error C2440: 'reinterpret_cast' : cannot convert from 'std::map<std::string,std::shared_ptr<Data_Struct>,std::less<_Kty>,std::allocator<std::pair<const _Kty,_Ty>>>' to 'std::map<std::string,std::shared_ptr<const Data_Struct>,std::less<_Kty>,std::allocator<std::pair<const _Kty,_Ty>>>'
    process(const_cast<std::map<std::string,std::shared_ptr<const Data_Struct>>>(my_data));
        // error C2440: 'const_cast' : cannot convert from 'std::map<std::string,std::shared_ptr<Data_Struct>,std::less<_Kty>,std::allocator<std::pair<const _Kty,_Ty>>>' to 'std::map<std::string,std::shared_ptr<const Data_Struct>,std::less<_Kty>,std::allocator<std::pair<const _Kty,_Ty>>>'
    process(std::static_pointer_cast<std::map<std::string,std::shared_ptr<const Data_Struct>>>(my_data));
        // error C2784: 'std::shared_ptr<_Ty> std::static_pointer_cast(const std::shared_ptr<_Ty2> &) throw()' : could not deduce template argument for 'const std::shared_ptr<_Ty2> &' from 'std::map<std::string,std::shared_ptr<Data_Struct>,std::less<_Kty>,std::allocator<std::pair<const _Kty,_Ty>>>'
    process(std::const_pointer_cast<std::map<std::string,std::shared_ptr<const Data_Struct>>>(my_data));
        // error C2784: 'std::shared_ptr<_Ty> std::const_pointer_cast(const std::shared_ptr<_Ty2> &) throw()' : could not deduce template argument for 'const std::shared_ptr<_Ty2> &' from 'std::map<std::string,std::shared_ptr<Data_Struct>,std::less<_Kty>,std::allocator<std::pair<const _Kty,_Ty>>>'
}

void process(std::map<std::string,std::shared_ptr<const Data_Struct>> data) {
    for(auto &d : data)
        std::cout << d.first << std::endl;
}

【问题讨论】:

    标签: c++ c++11 stl shared-ptr


    【解决方案1】:

    这两种地图类型完全不相关,尽管有明显的相似之处,但不能互换使用。不过,您确实有几个选择:

    • 在其构造函数中填充您的数据类,这样您就不必在创建后对其进行修改。
    • 让流程函数在模板化迭代器范围而不是特定容器上工作。
    • 让流程函数在模板化容器而不是特定类型上工作。

    【讨论】:

    • 不幸的是,我无法在创建时填充我的数据。我想将地图容器作为一个整体(只是一个 const 版本)发送,所以我不想使用迭代器。如果我使用模板函数,我可以确保我的 shared_ptr 的 const-ness 吗?
    【解决方案2】:

    函数process() 通过值获取其参数。这意味着当它被调用时,会获取、处理然后丢弃地图的副本。我不知道这是不是你的意图。假设是,你需要的是一个转换函数:

    #include <iostream>
    #include <string>
    #include <map>
    #include <memory>
    
    
    struct Data_Struct
    {
        int a;
        std::string b;
    };
    
    void process(std::map<std::string,std::shared_ptr<const Data_Struct>>);
    
    std::map<std::string,std::shared_ptr<const Data_Struct>>
    convert_map(const std::map<std::string,std::shared_ptr<Data_Struct>>& source)
    {
        std::map<std::string,std::shared_ptr<const Data_Struct>> ret;
        for(const auto& item : source) {
            ret.emplace(item.first, item.second);
        }
        return ret;
    }
    
    void process(std::map<std::string,std::shared_ptr<const Data_Struct>> data) {
        for(auto &d : data)
            std::cout << d.first << std::endl;
    }
    
    void calling_function() {
        std::map<std::string,std::shared_ptr<Data_Struct>> my_data;
        my_data.emplace("test",std::shared_ptr<Data_Struct>(new Data_Struct)).first->second->a = 2;
        process(convert_map(my_data));
    }
    
    
    using namespace std;
    
    int main()
    {
        calling_function();
    
        return 0;
    }
    

    【讨论】:

    • 我没有意识到我在我的测试用例中是通过值传递的,我在我的用例中是通过引用传递的。但是,制作地图的 const 副本不会产生太多开销,因为我没有复制实际数据,而只是复制指向数据的指针和字符串键。它不是那么理想或美丽,但我能够让它在我的实际代码中工作。感谢您的帮助。
    猜你喜欢
    • 1970-01-01
    • 2014-08-06
    • 2019-10-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多