2
votes

I am trying to do this: maitain two vectors of strings whereby one vector stores values and the second stores references of the same values. I thought using boost::reference_wrapper would do the trick but it seems it won't. My platform is Visual C++ 2008.

std::vector<std::string> str_vec;
str_vec.push_back("abc");
str_vec.push_back("cde");
str_vec.push_back("fgh");

std::vector<boost::reference_wrapper<std::string> > str_view;
for(std::vector<std::string>::iterator it = str_vec.begin(); it != str_vec.end(); ++it)
{
  str_view.push_back(*it);
}

This is the error:

error C2664: 'std::vector<_Ty>::push_back' : cannot convert parameter 1 from std::basic_string<_Elem,_Traits,_Ax>' to 'const boost::reference

I could use boost::shared_ptr but I thought a reference better expresses my intent. This code can probably work in C++11 using std::reference_wrapper but that is not available to me right now.

1
what is visual c++ 2009? there is 2008, 2010 and 2011 beta as far as I know.EdChum

1 Answers

3
votes

Yes, it can. The documentation states that it is CopyConstructible and Assignable which are required concepts for container template arguments. But you need to use boost::ref or boost::cref to create objects of type reference_wrapper. There is no implicit conversion and this is why your code does not work.

Be aware that a slight difference between std::reference_wrapper and boost::reference_wrapper is that only the std version works with functors.

Example:

std::vector<std::string> str_vec;
str_vec.push_back("abc");
str_vec.push_back("cde");
str_vec.push_back("fgh");

std::vector<boost::reference_wrapper<std::string> > str_view;
std::transform(begin(str_vec), end(str_vec),
               std::back_inserter(str_view), boost::ref<std::string>);

If you dislike that and would like to have implicit conversion from the original value, you might want to use:

template<typename T>
class my_ref_wrap : public boost::reference_wrapper<T> {
public:
  my_ref_wrap(T& t) : boost::reference_wrapper<T>(t) {}
};

std::vector<my_ref_wrap<std::string> > str_view;
std::copy(begin(str_vec), begin(str_vec),
          std::back_inserter(str_view));

Although I would not do that.