c++c++11c++17stdany

How to Add Element into a std::vector using std::any


I am working on a C++17 project and there i am using std::any. A minimal reproducible example is given below for reference explaining what i want to achieve.

#include <any>
#include <vector>
#include <iostream>
int main()
{
    std::vector<int> vec{1,2,3};
    
    std::any anything = vec;
    
   // anything.push_back(4);//i want to add an element into vector vec, using variable anything but this statement won't work

    
    std::cout<<std::any_cast<std::vector<int>>(anything).size()<<std::endl;//prints 3 
    std::any_cast<std::vector<int>>(anything).push_back(4);//this adds(push_back) element into rvalue
    std::cout<<std::any_cast<std::vector<int>>(anything).size()<<std::endl;//prints 3 but i want 4 
}

As can be seen in the above example, i have a std::any object and i am using std::any_cast to add element into the vector. I want to add the element into the actual(lvalue) vector named vec but instead, the element is added into an rvalue. Is there a way to add element into the vector named vec using std::any. If not then is there any other way of doing this like using std::variant or something else that i may not be aware of. I am looking for a way of doing this in any version of C++ like C++11 or C++17 etc.

In my actual project, there is requirement for storing object of any type. So i got the same problem there. And then realized what is wrong(namely, we are using push_back on an rvalue) and then i reduced the problem to a minimal reproducible example and am asking here.


Solution

  • we are using push_back on an rvalue

    No, that's not the problem. any stores a copy of what it is given. It doesn't reference some other object. It creates an object from what it is given. So even if you get a reference to the object in the any, it wouldn't be a reference to vec itself.

    If you want to store a reference to an object in an any, you need to do so explicitly by storing either a pointer or a reference_wrapper to that object:

    using ref_type = decltype(std::ref(vec));
    
    std::any anything = std::ref(vec);
    
    std::any_cast<ref_type>(anything).get().push_back(4);
    

    Note that having an any which references an object is dangerous. If the any outlives the lifetime of the referenced object, you'll get bad things when you try to access the referenced object. This is part of why any stores copies by default.