一种值类型的容器迭代器模板

Container Iterator Template for one value type

你之前帮助过我,所以我又来了一个问题,希望得到答案。

我有一个函数可以处理一系列 std::complex<float> 值。我最初尝试的函数定义是

// Example 1
using namespace std; // not in original code
Errc const& process(vector<complex<float>>::iterator begin, vector<complex<float>>::iterator end);

然而,这仅适用于向量,不适用于 C 样式数组、std::arrays、范围等

经过一些摆弄、很多 Google 和一点点运气,我设法构建了这个:

// Example 2
using namespace std; // not in original code
template<
    template<typename T> class C,
    typename T,
    typename C<T>::iterator iterator
    >
Errc const& process(typename C<T>::iterator begin, typename C<T>::iterator end);

我什至不确定这是否有效,但至少可以编译。我认为它的作用是定义一个函数来处理具有任意值类型的任何容器。这将是一个问题,因为我只能处理 std::complex (或者类似的复杂浮点值)但不能处理 std::string 例如。

我想做的事情:

// Example 3
using namespace std; // not in original code
template<
    template<typename complex<float>> class C,
    typename C<complex<float>>::iterator iterator
    >
Errc const& process(typename C<complex<float>>::iterator begin, typename C<complex<float>>::iterator end);

但这显然不是这样做的方法。我有 60% 的把握肯定我在示例 2 中也搞砸了。

非常感谢任何帮助或提示。谢谢

您可以使用 std::iterator_traits 并将迭代器的 value_type 与您想要支持的类型进行比较:

#include <iterator>
#include <type_traits>

template<class It, std::enable_if_t<
    std::is_same_v<class std::iterator_traits<It>::value_type,
                   std::complex<float>
    >, int> = 0>
Errc const& process(It begin, It end) {
   //...
}

选择:

template<class It>
std::enable_if_t<std::is_same_v<class std::iterator_traits<It>::value_type,
                                std::complex<float>>, Errc const&>
process(It begin, It end) {
    //...
}

如果不需要SFINAE,static_assert:

template<class It>
Errc const& process(It begin, It end) {
    static_assert(
        std::is_same_v<class std::iterator_traits<It>::value_type,
                       std::complex<float>>);
    //...
}

你的例子 2 几乎是正确的

template<
    template<typename T> class C,
    typename T,
    typename C<T>::iterator iterator // That is wrong
    >
Errc const& process(typename C<T>::iterator begin, typename C<T>::iterator end);

应该是:

template<template <typename> class C, typename T>
Errc const& process(typename C<T>::iterator begin, typename C<T>::iterator end);

但问题是 C/T 不可推导,您必须这样称呼它:

process<std::vector, std::complex<float>>(v.begin(), v.end());

并且 C-arraystd::array 都不匹配 template <typename> class C(并且 std::vector 也有默认分配器:-/)

简单点就是

template<typename Iterator>
Errc const& process(Iterator begin, Iterator end);

可能与一些 SFINAE

template <typename Iterator,
          std::enable_if_t<std::is_same_v<std::complex<float>,
                                          std::iterator_traits<Iterator>::value_type>, int> = 0>
Errc const& process(Iterator begin, Iterator end);

或 C++20 要求:

template <typename Iterator>
Errc const& process(Iterator begin, Iterator end)
requires (std::is_same_v<std::complex<float>, std::iterator_traits<Iterator>::value_type);

如果您只需要 连续 个序列,您可以使用 std::span

Errc const& process(std::span<std::complex<float>)