std::array::iterator 忽略尺寸模板
std::array::iterator that ignores the size template
我正在实现一个函数,该函数想要遍历 std::array 中的多个元素,但我并不关心 std::array 有多长。所以我想到了以下功能:
#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());
}
除了std::array<bool,0>
,我对此很满意。我的问题是,是否有另一种方法来指定此函数所需的迭代器?
更新
有些事情我应该提一下。当然,这段代码是更大范围的一部分,我尽量隐藏了更多细节。
- 我想确保正在使用的迭代器是
bool
s.
- 我正在使用 C++14
- 该函数是 class 接口的一部分,我希望能够处理多个数组大小。我不想打扰接口的实现者确切知道数组的大小。
class MyInterface
{
public:
virtual foo(std::array<bool,0>::const_iterator begin, std::array<bool,0>::const_iterator end) = 0;
~MyInterface() = default;
};
我记得虚函数不能模板化。这意味着我将不得不为我的整个界面制作模板,这将完全失去我为什么首先尝试这个的要点。
使用模板:
template <size_t N>
void foo(std::array<bool,N>::const_iterator begin, std::array<bool,N>::const_iterator end)
{
printf("iterator");
}
现在只要两个迭代器都来自大小为 N
的数组,这个函数就可以工作。
如果你想接受来自不同大小数组的迭代器,你只需要为第二个迭代器添加另一个模板参数,如
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");
}
您可以将其作为函数模板作为
template <typename I>
void foo(I begin, I end)
{
std::cout << "iterator";
}
你不需要关心容器类型(和大小),你可以传递std::array
、std::vector
和std::string
等迭代器,甚至是原始指针(也满足迭代器的要求)
如果函数在引用 std::array 冗余时接受两个迭代器。只需将函数声明为
template <class Iterator>
void foo( Iterator first, Iterator last );
在声明中,您可以命名与函数中使用的迭代器类型相对应的迭代器,例如
template <class ForwardIterator>
void foo( ForwardIterator first, ForwardIterator last );
或者您可以使用名称 BidirectionalIterator
或 RandomAccessIterator
代替名称 ForwardIterator
进行自我记录。
如果您需要知道迭代器的值类型,您可以使用不同的方法。例如
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;
//...
}
}
在这种情况下,您将拥有灵活的函数定义。例如,如果将来您将 std::array<N, bool>
更改为 std::vector<bool>
,该功能将照常工作。
只需使用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);
}
我正在实现一个函数,该函数想要遍历 std::array 中的多个元素,但我并不关心 std::array 有多长。所以我想到了以下功能:
#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());
}
除了std::array<bool,0>
,我对此很满意。我的问题是,是否有另一种方法来指定此函数所需的迭代器?
更新
有些事情我应该提一下。当然,这段代码是更大范围的一部分,我尽量隐藏了更多细节。
- 我想确保正在使用的迭代器是
bool
s. - 我正在使用 C++14
- 该函数是 class 接口的一部分,我希望能够处理多个数组大小。我不想打扰接口的实现者确切知道数组的大小。
class MyInterface
{
public:
virtual foo(std::array<bool,0>::const_iterator begin, std::array<bool,0>::const_iterator end) = 0;
~MyInterface() = default;
};
我记得虚函数不能模板化。这意味着我将不得不为我的整个界面制作模板,这将完全失去我为什么首先尝试这个的要点。
使用模板:
template <size_t N>
void foo(std::array<bool,N>::const_iterator begin, std::array<bool,N>::const_iterator end)
{
printf("iterator");
}
现在只要两个迭代器都来自大小为 N
的数组,这个函数就可以工作。
如果你想接受来自不同大小数组的迭代器,你只需要为第二个迭代器添加另一个模板参数,如
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");
}
您可以将其作为函数模板作为
template <typename I>
void foo(I begin, I end)
{
std::cout << "iterator";
}
你不需要关心容器类型(和大小),你可以传递std::array
、std::vector
和std::string
等迭代器,甚至是原始指针(也满足迭代器的要求)
如果函数在引用 std::array 冗余时接受两个迭代器。只需将函数声明为
template <class Iterator>
void foo( Iterator first, Iterator last );
在声明中,您可以命名与函数中使用的迭代器类型相对应的迭代器,例如
template <class ForwardIterator>
void foo( ForwardIterator first, ForwardIterator last );
或者您可以使用名称 BidirectionalIterator
或 RandomAccessIterator
代替名称 ForwardIterator
进行自我记录。
如果您需要知道迭代器的值类型,您可以使用不同的方法。例如
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;
//...
}
}
在这种情况下,您将拥有灵活的函数定义。例如,如果将来您将 std::array<N, bool>
更改为 std::vector<bool>
,该功能将照常工作。
只需使用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);
}