简体   繁体   中英

Using std::map stored in a std::any and then accessed via std::any_cast

I am trying to understand the results from the following code:

template<typename KeyTypeT, typename ValueTypeT>
class MapWrapper {
    std::any _container;

    MapWrapper() {
        _container = std::map<KeyTypeT, ValueTypeT>();
    }

    void insert(KeyTypeT key, ValueTypeT value) {
       auto originalMap = std::any_cast<std::map<KeyTypeT, ValueTypeT>>(_container);
       std::cout << "count is " << originalMap.size() << std::endl;

       auto afterInsertion = std::any_cast<std::map<KeyTypeT, ValueTypeT>>(_container);
       afterInsertion.insert(std::make_pair(key, value));
       std::cout << "count is " << afterInsertion.size() << std::endl;

       auto originalMapAfterInsertion = std::any_cast<std::map<KeyTypeT, ValueTypeT>>(_container);
       std::cout << "count is " << originalMapAfterInsertion.size() << std::endl;


       _container = afterInsertion;
       auto originalMapAfterAssignement = std::any_cast<std::map<KeyTypeT, ValueTypeT>>(_container);
       std::cout << "count is " << originalMapAfterAssignement.size() << std::endl;
    }
};

The results are as follows:

Test Results:
count is 0
count is 1
count is 0 // why is this not 1?
count is 1

My question is why does _container not contain the newly inserted key until after I do an assignment?

Is std::any_cast returning a copy to the std::map<KeyTypeT, ValueTypeT> ? I would have expected it to return the original map. Is there a way to modify the original map stored in the std::any ?

The overload of any_cast that you are using (#2) gives you a copy of the value held by the any , not a reference to it. So the map that you're inserting into is a different map than the one the any is holding.

If you want to directly modify what the any is holding, you need to use one of the overloads that take the any by pointer (ie #5):

std::any a = 1;
int* p = std::any_cast<int>(&a); // <== like this
assert(p);
*p = 42;
assert(std::any_cast<int>(a) == 42);

Or you can explicitly provide a reference type into any_cast :

std::any a = 1;
std::any_cast<int&>(a) = 42; // <== int&, not int
assert(std::any_cast<int>(a) == 42);

Also note that even if any_cast itself wasn't giving you a copy, you're making one yourself by writing:

auto originalMap = ...;

instead of taking a reference to the result. So you probably wanted:

auto& map = std::any_cast<std::map<...>&>(_container);

你的any_cast正在返回一个副本 - 尝试返回一个指向所包含对象的指针或包装在std :: reference_wrapper中

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM