简体   繁体   English

用boost :: algorithms :: join提取和连接字符串

[英]Extracting and joining strings with boost::algorithms::join

I have a collection of a certain struct, and I want to join a string member of each of these structs into a semicolon-separated list. 我有一个特定结构的集合,我想将每个这些结构的字符串成员加入以分号分隔的列表中。 Making good use of the standard algorithms library and Boost, the problem breaks down easily: 充分利用标准算法库和Boost,可以轻松解决问题:

  1. Use std::transform to get a collection of the strings, then 使用std::transform获取字符串的集合,然后
  2. Call boost::algorithm::join to join them together. 调用boost::algorithm::join将它们连接在一起。

However, making a copy of the strings just to feed them to join is silly, so I attempted to use a reference_wrapper around the strings as the output for std::transform . 但是,仅复制字符串以供它们join是很愚蠢的,因此我尝试在字符串周围使用reference_wrapper作为std::transform的输出。 The corresponding code can be seen here: 相应的代码可以在这里看到:

struct IPAddress {
    vector<uint8_t> binaryValue;
    string stringValue;
}

// ---snip---

vector<IPAddress> addresses;

// Populate and manipulate the addresses vector
// ---snip---

// Join the list.
vector<reference_wrapper<string>> addressStrings(addresses.size());
transform(begin(addresses), end(addresses), begin(addressStrings),
    [](const IPAddress& addr) {
        return ref(addr.stringValue); // Expodes
    });

return boost::algorithm::join(addressStrings, ";"); // Also explodes

The lambda provided to std::transform fails to compile, claiming that there is no match for the assignment operator between two reference_wrapper<string> s, despite that being documented and the entire point of a reference_wrapper . 提供给std::transform的lambda无法编译,声称尽管两个reference_wrapper<string>都已记录在案 ,但对reference_wrapper的整个要点也没有匹配。

Then, if I comment out the transform call, boost::algorithm::join fails anyways by trying to call a default constructor of reference_wrapper (which has none) instead of string . 然后,如果我注释掉了transform调用,则boost::algorithm::join仍然会通过尝试调用reference_wrapper的默认构造函数(没有)而不是string来失败。

Am I missing something straightforward, or should I just give up and use a for loop with iterators? 我是否缺少一些简单明了的东西,还是应该放弃并在迭代器中使用for循环?

With a little help from boost ranges you can have your cake and eat it. 在增强范围的一点帮助下,您可以吃蛋糕并食用。

It removes the sting from this mix: the complication is that you want to use an intermediate collection of std::string const& but, obviously that doesn't work with std::vector . 它消除了这种混合的麻烦:复杂之处在于,您想使用std::string const&的中间集合,但是显然不适用于std::vector

So, we drop the intermediate collection, instead using an adapted view ( boost::adaptors::transformed ) and, no need for a lambda either[¹], just use std::mem_fun : See it Live On Coliru 因此,我们删除中间集合,而不是使用适应的视图boost::adaptors::transformed ),并且也不需要lambda [¹],只需使用std::mem_fun :观看Live on Coliru

#include <boost/algorithm/string.hpp>
#include <boost/range/adaptors.hpp>

#include <vector>
#include <string>
#include <functional>

struct IPAddress {
    std::vector<uint8_t> binaryValue;
    std::string stringValue;
};

std::string foo(std::vector<IPAddress> const& addresses)
{
    using namespace boost::adaptors;
    return boost::algorithm::join(
        addresses | transformed(std::mem_fn(&IPAddress::stringValue)), 
        ";");
}

#include <iostream>

int main()
{
    std::vector<IPAddress> const addresses {
        { {}, "test1" },
        { {}, "test2" },
    };

    std::cout << foo(addresses);
}

Prints 打印

test1;test2

[¹] unless stringValue was an overloaded member function [¹]除非stringValue是重载的成员函数

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM