2013-10-14 2 views
3

Моя проблема довольно проста: у меня есть динамический массив объектов, у которых есть метод , возвращающий строку. Я хочу объединить все эти строки вместе.Конкатенатные строки, предоставляемые методом класса в C++

Если бы я был массив строк вместо объектов с методом, возвращающим строки, это было бы тривиальная задача:

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

Но в моем случае это скорее выглядит следующим образом:

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

Я хотел бы использовать стандартные библиотечные алгоритмы, так как я уверен, что это эффективный и что-то, что мне не нужно отлаживать, но это слишком сложно читать и понимать:

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()); 

Будущие Сопровождающие, вероятно (и это справедливо) поохотиться меня пробивать мне в лицо для понапрасну усложняя легкой задачей, которая могла бы быть сделано с:

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

ли там что-то более легкое здесь, чего я не вижу, или это действительно так: , где нужно позволить стандартным библиотекам отдыхать, и использовать цикл for ( , что накапливает в любом случае)?

+0

Я бы поставил под вопрос ваше желание: алгоритмы 'std' в основном предшествуют итерации на основе рангов, и многие из более простых алгоритмов лучше всего делать явно, особенно сейчас. – Yakk

ответ

6

Если вы настаиваете использовать STL, есть еще одна версия std::accumulate:

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

Тогда ваш код может стать

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

EDIT: Возможно больше копирования элизии дружественных декларации

+0

Да, я просто понял, отредактировал ответ, чтобы отразить это. – Erbureth

+0

К сожалению, это копирует накопленную строку на каждую итерацию.Параметр sink sink * может быть более эффективным, если разрешено реализовать реализацию 'std :: accumulate' через некоторый' result = std :: move (result) + * iterator; '(я не знаю, если это разрешено) – dyp

+0

@DyP В отредактированном ответе, если я не ошибаюсь, должна быть выполнена оптимизация оптимизации изображения. – Erbureth

2

Я бы просто использовал подход for loop. Это легче читать, и вам не нужно отлаживать или тестировать (по крайней мере, не на том же уровне, как если бы вы написали свой собственный алгоритм). Просто потому, что это не решение, использующее библиотеку std, не означает, что это разумное решение, которое легко поддерживать.

+0

Не последнее предложение, противоречащее предыдущим? «только потому, что это не решение, использующее библиотеку std, не означает, что это разумное решение»? –

+0

@ mel-: Бьюсь об заклад, там нет «нет». –

0

Вы можете написать оператор + =. Что-то, как

std::string & operator +=(std::string &s, const Foo &f) 
{ 
    return (s += f.name()); 
} 
+0

Вы правы, но только потому, что мне нужно конкатенировать строки для того, что я сейчас делаю, не подразумевает что это естественное поведение: 'foo + foo = foo.name + foo.name'; на самом деле в классах, с которыми я работаю, это будет очень контрастно интуитивно. –

+0

Вы не реализуете Foo + Foo. Вы реализуете std :: string + = Foo –

0

Я не вижу, как станд :: for_each, станд :: накапливают собираются, чтобы дать вам выигрыш производительности (ваш вектор даже достаточно большой, чтобы это имеет значение?). Возможно, вы захотите провести анализ времени, если это имеет значение для вас.

Я бы хотел читать и ремонтироваться, используя сложность, когда это не критично.

+0

Возможно, это только я, но это больше похоже на комментарий, чем на полный ответ. – crashmstr

Смежные вопросы