使用存储在std :: any中的std :: map,然后通过std :: any_cast访问

时间:2018-09-03 15:33:34

标签: c++ c++17

我正在尝试从以下代码中了解结果:

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;
    }
};

结果如下:

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

我的问题是,为什么_container直到进行分配后才包含新插入的密钥?

std::any_cast是否将副本返回到std::map<KeyTypeT, ValueTypeT>?我本来希望它返回原始地图。有没有办法修改存储在std::any中的原始地图?

2 个答案:

答案 0 :(得分:7)

您正在使用(#2)的any_cast的重载为您提供any所保存值的副本,而不是对其的引用。因此,您要插入的mapmap持有的any不同。

如果您想直接修改any持有的内容,则需要使用一种通过指针(即#5)来占用any的重载之一:

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

或者您可以在any_cast中明确提供引用类型:

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

还请注意,即使any_cast本身没有给您副本,您也可以通过编写以下内容来自己制作:

auto originalMap = ...;

而不是引用结果。所以您可能想要:

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

答案 1 :(得分:0)

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