Как скопировать ссылки элементов одного вектора в другой вектор?

У меня есть vector:

std::vector<island> sea;

И теперь я хочу хранить указатели на все элементы этого vector в другом vector. Но просто для личного упражнения я хочу сделать это в причудливом стиле C++, поэтому вместо std::vector<const island*> p_sea я набираю:

std::vector<std::reference_wrapper<const island>> r_sea;

И теперь я хотел бы заполнить этот новый vector ссылками:

std::transform(sea.begin(), sea.end(),
               std::back_inserter(r_sea),
               std::cref<island>
);

Насколько я понимаю, из статей cppreference четвертый аргумент transform должен быть функцией, которая принимает константные ссылки на элементы из исходного диапазона и возвращает элементы целевого диапазона; именно это и делает std::cref<island>: принимает const island& в качестве аргументов и возвращает std::reference_wrapper<const island>. Так что я считаю, что это должно работать ??

Однако это не так:

#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>
#include <iterator>


struct island {
    long long x,y; //coords
};

int main() {
    std::vector<island> sea;
    std::vector<std::reference_wrapper<const island>> r_sea;

    std::transform(sea.begin(), sea.end(),
                   std::back_inserter(r_sea),
                   std::cref<island>
    );

    return 0;
}

Это приводит к следующим ошибкам компиляции:

prog.cpp: In function ‘int main()’:
prog.cpp:19:5: error: no matching function for call to ‘transform(std::vector<island>::iterator, std::vector<island>::iterator, std::back_insert_iterator<std::vector<std::reference_wrapper<const island> > >, <unresolved overloaded function type>)’
     );
     ^
In file included from /usr/include/c++/6/algorithm:62:0,
                 from prog.cpp:3:
/usr/include/c++/6/bits/stl_algo.h:4166:5: note: candidate: template<class _IIter, class _OIter, class _UnaryOperation> _OIter std::transform(_IIter, _IIter, _OIter, _UnaryOperation)
     transform(_InputIterator __first, _InputIterator __last,
     ^~~~~~~~~
/usr/include/c++/6/bits/stl_algo.h:4166:5: note:   template argument deduction/substitution failed:
prog.cpp:19:5: note:   could not resolve address from overloaded function ‘cref<island>’
     );
     ^
In file included from /usr/include/c++/6/algorithm:62:0,
                 from prog.cpp:3:
/usr/include/c++/6/bits/stl_algo.h:4203:5: note: candidate: template<class _IIter1, class _IIter2, class _OIter, class _BinaryOperation> _OIter std::transform(_IIter1, _IIter1, _IIter2, _OIter, _BinaryOperation)
     transform(_InputIterator1 __first1, _InputIterator1 __last1,
     ^~~~~~~~~
/usr/include/c++/6/bits/stl_algo.h:4203:5: note:   template argument deduction/substitution failed:
prog.cpp:19:5: note:   could not resolve address from overloaded function ‘cref<island>’
     );

https://ideone.com/E80WXH

Что я делаю не так?

... Я вернулся к злым указателям C.


person Community    schedule 11.12.2017    source источник
comment
Попробуйте std::reference_wrapper<const island> вместо std::reference_wrapper<const island*>.   -  person cdhowie    schedule 11.12.2017
comment
@cdhowie опечатка; не исправляет ошибки компиляции; Я удаляю опечатку из вопроса прямо сейчас.   -  person    schedule 11.12.2017
comment
Ваша проблема в том, что std::cref перегружен. Вам нужно устранить неоднозначность, какую перегрузку использовать.   -  person StoryTeller - Unslander Monica    schedule 11.12.2017
comment
@StoryTeller как?   -  person    schedule 11.12.2017
comment
Почему вы не публикуете свой реальный код?   -  person    schedule 11.12.2017
comment
@cdhowie Опечатка исправлена, ошибки компиляции сохраняются.   -  person    schedule 11.12.2017
comment
@gaazkam MVCE был бы особенно полезен для таких вопросов.   -  person cdhowie    schedule 11.12.2017
comment
@manni66 manni66 Проблема в том, что это является частью реального кода. Алгоритмическая задача. Поиск пути среди сетки островов. Мне нужно отсортировать острова по нескольким параметрам одновременно. Я должен опубликовать весь алгоритм поиска пути? Это не было бы минимальным VCE!!   -  person    schedule 11.12.2017
comment
@cdhowie, как указано выше.   -  person    schedule 11.12.2017
comment
@gaazkam MVCE не означает вставку всего вашего кода. Например, это является достаточным MVCE для этой конкретной проблемы.   -  person cdhowie    schedule 11.12.2017
comment
@cdhowie Ну, я разместил это на ideone и связался с ним, хорошо, теперь я понимаю, что этого было недостаточно, исправил вопрос, теперь все в порядке?   -  person    schedule 11.12.2017
comment
@gaazkam Да, это прекрасно. Внешние ресурсы, такие как ideone, хороши для дополнения вопроса, но мы не должны полагаться на них в вопросе. Если ideone исчезнет, ​​мы не хотим, чтобы ваш вопрос потерял смысл.   -  person cdhowie    schedule 11.12.2017


Ответы (2)


std::cref перегружен. Простого указания аргумента шаблона недостаточно для устранения неоднозначности между перегрузками. У вас есть два варианта:

  1. В ролях

    static_cast<std::reference_wrapper<const island>(*)(const island&)>(std::cref<island>)
    
  2. Поднимите имя до объекта функтора (лямбда). как предложил @Yakk.

person StoryTeller - Unslander Monica    schedule 11.12.2017

Замените std::cref<island> на [](auto&x){return std::cref<island>(x);}, предполагая, что c+ +14.

В c++11, замените auto на island const.

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

person Yakk - Adam Nevraumont    schedule 11.12.2017