2

I have a vector:

std::vector<island> sea;

And now I want to hold pointers to all elements of this vector in another vector. But just for a personal exercise I want to do this in a fancy C++ style, so instead of std::vector<const island*> p_sea I type:

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

And now I'd like to populate this new vector with references:

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

The way I understand it, from cppreference articles, the fourth argument of transform should be a function that takes const references to elements from the source range and returns elements of the destination range; and this is exactly what std::cref<island> does: it takes const island& as arguments and returns std::reference_wrapper<const island>. So I believe this should work??

However, it doesn't:

#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;
}

This results in the following compilation errors:

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

What am I doing wrong?

...I'm back to evil C pointers.

  • 1
    Try `std::reference_wrapper` instead of `std::reference_wrapper`. – cdhowie Dec 11 '17 at 18:20
  • @cdhowie typo; doesn't fix compilation errors; am removing the typo from the question right now. –  Dec 11 '17 at 18:21
  • Your problem is that `std::cref` is overloaded. You need to disambiguate which overload to use. – StoryTeller - Unslander Monica Dec 11 '17 at 18:21
  • @StoryTeller how? –  Dec 11 '17 at 18:22
  • Why don’t you post your real code? –  Dec 11 '17 at 18:22
  • @cdhowie Typo fixed, compilation errors persist. –  Dec 11 '17 at 18:22
  • @gaazkam An MVCE would be particularly helpful for questions like this. – cdhowie Dec 11 '17 at 18:22
  • @manni66 The problem is that this *is* a part of real code. Algorithmic task. Pathfinding among a grid of islands. I need to have the islands sorted in a few ways at the same time. Am I supposed to post the whole pathfinding algorithm? This would not be Minimal VCE!! –  Dec 11 '17 at 18:27
  • @cdhowie as above. –  Dec 11 '17 at 18:27
  • @gaazkam MVCE doesn't mean "paste all of your code." For example, [this](http://coliru.stacked-crooked.com/a/7205c3e2f5702d0b) is a sufficient MVCE for this specific problem. – cdhowie Dec 11 '17 at 18:29
  • @cdhowie Well I posted this on ideone and linked to it, OK I now understand this wasn't enough, fixed the quesion, is it OK now? –  Dec 11 '17 at 18:31
  • @gaazkam Yes, that's perfect. Off-site resources like ideone are good to augment a question, but we shouldn't depend on them for a good question. If ideone goes away, we don't want your question to stop making sense. – cdhowie Dec 11 '17 at 18:31

2 Answers2

3

Replace std::cref<island> with [](auto&x){return std::cref<island>(x);}, assuming .

In , replace auto with island const.

cref has overloads, you cannot pass the overload set as an object, as overload sets are not objects.

Yakk - Adam Nevraumont
  • 262,606
  • 27
  • 330
  • 524
0

std::cref is overloaded. Merely specifying the template argument is not enough to disambiguate between the overloads. You have two options:

  1. Cast it

    static_cast<std::reference_wrapper<const island>(*)(const island&)>(std::cref<island>)
    
  2. Lift the name up to a functor object (a lambda). like @Yakk proposed.

StoryTeller - Unslander Monica
  • 165,132
  • 21
  • 377
  • 458