std::begin 可以使用数组参数吗?如果可以,如何?
我在使用 std::begin()
和 std::end()
(来自 iterator
库)和 c- 时遇到问题样式数组参数.
I have trouble using std::begin()
and std::end()
(from the iterator
library) with c-style array parameters.
void SetOrigin(const double i_point[3]) {
Vector v;
std::copy(
std::begin(i_point),
std::end(i_point),
v.begin());
this->setOrigin(v);
}
这会导致 Visual Studio 2010 出现以下错误(结束时类似):
This results in the following error with Visual Studio 2010 (and similar for end):
error C2784: '_Ty *std::begin(_Ty (&)[_Size])' : could not deduce template argument for '_Ty (&)[_Size]' from 'const double []'
1> c:program files (x86)microsoft visual studio 10.0vcincludexutility(995) : see declaration of 'std::begin'
将参数更改为非常量会得到相同的结果.
Changing the parameter to non-const gives same result.
试图将参数指定为
...
std::begin<const double, 3>(i_point),
std::end<const double, 3>(i_point),
...
给予:
error C2664: '_Ty *std::begin<const double,3>(_Ty (&)[3])' : cannot convert parameter 1 from 'const double []' to 'const double (&)[3]'
是不是不可能在数组参数上使用 std::begin
因为它们衰减为指针?有什么技巧可以解决这个问题,还是最好不要对数组参数使用迭代器函数?
Is it just not possible to use std::begin
on array parameters because they decay to pointers? Is there a trick to get around this or is it best just to not use the iterator functions on array parameters?
推荐答案
可以,std::begin
和 std::end
可以使用 C 样式数组的参数.
Yes, std::begin
and std::end
can work with parameters that are C style arrays.
诀窍在于传递一个 C 样式数组的参数.当您将一维数组指定为普通函数的普通参数时,其类型会默默地从T 数组"调整为指向 T 的指针".当您调用该函数时,传递的不是数组(作为数组),而是指向数组第一个元素的指针.
The trick is in passing a parameter that's a C style array. When you specify a 1D array as a normal parameter to a normal function, its type is silently adjusted from "array of T" to "pointer to T". When you call that function, what gets passed isn't the array (as an array), but a pointer to the first element of the array.
但是,可以通过引用函数模板来传递数组:
It is, however, possible to pass an array by reference to a function template:
template <class T, size_t N>
void function(T (&array)[N]) {
// function body here
}
在 this 的情况下,您传递的是一个实际的数组(尽管是通过引用)而不是一个指针,您可以使用 std::begin
和 std::end
非常好.例如:
In this case, where you're passing an actual array (albeit, by reference) rather than a pointer, you can use std::begin
and std::end
perfectly well. For example:
template <class T, size_t N>
T sum(T (&array)[N]) {
return std::accumulate(std::begin(array), std::end(array), T());
}
现在传递一个数组很简单,比如:
Now passing an array is trivial, such as:
int array[] = {1, 2, 3, 4};
auto total = sum(array);
std::begin
和 std::end
本身的实现类似于 sum
――数组是通过引用传递的,所以它们可能看起来像这样:
std::begin
and std::end
themselves are implemented similarly to sum
--the array is passed by reference, so they can look something like this:
template <class T, size_t N>
T *begin(T (&array)[N]) {
return array;
}
template <class T, size_t N>
T *end(T (&array)[N]) {
return array + N;
}
请注意,尽管这些是最近添加到标准中的,但它们不需要任何特别棘手的模板使用,因此上面的实现应该可以在普通的旧 C++98 编译器上正常工作(如果没有记错的话,即使使用 VC++ 6 等预标准编译器).
Note that although these were added to the standard more recently, they don't require any particularly tricky use of templates, so the implementation above should work fine with a plain old C++98 compiler (and, if memory serves, even with pre-standard compilers such as VC++ 6).
相关文章