获取std :: string容器的C-string迭代器

时间:2016-08-30 21:32:17

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

假设我有一个std :: unordered_map。我需要一个迭代器,它遍历地图的键但是取消引用C风格的char const *而不是std :: string。 Boost :: adapter看起来就像我第一部分需要的那样:

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

我是否必须为std :: string-&gt; C-string转换编写自定义适配器,还是有另一种方式?

3 个答案:

答案 0 :(得分:3)

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

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

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

答案 1 :(得分:3)

最简单的答案:

#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";
    }
}

答案 2 :(得分:0)

如果你没有提升方便,你可以通过派生地图的迭代器手动滚动它:

#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);
    }   
}