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

enable_if to check if value type of iterator is a pair

本文关键字:是否 类型 if 检查 迭代器 enable      更新时间:2023-10-16

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

但是,当我将此函数与映射迭代器一起使用时,我从 clang (Xcode 8.3( 收到以下错误消息:

忽略候选模板:无法将"enable_if"与"__map_iterator"匹配

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

在检查__map_iterator类型时,看起来它应该与is_pair检查相匹配。

最好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现在是一个通用参考。

完整示例:

#include <type_traits>
#include <utility>
#include <map>
template <typename>
struct is_pair : std::false_type
{ };
template <typename T, typename U>
struct is_pair<std::pair<T, U>> : std::true_type
{ };

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.
}
int main()
{
    std::map<int, int> foo{
        { 1, 2 },
        { 3, 4 },
    };
    do_stuff(foo.begin());
    return 0;
}

活在 gcc.godbolt.org

我想

通了,基本上是: SFINAE 在返回类型中工作,但不作为模板参数工作

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

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)
引用

是必需的,因为我需要对映射内值的实际引用。

不需要检查的常量版本。

我使用了类似于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。

相关文章: