Мне нужно создать функцию шаблона constexpr для суммирования контейнера и передать статическое утверждение. Это мой код, но у меня есть вопросы.
#include <iostream>
#include <array>
using namespace std;
template <typename T>
constexpr auto Sum(const T& arr)
{
using arrType = decltype(*arr.begin());
arrType res = 0;
for (auto it = arr.begin(); it != arr.end(); it++) {
res += *it;
}
return res;
}
int main()
{
constexpr array<int, 3> base{5, 2, 0};
static_assert(Sum(base) == 7);
return 0;
}
Применение std::remove_reference и std::remove_cv приводит к компиляции.
#include <iostream>
#include <type_traits>
#include <array>
using namespace std;
template <typename T>
constexpr auto Sum(const T& arr)
{
using arrType = remove_cv_t<remove_reference_t<decltype(*arr.begin())>>;
arrType res = 0;
for (auto it = arr.begin(); it != arr.end(); it++) {
res += *it;
}
return res;
}
int main()
{
constexpr array<int, 3> base{5, 2, 0};
static_assert(Sum(base) == 7);
return 0;
}
FWIW, это можно упростить с помощью std::remove_cvref_t<...> в C++20.
Ваш код не компилируется, потому что, поскольку arr является постоянной ссылкой, decltype(*arr.begin()) является const int. Итак, ваш res — это const, и вы не можете назначить его в своем цикле.
Чтобы исправить только эту ошибку, вы должны использовать std::decay, то есть:
using arrType = std::decay_t<decltype(*arr.begin())>;
Вы не указываете, что вы подразумеваете под «контейнером». Если вы имеете в виду определение стандартной библиотеки (которое поддерживается всеми контейнерами STL), вы можете вместо этого использовать value_type, а также еще больше упростить свой код:
template <typename T>
constexpr auto Sum(const T& arr) {
typename T::value_type result{};
for (auto const& x : arr) {
result += x;
}
return result;
}
Если у вас C++20, вы также можете использовать std::accumulate:
template <typename T>
constexpr auto Sum(const T& arr)
{
return std::accumulate(arr.begin(), arr.end(),
typename T::value_type{});
}
Обратите внимание, что std::accumulate является только constexpr, начиная с C++20.
Спасибо, хороший момент, добавил это к моему ответу.
Не все контейнеры можно конструировать с помощью constexpr, поэтому в общем случае это не сработает. И, таким образом, ваш код вернется к оценке во время выполнения в этих случаях.