我想为值类型为一对的迭代器编写一个专门的模板函数。我的期望是它应该匹配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。
答案 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
答案 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。