enable_if to check if value type of iterator is a pair

Viewed 1946

I would like to write a specialised template function for iterators whose value type is a pair. My expectation is that this should match iterators of std::map.

In order to detect the pair:

template <typename>
struct is_pair : std::false_type
{ };

template <typename T, typename U>
struct is_pair<std::pair<T, U>> : std::true_type
{ };

// also tried this, but it didn't help
template <typename T, typename U>
struct is_pair<std::pair<const T, U>> : std::true_type
{ };

Then i use enable_if in the function declaration:

template<class ITR>
decltype(auto) do_stuff(
        std::enable_if<is_pair<typename ITR::value_type>::value, ITR> itr) {
    //access of itr->second ok.
}

However, when i use this function with a map iterator I get the following error messages from clang (Xcode 8.3):

Candidate template ignored: could not match 'enable_if' against '__map_iterator'

With no further explanation why enable if didn't match.

When inspecting the type of __map_iterator, it looks like it should match is_pair check.

3 Answers

I used code similar to what GreenScape proposed, but I made a small adjustment.

I changed

template<class ITR, typename = typename std::enable_if<is_pair<typename ITR::value_type>::value, ITR>::type>

into

template<class ITR, typename = typename std::enable_if<is_pair<typename std::iterator_traits<ITR>::value_type>::value, ITR>::type>

Using this, not only std::vector works, but also std::array.

Related