Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Concatenate strings provided by a class method in C++

My problem is rather simple: I have a dynamic array of objects that have a method returning a string. I want to concatenate all these strings together.

If I had an array of strings instead of objects with a method returning a string, this would be a trivial task:

std::vector<std::string> v{ "f", "o", "o" };
std::string const x = std::accumulate(v.begin(), v.end(), std::string());

But in my case it rather looks like this:

struct foo
{
    foo(std::string const & name) : name_(name) {}
    std::string const & name() const { return name_; }

    private:
        std::string const name_;
};

std::vector<foo> v{ foo("f"), foo("o"), foo("o") };

I would like to use the standard library algorithms as I am sure that those are efficient and something that I don't have to debug, but this is too hard to read and understand:

std::vector<std::string> transformed(v.size());
std::transform(v.begin(), v.end(), transformed.begin(),
    [](foo const & f) { return f.name(); });
std::string const x = std::accumulate(transformed.begin(), transformed.end(),
    std::string());

The future maintainers would probably (and rightfully so) hunt me down to punch me in the face for needlessly complicating an easy task, that could have been done with:

std::string x;
for(auto const & f : v)
    x += f.name();

Is there something easier here that I am not seeing, or is this indeed the case where one should let the standard libraries rest, and use the for loop (which is what accumulate boils down to anyway)?

like image 266
mel- Avatar asked Dec 15 '25 02:12

mel-


2 Answers

If you are insisting to use STL, there is another version of std::accumulate:

template< class InputIt, class T, class BinaryOperation >
T accumulate( InputIt first, InputIt last, T init, BinaryOperation op );

Then your code can become

std::string const x = std::accumulate(v.begin(), v.end(), std::string(),
                         [](std::string a, foo const& b){return a += b.name();});

EDIT: Perhaps more copy-elision friendly declaration

like image 133
Erbureth Avatar answered Dec 16 '25 16:12

Erbureth


I would just use the for loop approach. It's easier to read and it's not something you will need to debug or test (at least not at the same level as if you wrote your own algorithm of some sort). Just because it isn't a solution that utilizes the std library doesn't mean that's it's a sensible solution that is easy to maintain.

like image 42
Andrew Avatar answered Dec 16 '25 17:12

Andrew



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!