Использование std :: map, хранящегося в std :: any, а затем доступ через std :: any_cast - PullRequest
0 голосов
/ 03 сентября 2018

Я пытаюсь понять результаты из следующего кода:

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 голосов
/ 03 сентября 2018

Ваш any_cast возвращает копию - попробуйте вернуть указатель на содержащийся объект или оберните в std :: reference_wrapper

0 голосов
/ 03 сентября 2018

Перегрузка any_cast, которую вы используете (# 2), дает вам копию значения, содержащегося в any, а не ссылку на него. Таким образом, map, который вы вставляете, отличается от map от того, который содержит any.

Если вы хотите напрямую изменить то, что держит any, вам нужно использовать одну из перегрузок, которые принимают указатель any (т. Е. # 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);

Или вы можете явно указать ссылочный тип в 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);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...