Получение указателя или ссылки на mapped_type из произвольной карты
Изменить: я нашел и написал решение моей проблемы, но я оставил вопрос без ответа, так как мое решение все еще не может быть идеальным.
Я пишу небольшую библиотеку, предназначенную для выполнения подпрограмм на картах карт, но у меня возникают проблемы при разработке набора шаблонов классов, которые позволят мне получить указатель или ссылку (в зависимости от second_type для value_type карты) на карту mapped_type, независимо от типа карты (например, std::map, boost::ptr_map).
Чтобы уточнить, я составил таблицу некоторых типов ввода и желаемых типов вывода.
Case Input Type Output Type
A std::map<int, std::map<int, int> > std::map<int, int>&
B std::map<int, boost::ptr_map<int, int> > boost::ptr_map<int, int>&
C boost::ptr_map<int, std::map<int, int> > std::map<int, int>* const
D std::map<int, std::map<int, int> >* std::map<int, int>&
E std::map<int, boost::ptr_map<int, int> >* boost::ptr_map<int, int>&
F boost::ptr_map<int, std::map<int, int> >* std::map<int, int>* const
Мой код пропускает случаи A, B, D и E, но терпит неудачу в случаях C и F. Вот что я имею до сих пор.
template <class Map>
struct map_utils
{
template <class K>
static typename
boost::remove_pointer<
typename Map::value_type
>::type::second_type&
get(Map& m, const K k)
{
return m[k];
}
template <class K>
static typename
boost::remove_pointer<
typename Map::value_type
>::type::second_type&
get(const Map& m, const K k)
{
return const_cast<Map&>(m)[k];
}
};
template <class Map>
struct map_utils<Map*>
{
template <class T>
static typename
boost::remove_pointer<
typename Map::value_type
>::type::second_type&
get(Map* m, const T t)
{
return (*m)[t];
}
template <class T>
static typename
boost::remove_pointer<
typename Map::value_type
>::type::second_type&
get(const Map* m, const T t)
{
return const_cast<Map*>(m)->operator[](t);
}
};
Я пытаюсь использовать boost::mpl, чтобы сделать это, и это то, что я до сих пор готовил, но я получаю ту же ошибку, используя обе версии кода.
Ошибка.
error: invalid initialization of reference of type ‘std::map<int, double>* const&’ from expression of type ‘boost::ptr_container_detail::reversible_ptr_container<boost::ptr_container_detail::map_config<std::map<int, double>, std::map<int, void*, std::less<int>, std::allocator<std::pair<const int, void*> > >, true>, boost::heap_clone_allocator>::Ty_’
Измененная специализация структуры для работы с l-значениями, которые не являются указателями на карты.
template <class K>
static typename
boost::mpl::if_<
boost::is_pointer<
typename boost::remove_pointer<
typename Map::value_type
>::type::second_type
>,
typename boost::remove_pointer<
typename boost::remove_const<
typename Map::value_type
>::type
>::type::second_type,
typename boost::remove_pointer<
typename Map::value_type
>::type::second_type&
>::type
get(Map& m, const K k)
{
return m[k];
}
2 ответа
C и F кажутся неправильными, сопоставленный тип не является boost::ptr_map. В противном случае кажется, что вы могли бы просто использовать полную специализацию шаблона, чтобы решить, является ли это std::map или boost::ptr_map. Что-то вроде этого:
template <class Map>
class Whatever;
template <class K, class V>
class Whatever<std::map<K, V> >
{
public:
typedef V& Type;
};
template <class K, class V>
class Whatever<std::map<K, V>* >
{
public:
typedef V& Type;
};
template <class K, class V>
class Whatever<boost::ptr_map<K, V> >
{
public:
typedef V* const Type;
};
template <class K, class V>
class Whatever<boost::ptr_map<K, V>* >
{
public:
typedef V* const Type;
};
Я успешно получил код для компиляции и значительно упростил его, используя made_type typedef, например, так:
template <class K>
static typename boost::remove_pointer<
typename Map::mapped_type
>::type&
get(Map& m, const K k)
{
return m[k];
}
Только специальное тело методов должно быть изменено в специализированных версиях структуры, определенной в приведенном выше вопросе, чтобы приспособиться и к указателям на карты. Если вы хотите получить полный список кодов, дайте мне знать, и я дам здесь все это.