Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

std::vector<Foo> when some members of Foo are references

I often prefer to use references than pointers whenever possible, it makes the syntax cleaner in my opinion. In this case, I have a class:

class Foo
{
public:
    Foo(Bar & bar) : bar_(bar) {}

private:
    Bar & bar_;
};

operator=() is implicitely deleted by the compiler for such a class, since once a reference is set, it cannot be changed (I can technically define my own that doesn't change bar_, but this would not be the required behaviour, so I'd rather the compiler complain if I try to assign a foo).

What I need is a std::vector<Foo> v;. This is impossible before C++11, since the template parameter must to be CopyAssignable. Indeed, when I call v.push_back(Foo(bar));, the compiler complains. But I feel it could be possible since C++11 and Move semantics.

My question is: is there a workaround using C++11 that would make building such a vector possible, or am I stuck in this case and have no way around using pointers instead of references? If there's a workaround, I'd highly appreciate a code snippet since I'm unfamiliar with move semantics.

like image 721
Boris Dalstein Avatar asked Nov 06 '13 00:11

Boris Dalstein


2 Answers

Voila emplace_back is able to do the job because of perfect forwarding.

#include <vector>                                                                  

class Bar{};                                                                       
class Foo                                                                          
{                                                                                  
public:                                                                            
    Foo(Bar & bar) : bar_(bar) {}                                                  

private:                                                                           
    Bar & bar_;                                                                    
};                                                                                 
using namespace std;                                                               
int main() {                                                                       
    vector<Foo> v;                                                                 
    Bar bar;
    v.emplace_back(bar);                                                     
} 

You can also store a reference by itself in a container with std::reference_wrapper used likestd::vector<std::reference_wrapper<int>> v

like image 84
aaronman Avatar answered Sep 20 '22 06:09

aaronman


Use v.emplace_back(bar) instead of push_back. It will construct a Foo in place in the memory vector has allocated for it, thus requiring no copying. Just pass emplace_back the arguments to construct a Foo.

like image 26
David Avatar answered Sep 20 '22 06:09

David