如何在 C++ 中对 STL 映射应用变换

发布于 2024-12-11 09:16:11 字数 745 浏览 0 评论 0原文

在 C++ 中,我使用转换将映射的所有值更改为大写。

  std::map<std::string, std::string> data = getData();

  // make all values uppercase
  std::transform(data.begin(), data.end(), data.begin(),
         [](std::pair<std::string, std::string>& p) {
           boost::to_upper(p.second);
           return(p);
         });

这给了我以下编译错误:

/opt/local/include/gcc46/c++/bits/stl_algo.h:4805:2: error: no match for call to '(main(int, char**)::<lambda(std::pair<std::basic_string<char>, std::basic_string<char> >&)>) (std::pair<const std::basic_string<char>, std::basic_string<char> >&)

我认为我的 lambda 表达式中的参数类型有问题。这可能很简单,但我似乎无法弄清楚预期的是什么。

In C++, I'm using transform to change all the values of a map to uppercase.

  std::map<std::string, std::string> data = getData();

  // make all values uppercase
  std::transform(data.begin(), data.end(), data.begin(),
         [](std::pair<std::string, std::string>& p) {
           boost::to_upper(p.second);
           return(p);
         });

This gives me the following compilation error:

/opt/local/include/gcc46/c++/bits/stl_algo.h:4805:2: error: no match for call to '(main(int, char**)::<lambda(std::pair<std::basic_string<char>, std::basic_string<char> >&)>) (std::pair<const std::basic_string<char>, std::basic_string<char> >&)

I think there's something wrong with the type of the argument in my lambda expression. It's probably something simple, but I can't seem to figure out what's expected.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

不如归去 2024-12-18 09:16:11

您缺少该对的第一种类型中的 const。

[](std::pair<const std::string, std::string>& p) {

但这不是您的问题:您不能使用 map 作为 OutputIterator,因为它们不支持分配。但是,您可以使用 std::for_each 改变第二个参数。

好旧的 map_to_foobar

std::for_each(data.begin(), data.end(), 
              [](std::pair<const std::string, std::string>& p) {
                p.second = "foobar";
              });

概念性的东西:使用与输入和输出相同的范围调用 transform 是非常合法的,并且如果所有函子都按值返回并且不这样做,则很有意义不要改变他们的论点。然而,就地改变某些东西可能会更快(或者至少在代码中看起来更快,更不用说优化编译器了),并且对于成员函数来说很有意义。

You are missing the const in the first type of the pair.

[](std::pair<const std::string, std::string>& p) {

However this is not your problem: You cannot use a map as the OutputIterator, as they do not support assignment. You can, however mutate the second argument using std::for_each.

Good old map_to_foobar:

std::for_each(data.begin(), data.end(), 
              [](std::pair<const std::string, std::string>& p) {
                p.second = "foobar";
              });

Conceptual stuff: Calling transform with the same range as input and output is quite legit and makes a lot of sense if all your functors return by value and don't mutate their arguments. However, mutating something in place can be a faster (or at least look faster in code, nevermind the optimizing compiler) and makes a lot of sense with member functions.

偷得浮生 2024-12-18 09:16:11

如果您打算坚持使用 std::transform,那么您需要 std::inserter()

C++03 MCVE

typedef std::map<int, std::string> Map;

struct ToUpper
{
    Map::value_type & operator()(Map::value_type & pair) const
    {
        boost::to_upper(pair.second);
        return pair;
    }
};

int main()
{
    Map m;
    m[0] = "snake_case";
    m[1] = "camelCase";
    m[2] = "PascalCase";
    
    std::transform(m.begin(), m.end(), std::inserter(m, m.end()), ToUpper());
    
    for (Map::const_iterator it = m.begin(); it != m.end(); ++it)
        std::cout << it->first << ", " << it->second << std::endl;
}

C++11(您可以在 中执行所有操作main() 真的)

int main()
{
    auto m = getData();

    auto toUpper = [] (decltype(m)::value_type & pair)
    {
        boost::to_upper(pair.second);
        return pair;
    };

    std::transform(m.begin(), m.end(), std::inserter(m, m.end()), toUpper);

    for (auto const & pair : m)
        std::cout << pair.first << ", " << pair.second << std::endl;
}

C++14(您可以在 lambda 参数中使用auto

int main()
{
    auto m = getData();

    auto toUpper = [] (auto & pair)
    {
        boost::to_upper(pair.second);
        return pair;
    };
    std::transform(m.begin(), m.end(), std::inserter(m, m.end()), toUpper);

    for (auto const & pair : m)
        std::cout << pair.first << ", " << pair.second << std::endl;
}

C++17(只是因为我喜欢结构化绑定)

int main()
{
    auto m = getData();

    auto toUpper = [] (auto & pair)
    {
        boost::to_upper(pair.second);
        return pair;
    };
    std::transform(m.begin(), m.end(), std::inserter(m, m.end()), toUpper);

    for (auto const & [key, value] : m)
        std::cout << key << ", " << value << std::endl;
}

If you plan on sticking to std::transform, then you need std::inserter():

C++03 MCVE

typedef std::map<int, std::string> Map;

struct ToUpper
{
    Map::value_type & operator()(Map::value_type & pair) const
    {
        boost::to_upper(pair.second);
        return pair;
    }
};

int main()
{
    Map m;
    m[0] = "snake_case";
    m[1] = "camelCase";
    m[2] = "PascalCase";
    
    std::transform(m.begin(), m.end(), std::inserter(m, m.end()), ToUpper());
    
    for (Map::const_iterator it = m.begin(); it != m.end(); ++it)
        std::cout << it->first << ", " << it->second << std::endl;
}

C++11 (you can do everything in main() really)

int main()
{
    auto m = getData();

    auto toUpper = [] (decltype(m)::value_type & pair)
    {
        boost::to_upper(pair.second);
        return pair;
    };

    std::transform(m.begin(), m.end(), std::inserter(m, m.end()), toUpper);

    for (auto const & pair : m)
        std::cout << pair.first << ", " << pair.second << std::endl;
}

C++14 (you can use auto in lambda parameters)

int main()
{
    auto m = getData();

    auto toUpper = [] (auto & pair)
    {
        boost::to_upper(pair.second);
        return pair;
    };
    std::transform(m.begin(), m.end(), std::inserter(m, m.end()), toUpper);

    for (auto const & pair : m)
        std::cout << pair.first << ", " << pair.second << std::endl;
}

C++17 (just because i love structured bindings)

int main()
{
    auto m = getData();

    auto toUpper = [] (auto & pair)
    {
        boost::to_upper(pair.second);
        return pair;
    };
    std::transform(m.begin(), m.end(), std::inserter(m, m.end()), toUpper);

    for (auto const & [key, value] : m)
        std::cout << key << ", " << value << std::endl;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文