Как исключить предупреждение «Только индексировать в массивы с использованием константных выражений»?

Я написал шаблон дерева kd, его параметром является натуральное число 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;
}

Я включил «Включить проверку C ++ Core (Release)», и он предупреждает меня. Есть ли правильный способ написать эту процедуру, чтобы устранить предупреждение?

2

Решение

Поскольку вы упоминаете в комментариях, что ваш kd_pointИтерация, основанная на диапазоне поддержки (поэтому я предполагаю, что может возвращать итераторы), вы можете переписать функцию без необработанного цикла. Вместо этого используйте именованные алгоритмы из стандартной библиотеки:

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);
}
);
}
2

Другие решения

Ответ от рассказчик это, вероятно, самый подходящий способ C ++ для решения этой конкретной задачи.

Я хотел бы добавить, что в целом, если вы хотите выполнять итерации не по одной, а по двум последовательностям одновременно, вы можете использовать «секретную перегрузку 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;
}

Обратите внимание, что, как и в случае со стандартными алгоритмами, этот алгоритм предназначен только для заголовков и не вносит никакой зависимости от библиотеки в ваш код.

2

По вопросам рекламы [email protected]