Почему я не могу использовать boost::адаптер::значения карты вне цикла на основе диапазона?

#c #boost #boost-range #boost-adaptors

Вопрос:

Я хочу использовать boost boost::adaptor::map_values для построения вектора всех значений a std::map . Возьмите этот пример кода (или попробуйте его в Godbolt):

 #include <boost/range/adaptors.hpp>
#include <boost/range/adaptor/map.hpp>

std::vector<int> getValueVector(const std::map<int, int> amp; m)
{
    auto valueRange = boost::adaptors::map_values(m);
    return std::vector<int>(valueRange.begin(), valueRange.end());
}

int main() {
    std::map<int, int> my_map;
    getValueVector(my_map);
}
 

GCC жалуется:

 error: no match for call to '(const boost::range_detail::map_values_forwarder) (const std::map<int, int>amp;)'
 

Все примеры и вся документация, которые я могу найти, когда-либо используют адаптеры boost только внутри операторов, которые принимают диапазоны (например, на основе диапазонов для циклов или boost::copy ), но никогда в операторах, которым нужны пары итераторов, таких как std::vector конструктор.

Согласно GCC, проблема здесь в том, что map_values это неприменимо к std::map<int, int> . Тем не менее, это буквально единственный пример, приведенный в документах, поэтому я почти уверен, что std::map<int, int> для этого все должно быть в порядке map_values .

Что здесь не так?

P.S.: Я знаю, что существует множество других способов элегантного построения вектора по значениям карты. Я хочу знать, почему этот код не работает. Кроме того, этот подход имеет дополнительное преимущество гарантированного RVO вместо «вероятно, NRVO», которое есть у большинства других решений, которые я могу придумать.

Комментарии:

1. Вы неправильно его применяете. Я верю, что это должно быть что-то вроде m | boost::adaptors::map_values;

2. В документации говорится, что m | boost::adaptors::map_values и boost::adaptors::map_values(m) должно быть эквивалентно. Но на самом деле, похоже, это работает. Странный.

3. @LukasBarth я думаю m | boost::adaptros::map_values , и boost::adaptors::values(m) они эквивалентны. Обратите внимание на другое название

Ответ №1:

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

Вверху они пишут:

 Syntax      Code

Pipe        rng | boost::adaptors::map_values
Function    boost::adaptors::values(rng) 
 

И действительно, когда я изменю ваш код на этот:

 #include <boost/range/adaptors.hpp>
#include <boost/range/adaptor/map.hpp>
#include <iostream>

std::vector<int> getValueVector(const std::map<int, int> amp; m)
{
    auto valueRange = boost::adaptors::values(m);
    return std::vector<int>(valueRange.begin(), valueRange.end());
}

int main() {
    std::map<int, int> my_map{{1,2},{3,4},{5,6}};
    auto v = getValueVector(my_map);
    for (const autoamp; e : v) std::cout << e << " ";
}
 

Есть ожидаемый результат:

 2 4 6 
 

Комментарии:

1. О, ты прав. Варианты на operator| основе и на основе вызова функций называются по-разному. Спасибо!