简体   繁体   English

忽略大小模板的 std::array::iterator

[英]std::array::iterator that ignores the size template

I am implementing a function that wants to loop over a number of elements in an std::array, but I don't really care how long the std::array is.我正在实现一个 function,它想要遍历 std::array 中的多个元素,但我并不关心 std::array 有多长。 So I was thinking of the following function:所以我在想下面的function:

#include <stdio.h>
#include <array>
#include <iterator>

void foo(std::array<bool,0>::const_iterator begin, std::array<bool,0>::const_iterator end)
{
    printf("iterator");
}

int main()
{
    std::array<bool, 25> one;
    std::array<bool, 33> two;

    foo(one.cbegin(), one.cend());
    foo(two.cbegin(), two.cend());
}

I am quite okay with this, except for the std::array<bool,0> .我对此很满意,除了std::array<bool,0> My question is, is there another way to specify the iterator that is required for this function?我的问题是,是否有另一种方法来指定此 function 所需的迭代器?


Update更新

There are some things I should mention.有些事情我应该提一下。 Of course this code is part of a bigger scope and I tried to hide as much detail as I could.当然,这段代码是更大的 scope 的一部分,我试图尽可能多地隐藏细节。

  1. I want to ensure that the iterator being used is of bool s.我想确保正在使用的迭代器是bool的。
  2. I am using C++14我正在使用 C++14
  3. The function is part of a class interface and I want to be able to handle multiple array sizes. function 是 class 接口的一部分,我希望能够处理多种阵列大小。 I don't want to bother the implementors of the interface to know exactly what the size of the array is.我不想打扰接口的实现者确切地知道数组的大小。
class MyInterface
{
public:
    virtual foo(std::array<bool,0>::const_iterator begin, std::array<bool,0>::const_iterator end) = 0;

    ~MyInterface() = default;
};

I remembered that virtual functions cannot be templated.我记得虚函数不能被模板化。 That means I would have to template my whole interface and that would exactly loose the point of why I was trying this in the first place.这意味着我将不得不对我的整个界面进行模板化,而这将完全失去我最初尝试这个的原因。

You can just make it a function template as您可以将其作为 function 模板

template <typename I>
void foo(I begin, I end)
{
    std::cout << "iterator";
}

You don't need to care about container type (and the size), you can pass iterators of std::array , std::vector and std::string and so on, even raw pointers (which also satisfies iterator's requirements).您不需要关心容器类型(和大小),您可以传递std::arraystd::vectorstd::string等迭代器,甚至是原始指针(这也满足迭代器的要求)。

Just use span :只需使用span

#include <array>
#include <span>

class MyInterface {
public:
    virtual void foo(std::span<bool> barr) = 0;

    // interface destructors should be virtual
    virtual ~MyInterface() = default;
};

void bar(MyInterface& interface) {
    std::array<bool, 42> arr;
    interface.foo(arr);
}

If you don't have access to a C++20 compiler, you may use gsl::span from gsl instead.如果您无法访问 C++20 编译器,则可以使用 gsl 中的gsl gsl::span代替。

Use a template:使用模板:

template <size_t N>
void foo(std::array<bool,N>::const_iterator begin, std::array<bool,N>::const_iterator end)
{
    printf("iterator");
}

And now as long as both iterators come from an array of size N this function will work.现在只要两个迭代器都来自一个大小为N的数组,这个 function 就可以工作。


If you want to accept iterators from different sized arrays, you just need to add another template parameter for the second iterator like如果您想接受来自不同大小的 arrays 的迭代器,您只需为第二个迭代器添加另一个模板参数,例如

template <size_t N, size_t M>
void foo(std::array<bool,N>::const_iterator begin, std::array<bool,M>::const_iterator end)
{
    printf("iterator");
}

If the function accepts two iterators when the referring std::array is redundant.如果 function 在引用 std::array 是多余的时接受两个迭代器。 Just declare the function like只需像这样声明 function

template <class Iterator>
void foo( Iterator first, Iterator last );

In the declaration you can name the iterator that corresponds to the used iterator type in the function like for example在声明中,您可以命名与 function 中使用的迭代器类型对应的迭代器,例如

template <class ForwardIterator>
void foo( ForwardIterator first, ForwardIterator last );

Or instead of the name ForwardIterator you could use the name BidirectionalIterator or RandomAccessIterator for self-documenting.或者代替名称ForwardIterator ,您可以使用名称BidirectionalIteratorRandomAccessIterator进行自我记录。

If you need to know the value type of the iterator you can use different approaches.如果您需要知道迭代器的值类型,您可以使用不同的方法。 For example例如

template <class Iterator>
void foo( Iterator first, Iterator last )
{
    using value_type = typename std::iterator_traits<Iterator>::value_type;
    if ( first != last )
    {
         value_type item1 = *first;
         // or
         auto item2 = *first;
         //
         const auto &item3 = *first;
         //...             
    }
}

In this case you will have a flexible function definition.在这种情况下,您将有一个灵活的 function 定义。 For example if in future you will change std::array<N, bool> to std::vector<bool> the function will as usual work.例如,如果将来您将std::array<N, bool>更改为std::vector<bool> function 将照常工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM