Detect if type is a “mapping”

别说谁变了你拦得住时间么 提交于 2019-12-05 11:59:30
is_pair_v<std::iterator_traits<typename Container::iterator>::value_type>

should be

is_pair_v<typename std::iterator_traits<typename Container::iterator>::value_type>

because value_type is a type. Without the typename, it will be parsed as a value and fail the enable_if, thus falling back to the primary template.

The reason your tests in main yield the correct value is because the templates there have already been instantiated and there is no ambiguity whether value_type is a type or value.

The second error is your primary template

template<typename...>

should be

template<typename, typename = void>

Otherwise, is_mapping<T> will never be the specialization with two arguments because the argument count mismatch.

Live

The compiler is not selecting the partially specialized struct. There are two reasons for this:

  1. You do an enable_if off of is_pair_v<std::iterator_traits<typename Container::iterator>::value_type>. The compiler would see std::iterator_traits<...>::value_type as a value instead of a type, but SFINAE kicks in and this is just silently removed.
  2. Using template <typename...> makes it so that the specialization isn't selected. If I am right, this is because is_mapping<T> could either resolve to is_mapping<T> using the initial definition, or is_mapping<T, void> using the specialization. It seems that is_mapping<T> is preferred in this case.

    Fixing this is as easy as changing that to template <typename, typename = void>:

template <typename, typename = void>
struct is_mapping : std::false_type { };

template <typename Container>
struct is_mapping<Container, std::enable_if_t<
    is_pair_v<typename std::iterator_traits<typename Container::iterator>::value_type>
>> : std::true_type { };

However, a simpler implementation of is_mapping would be:

template <typename Container>
struct is_mapping : is_pair<
    typename std::iterator_traits<typename Container::iterator>::value_type
> {};

Basically, your version looks like

if (is_pair(...)) return true;
else return false;

Whereas you could simply do

return is_pair(...)
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!