I'd like to parse c++ containers into another object using their ::iterator
member type. Containers who's iterator member type points to an object of a single type (vectors, queues, etc.) will turn into a list-like object, and containers who's iterator member type points to an std::pair
will turn into a map-like object.
I'm trying to write a member function to detect the latter kind of container, but it does not work. Here's what I have so far:
#include <tuple>
#include <iterator>
#include <type_traits>
template <typename T>
struct is_pair : std::false_type { };
template <typename T, typename U>
struct is_pair<std::pair<T, U>> : std::true_type { };
template <typename T>
constexpr bool is_pair_v = is_pair<T>::value;
template <typename...>
struct is_mapping : std::false_type { };
template <typename Container>
struct is_mapping<Container, std::enable_if_t<
is_pair_v<std::iterator_traits<typename Container::iterator>::value_type>
>> : std::true_type { };
template <typename T>
constexpr bool is_mapping_v = is_mapping<T>::value;
#include <map>
#include <vector>
#include <iostream>
int main() {
std::cout << "is_pair:" << std::endl;
std::cout << "Map: " << is_pair_v<std::iterator_traits<std::map<int, int>::iterator>::value_type> << std::endl;
std::cout << "Vector: " << is_pair_v<std::iterator_traits<std::vector<int>::iterator>::value_type> << std::endl;
std::cout << std::endl;
std::cout << "is_mapping:" << std::endl;
std::cout << "Map: " << is_mapping_v<std::map<int, int>> << std::endl;
std::cout << "Vector: " << is_mapping_v<std::vector<int>> << std::endl;
}
For some reason, is_mapping_v
is always false and the code results in this output:
$ g++ -std=c++14 temp.cc && ./a.out
is_pair:
Map: 1
Vector: 0
is_mapping:
Map: 0
Vector: 0
What is wrong with my code?
Note: This is not the a duplicate of Checking if a type is a map. The answer to that question uses the ::key_type
and ::mapped_type
members to detect the map (It fails for classes such as std::multimap
). I am also explicitly using the fact that the iterator points to std::pair
s later in my code, so checking that makes a lot more sense.