c++ - 如何在 C++ 中为不同的迭代器 value_types 重载函数

标签 c++ templates

我想在 C++ 11 中实现一个带有一对迭代器的模板函数。如果传递了一对迭代器,其值类型是任意类型的 std::pair,则实现应该做一些特殊处理。我试图提出以下定义:

// arbitrary value types
template<typename Iter>
void process(Iter begin, Iter end) {
    for (Iter iter = begin; iter != end; ++iter) {
        std::cout << *iter << "\n";
    }
}

// std::pair value types
template<typename Iter, typename First, typename Second,
    typename std::enable_if<
        std::is_same<
            typename std::iterator_traits<Iter>::value_type, std::pair<First,Second>
            >::value
        >::type* = 0>
void process(Iter begin, Iter end) {
    for (Iter iter = begin; iter != end; ++iter) {
        std::cout << (*iter).first << " " << (*iter).second << "\n";
    }
}

使用以下示例代码:

std::vector<int> int_vec{{1,2,3,4}};
process(int_vec.begin(), int_vec.end());

正确调用函数 process 的第一个定义。然而

std::vector<std::pair<int,std::string>> pair_vec{
    {std::make_pair(1, "First"), std::make_pair(2, "Second")}};
process(pair_vec.begin(), pair_vec.end());

还调用第一个定义并产生错误消息(使用 Clang):

error: invalid operands to binary expression ('ostream' (aka 'basic_ostream<char>') and 'std::__1::pair<int, std::__1::basic_string<char> >')

为什么编译器在那种情况下不选择第二个定义?我需要如何更改重载函数?

最佳答案

在您尝试使用 enable_if 时,您引入了两个非推导上下文的模板参数。编译器无法确定 FirstSecond 是什么,因此总是从重载集中删除重载。从来没有考虑过。

我建议完全回避 SFINAE。如果您正在做的只是涉及对范围内的每个元素执行一些实际操作,只需使用函数重载:

template <class T>
void process_impl(T const& elem) {
    // generic case
    std::cout << elem << '\n';
}

template <class T, class U>
void process_impl(std::pair<T, U> const& elem) {
    // overload for pair
    std::cout << elem.first << ' ' << elem.second << '\n';
}

template <class Iter>
void process(Iter first, Iter last) {
    // if C++14
    std::for_each(first, last, [](auto&& elem){ process_impl(elem); });

    // if C++11
    using E = typename std::iterator_traits<Iter>::reference;
    std::for_each(first, last, [](E elem) { process_impl(elem); });
}

关于c++ - 如何在 C++ 中为不同的迭代器 value_types 重载函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38701475/

相关文章:

c++ - 如何在 vc++ 中使用samplegrabber?样本采集器未定义

c++ - 如何使用 SFINAE 禁用方法重载集?

c++ - 为什么必须在哪里放置 “template”和 “typename”关键字?

c++ - 转发引用、引用限定符和模板成员函数

C++ 可变参数模板和模板模板参数 : error: type/value mismatch at argument 1 in template parameter list

c++ - 根据位置c++从PDF文档中提取文本

c++ - 将字符数组中的字符连接成一个整数

c++ - 使用 block 匹配算法获取纹理点云

c++ - 如何在模板类型名上编译时条件?

templates - 如何使用 C++ 模板传递函数及其签名(haskell 样式)?