2012-01-29 2 views
1

Просто вопрос о том, как работает копия ... Мне нужна определенная проверка для целей психического здоровья. Если у меня есть:STL Algo Library copy()

multiset<pair<double, string> > myMultiset; 

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

copy(myMultiset.begin(), myMultiset.end(), ostream_iterator</.../>(cout, " ")); 

Это происходит потому, что для А. Для ostream_iterator Я пытаюсь передать тип «пара», который не понравится? Если мультимножество было сделано из «пары», хотя я бы передавал только строку типа «ostream», мне кажется, что попытка передать два элемента сразу вызовет ошибку. есть ли итератор, который будет перебирать JUST ключи или только значения? Есть ли чистый способ справиться с этим? Каждый раз, когда я заканчиваю тем, что пишу «for()», чтобы я мог получить содержимое с «iter-> first» и «iter-> second» ... Я новичок в STL Algo, но мне нравится идея чистоты и я бы хотел использовать свои возможности ... Так много минут ...

+1

Вы "чувствуете"? Почему бы вам не попробовать? – svick

+1

Ответ здесь: http://stackoverflow.com/questions/312749/providing-an-iterator-for-the-first-element-of-a-container-of-pairs –

+0

Я действительно попробовал вариант и подумал, куда он идет. Думаю, я пытаюсь сделать слишком много слишком быстро ... – MCP

ответ

4

Причина, по которой ваш std::copy() не будет работать как есть, потому что нет std::operator<<(), определенного для std::pair. Существует много разумных способов, которыми пользователь может формально форматировать пару, а стандарт оставил ее неопределенной. Вы можете определить один по своему усмотрению:

template<typename K, typename V> 
std::ostream& operator<<(std::ostream& out, std::pair<K,V> const& p) 
{ 
    return out << p.first; 
} 

// ... 
std::copy(set.begin(), set.end(), 
      std::ostream_iterator<double>(std::cout, " ")); 

или определить функцию и использовать std::transform() вместо:

std::transform(set.begin(), set.end(), 
       std::ostream_iterator<double>(std::cout, " "), 
       [](std::pair<double,std::string> const& p) { 
    return p.first; 
}); 

Вы могли бы найти ключ вывающейся лямбды полезно, и плоть полезности функтора из него для повторного использования:

struct keys_of { 
    template<typename K, typename V> 
    K operator()(std::pair<K,V> const& p) const 
    { 
     return p.first; 
    } 
}; 

// ... 
std::transform(set.begin(), set.end(), 
       std::ostream_iterator<double>(std::cout, " "), 
       keys_of()); 

Иногда forпетли делает сделать вещи проще, более кратким, более им понятно. Новая линейка на основе for цикла занимает еще дальше:

for(auto p : set) { 
    std::cout << p.first << ' '; 
} 

Это будет вести себя немного отличается от других подходов в том, что он оставит оборванное пространство разделителя в конце. Он также работает только с контейнером; если у вас есть пара итераторов, а не контейнер (скажем, пара std::istream_iterator или пара произвольных итераторов в контейнер), то вы должны использовать алгоритм. Но я думаю, что так оно и есть самое простое и ясное из кучки.

+0

Много интересной информации. Благодаря! – MCP

1

Вы используете C++ 11? Если это так, вы можете использовать алгоритм transform с лямбдой для извлечения ключа (или значения).

Вы можете делать подобные вещи в старом C++, но это немного грязнее.

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