Reputation: 211
How do you use std::transform
in conjunction with containers which hold objects of type std::reference_wrapper
? when reading from const std::vector<std::reference_wrapper<const float>>
and writing into an std::vector<float>
everything works, but if I try to write into an std::vector<std::reference_wrapper<float>>
it doesn't compile giving the error
/usr/include/c++/5/bits/stl_algo.h:4214: error: use of deleted function >'std::reference_wrapper<_Tp>::reference_wrapper(_Tp&&) [with _Tp = float]' __result = __binary_op(__first1, *__first2);
I think it is trying to replace the reference instead of changing the value of the referred value. Is there a way to use transform to achieve this or should I prefer writing my own function?
edit: added a example for reference:
#include <iostream>
#include <vector>
#include <functional>
#include <algorithm>
int main()
{
std::vector<float> v(3, 1.0f);
std::vector<std::reference_wrapper<float>> refVector;
refVector.reserve(v.size());
for(auto& elem : v)
{
refVector.push_back((std::reference_wrapper<float>)elem);
}
std::vector<float> v2(3, 2.0f);
std::vector<float> v3(3, 3.0f);
std::vector<float> v4(3);
for(auto& elem : v)
std::cout << elem << std::endl; // all 1s
std::transform(refVector.begin(), refVector.end(), v3.begin(), v4.begin(), std::plus<float>());
for(auto& elem : v4)
std::cout << elem << std::endl; // all 4s
std::transform(v2.begin(), v2.end(), v3.begin(), refVector.begin(), std::minus<float>()); // doesn't compile
for(auto& elem : v)
std::cout << elem << std::endl; // want all -1s
return 0;
}
Upvotes: 0
Views: 928
Reputation: 62864
If you are trying to overwrite existing float
s that are referenced in your std::vector<std::reference_wrapper<float>>
, then you need something that will unwrap the std::reference_wrapper<float>
into a float &
. boost::indirect_iterator
is such a thing, although it is easy to write your own iterator adapter if you can't add a boost dependancy.
An example usage:
std::vector<float> src1 = /* values */, src2 = /* other values */;
std::vector<std::reference_wrapper<float>> dest = /* references to somewhere */;
boost::indirect_iterator<std::reference_wrapper<float>, float> indirected(dest.begin());
std::transform(src1.begin(), src1.end(), src2.begin(), indirected, std::plus<float>());
A sketch implementation
struct indirect_iterator
{
/* a bunch of typedefs go here */
indirect_iterator& operator++() { ++inner; }
float & operator*() { return inner->get(); }
float * operator->() { return &inner->get(); }
private:
std::vector<std::reference_wrapper<float>>::iterator inner;
}
Upvotes: 1