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>’
);
What am I doing wrong?
...I'm back to evil C pointers.
std::cref
is overloaded. Merely specifying the template argument is not enough to disambiguate between the overloads. You have two options:
Cast it
static_cast<std::reference_wrapper<const island>(*)(const island&)>(std::cref<island>)
Lift the name up to a functor object (a lambda). like @Yakk proposed.