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

问题描述

你之前帮助过我,所以我再次提出另一个问题,希望得到答案。

我有一个处理一系列 master 值的函数。我对函数定义的最初尝试是

std::complex<float>

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

经过一番摆弄、大量的谷歌和一点点运气,我设法构建了这个:

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

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

我想做什么:

// 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);

但这显然不是这样做的方法。我大约有 60% 的把握确定我在示例 2 中也搞砸了一些事情。

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

解决方法

您的示例 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>)
,

您可以使用 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>>);
    //...
}