如何消除'Only index into arrays using constant expressions'警告?

How to eliminate 'Only index into arrays using constant expressions' warning?

我写了一个kd-tree模板,参数是自然数K。

作为模板的一部分,我编写了以下函数来计算两点之间的距离(kd_point 是 std::array 的别名)

template <unsigned K>
float kd_tree<K>::DistanceSq(const kd_point &P, const kd_point &Q)
{
    float Sum = 0;

    for (unsigned i = 0; i < K; i++)
        Sum += (P[i] - Q[i]) * (P[i] - Q[i]);

    return Sum;
}

我已经打开 "Enable C++ Core Check (Release)",它给了我警告。这个例程有没有正确的写法来消除警告?

既然你在评论中提到你的 kd_point 支持基于范围的迭代(所以我假设可以 return 迭代器),你可以在没有原始循环的情况下重写函数。改用标准库中的命名算法:

template <unsigned K>
float kd_tree<K>::DistanceSq(const kd_point &P, const kd_point &Q)
{
  return std::inner_product(
    begin(P), end(P), begin(Q), 0.0f, std::plus<float>{},
    [](float pi, float qi) {
      return (pi - qi)*(pi - qi);
    }
  );
}

当然,标准库可以免除警告。如果(在这种情况下)用命名操作替换原始循环的边际收益对您没有吸引力,请考虑如果您使用支持 C++17 的编译器返回此代码,您将能够几乎毫不费力地并行化它:

template <unsigned K>
float kd_tree<K>::DistanceSq(const kd_point &P, const kd_point &Q)
{
  return std::transform_reduce(std::execution::par, // Parallel execution enabled 
    begin(P), end(P), begin(Q), 0.0f, std::plus<float>{},
    [](float pi, float qi) {
      return (pi - qi)*(pi - qi);
    }
  );
}

Answer by StoryTeller 可能是解决此特定任务的最合适的 C++ 方法。

我想补充一点,一般来说,如果你想同时迭代两个序列而不是一个序列,你可以使用 "secret overload of boost::range::for_each",接受两个范围:

#include <boost/range/algorithm_ext/for_each.hpp>

template <unsigned K>
float kd_tree<K>::DistanceSq(const kd_point &P, const kd_point &Q)
{
    float Sum = 0;

    boost::range::for_each(P, Q, [&Sum](float p, float q) 
    { 
      Sum += (p - q) * (p - q);
    });        

    return Sum;
}

请注意,与标准算法类似,此算法是 header-only,不会给您的代码带来任何库依赖性。