enable_if检查迭代器的值类型是否为一对

时间:2017-05-16 04:27:49

标签: c++ c++11

我想为值类型为一对的迭代器编写一个专门的模板函数。我的期望是它应该匹配std :: map的迭代器。

为了检测这对:

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
{ };

然后我在函数声明中使用enable_if:

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

然而,当我将这个函数与map迭代器一起使用时,我从clang(Xcode 8.3)获得以下错误消息:

  

忽略了候选模板:无法匹配&#39; enable_if&#39;反对&#39; __ map_iterator&#39;

如果没有进一步解释,为什么启用如果没有匹配。

检查__map_iterator的类型时,看起来应该匹配is_pair check。

3 个答案:

答案 0 :(得分:5)

最好将cmp移动到另一个默认模板参数,如下所示:

std::enable_if

这不会阻止参数推断,因为template<class ITR, typename = typename std::enable_if<is_pair<typename ITR::value_type>::value, ITR>::type> decltype(auto) do_stuff(ITR && itr) { //access of itr->second ok. } 现在是一个通用参考。

完整示例:

ITR && itr

Live on gcc.godbolt.org

答案 1 :(得分:1)

我想通了,基本上是:SFINAE working in return type but not as template parameter

所以最后我使用了这个签名:

template<class ITR>
typename std::enable_if_t<is_pair<typename ITR::value_type>::value, ITR>::value_type::second_type& get_value_from_iterator(ITR itr)

引用是必需的,因为我需要实际引用地图内的值。

检查的const版本不是必需的。

答案 2 :(得分:0)

我使用的代码类似于GreenScape提出的代码,但是我做了一些小的调整。

我改变了

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

进入

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

使用此功能,不仅可以使用std :: vector,还可以使用std :: array。