如何消除'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,不会给您的代码带来任何库依赖性。
我写了一个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,不会给您的代码带来任何库依赖性。