Разыменование члена шаблонного typedef - PullRequest
0 голосов
/ 27 ноября 2018

Я использую библиотеку, которая имеет:

typedef std::map<std::wstring, std::vector<std::wstring>* > XmlRecord_t;

Когда я выполняю итерацию на этой карте, я создаю переменные, такие как:

std::wstring& key( mapIter->first );
std::vector<std::wstring>* values( mapIter->second );

, что вполне нормально.Затем я хочу перебрать значения, поэтому у меня есть цикл for, такой как:

for( std::vector<std::wstring>::const_iterator it = vals->cbegin();... )

, который в порядке и работает хорошо.

Теперь, как любопытство, яХотелось бы повторно использовать имена typedef библиотеки, в случае изменения определения typedef, или для чистоты.Другими словами, я хотел бы использовать:

typedef XmlRecord_t::mapped_type VecPtr;
VecPtr values( mapIter->second )

вместо:

std::vector<std::wstring>* values( mapIter->second );  

Это работает до сих пор.Единственная проблема связана с циклом for.Мой typedef - это указатель на vector, а не просто vector.Поэтому я не могу использовать это typedef для замены:

std::vector<std::wstring>::const_iterator

любым способом, о котором я знаю.

Следовательно, мой вопрос обобщается так: если у вас есть библиотека (код, который я делаюне позволяет изменять):

typedef map<KEY, T*> Map2Ptrs

как вы можете использовать Map2Ptrs в своем коде для получения T (без указателя)?Чтобы сделать typedef типа T?

Очевидно, что авторам библиотеки следовало бы создать:

typedef std::vector<std::wstring>  XmlRecordVals;
typedef std::map<std::wstring, XmlRecordVals* > XmlRecord_t;

.Но у меня есть только оригинальный XmlRecord_t, с которым можно работать; (

Ответы [ 2 ]

0 голосов
/ 27 ноября 2018

Предполагая, что Map2Ptrs всегда является std::map, его ключ и сопоставленный тип можно проверить с помощью Map2Ptrs::key_type и Map2Ptrs::mapped_type соответственно.

Указатель можно удалить из типа с помощью std::remove_pointer_t(требуется C ++ 14 и #include<type_traits>), например:

using T = std::remove_pointer_t<Map2Ptrs::mapped_type>;

В современном C ++ вам, вероятно, не следует указывать типы итераторов вручную, их можно легко вывести:

for( auto it = vals->cbegin();... )

Кроме того, существует также диапазон-для, который устраняет необходимость указывать итераторы вручную и имеет гораздо более приятный синтаксис:

for(const auto& x : *vals) { /* Do something with x */ }

И, начиная с C ++ 17, для привязок карты можно структурироватьиспользуется:

for(const auto& [key, vals] : theMap) {
    /* Do something with key and vals */
}
0 голосов
/ 27 ноября 2018

Есть std::remove_pointer.Пример из cppreference :

print_is_same<int, std::remove_pointer<int*>::type>();  // true

Так что, если вы указали псевдоним указателя на векторный тип, вы получите итератор через:

using Xml_const_iterator = std::remove_pointer<XmlRecord_t>type::const_iterator;

Хотя я бы настоятельнопредлагаем вам изменить фактический псевдоним вместо указателя.

...