Причина, по которой ваш std::copy()
не будет работать как есть, заключается в том, что для std::pair
не определено std::operator<<()
. Есть много разумных способов, которыми пользователь мог бы текстуально отформатировать пару, и стандарт оставил это неопределенным. Вы можете определить один самостоятельно:
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
или пара произвольных итераторов в контейнер), вам следует использовать алгоритм. Но я думаю, что это самое простое и понятное из всех.