1

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;
}
5
  • A reference wrapper holds a pointer to an object. You can't form a pointer to the value 3.14. So you can't put 3.14 directly into a reference wrapper, but you can put a reference to a variable there. Commented Feb 21, 2018 at 16:52
  • 1
    @Cheersandhth.-Alf Probably OP wants to put the value 3.14 into the object that the wrapper holds reference to. Commented Feb 21, 2018 at 16:55
  • @IvanSmirnov that's what i meant Commented Feb 21, 2018 at 17:01
  • 1
    Can you show the code that "works" and the code that gives that error, rather than describing them? Commented Feb 21, 2018 at 17:01
  • Well, there is get member function for getting the reference. Commented Feb 21, 2018 at 17:02

1 Answer 1

1

If you are trying to overwrite existing floats 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;
} 
Sign up to request clarification or add additional context in comments.

4 Comments

Thank you! I don"t have boost so i'll have to start writing my first iterator. any crucial advice you feel like giving?
I've added a sketch of the main operation. The basic gist is anywhere the iterator would serve up a value, it calls std::reference_wrapper::get on the value returned by inner, and elsewhere it just calls the operation on inner
I just found out boost is actually installed, I could get the sketch to work but wasn't able to do it with boost
I recommend just using an ordinary for loop. It is (1) shorter code, and (2) more clear.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.