【问题标题】:get C-string iterator for std::string container获取 std::string 容器的 C 字符串迭代器
【发布时间】:2017-01-07 07:46:13
【问题描述】:

假设我有一个 std::unordered_map。我需要一个遍历映射键的迭代器,但取消引用 C 风格的 char const* 而不是 std::string。 Boost::adaptors 看起来正是我第一部分需要的东西:

std::unordered_map<std::string, int> map{{"one",1},{"two",2}};
for (auto& str : map | boost::adaptors::map_keys) {...}

我必须为 std::string->C 字符串转换编写自定义适配器还是有其他方法?

【问题讨论】:

    标签: c++ c++11 boost iterator


    【解决方案1】:

    首先,我质疑这个前提。使用std::string 比使用char const*s 更有用。

    也就是说,既然您已经在使用适配器,那么您只需要transformed

    for (auto c_str : map | map_keys
                          | transformed(std::mem_fn(&std::string::c_str)))
    {
        ...
    }
    

    【讨论】:

    • 我没有意识到你可以用这种方式转换,这正是我正在寻找的东西。此外,您会因使用 auto 而获胜。
    • 要回答您的问题,我需要为我迭代的对象提供标准布局保证。
    【解决方案2】:

    最简单的答案:

    #include <unordered_map>
    #include <boost/range/adaptors.hpp>
    #include <string>
    #include <iostream>
    
    using namespace boost::adaptors;
    
    int main() {
        std::unordered_map<std::string, int> map{{"one",1},{"two",2}};
        for (char const* sz : map 
                | map_keys
                | transformed(std::mem_fn(&std::string::c_str))
        ) {
            std::cout << sz << "\n";
        }
    }
    

    我的首选:

    #include <unordered_map>
    #include <boost/range/adaptors.hpp>
    #include <string>
    #include <iostream>
    
    using namespace boost::adaptors;
    int main() {
        std::unordered_map<std::string, int> map{{"one",1},{"two",2}};
        for (char const* sz : map | transformed([](auto const& p) { return p.first.c_str(); }))
        {
            std::cout << sz << "\n";
        }
    }
    

    【讨论】:

    • @Barry 不是问题。我认为只是更多的打字。
    • 遗憾的是,在 C++14 之前的版本中没有通用 lambda。神圣的 Bjarne,看起来很漂亮! +1
    【解决方案3】:

    如果您没有方便的 boost,您可以通过从地图的迭代器派生来手动滚动它:

    #include <unordered_map>
    #include <string>
    #include <stdio.h>
    
    struct cstrofkey
    : std::unordered_map<std::string, int>::const_iterator
    {
        using base_class = std::unordered_map<std::string, int>::const_iterator;
        using value_type = const char*;
        cstrofkey(base_class iter) : base_class(iter) {}
    
        auto operator*() const
        {
            return (base_class::operator*()).first.c_str();
        }
    };
    
    
    struct cstrkeyrange
    {
        cstrkeyrange(const std::unordered_map<std::string, int>& map)
        : _begin(map.cbegin()), _end(map.cend())
        {};
    
        cstrofkey begin() const { return _begin; }
        cstrofkey end() const { return _end; }
    
        cstrofkey _begin, _end;
    };
    
    
    int main()
    {
        std::unordered_map<std::string, int> map{{"one",1},{"two",2}};
    
    
        for (auto str : cstrkeyrange(map)) {
            printf("%s\n", str);
        }   
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-01-16
      • 2014-11-08
      • 1970-01-01
      • 2011-07-22
      • 2019-10-12
      • 2014-09-14
      • 2015-04-29
      • 2015-07-04
      相关资源
      最近更新 更多