可以std :: begin使用数组参数吗?如果可以,怎么做?

A.E*_*rew 14 c++ arrays iterator stl std

我在使用std::begin()std::end()(从iterator库中)使用c风格的数组参数时遇到了麻烦.

void SetOrigin(const double i_point[3]) {
  Vector v;
  std::copy(
    std::begin(i_point), 
    std::end(i_point), 
    v.begin());
  this->setOrigin(v);
}
Run Code Online (Sandbox Code Playgroud)

这导致Visual Studio 2010出现以下错误(类似于结束):

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.0\vc\include\xutility(995) : see declaration of 'std::begin'
Run Code Online (Sandbox Code Playgroud)

将参数更改为非const会产生相同的结果.

尝试将参数指定为

...
std::begin<const double, 3>(i_point), 
std::end<const double, 3>(i_point),
...
Run Code Online (Sandbox Code Playgroud)

得到:

error C2664: '_Ty *std::begin<const double,3>(_Ty (&)[3])' : cannot convert parameter 1 from 'const double []' to 'const double (&)[3]'
Run Code Online (Sandbox Code Playgroud)

是不是可以std::begin在数组参数上使用因为它们会衰减到指针?有没有解决这个问题的技巧,或者最好不要在数组参数上使用迭代器函数?

Jer*_*fin 17

是的,std::begin并且std::end 可以与为C风格的数组参数工作.

诀窍在于传递一个C样式数组的参数.当您将1D数组指定为普通函数的正常参数时,其类型将从"数组T"静默调整为"指向T".当你调用那个函数时,传递的不是数组(作为数组),而是指向数组第一个元素的指针.

但是,可以通过引用传递数组到函数模板:

template <class T, size_t N>
void function(T (&array)[N]) {
   // function body here
}
Run Code Online (Sandbox Code Playgroud)

这种情况下,你传递一个实际的数组(尽管是通过引用)而不是指针,你可以使用std::begin并且std::end非常好.例如:

template <class T, size_t N>
T sum(T (&array)[N]) { 
    return std::accumulate(std::begin(array), std::end(array), T());
}
Run Code Online (Sandbox Code Playgroud)

现在传递一个数组是微不足道的,例如:

int array[] = {1, 2, 3, 4};

auto total = sum(array);
Run Code Online (Sandbox Code Playgroud)

std::beginstd::end它们本身的实现类似sum- 数组通过引用传递,所以它们看起来像这样:

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;
}
Run Code Online (Sandbox Code Playgroud)

请注意,尽管最近这些已添加到标准中,但它们并不需要任何特别棘手的模板使用,因此上面的实现应该可以使用普通的旧C++ 98编译器(如果内存服务,即使使用pre标准编译器,如VC++ 6).