Создайте функцию шаблона constexpr для суммирования любого контейнера в C++

Мне нужно создать функцию шаблона constexpr для суммирования контейнера и передать статическое утверждение. Это мой код, но у меня есть вопросы.

  1. Я получил эту ошибку: назначение ссылки только для чтения «res».
  2. Правильно ли написана функция суммы?
#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;
}

Не все контейнеры можно конструировать с помощью constexpr, поэтому в общем случае это не сработает. И, таким образом, ваш код вернется к оценке во время выполнения в этих случаях.

Pepijn Kramer 16.02.2023 16:29
Laravel с Turbo JS
Laravel с Turbo JS
Turbo - это библиотека JavaScript для упрощения создания быстрых и высокоинтерактивных веб-приложений. Она работает с помощью техники под названием...
Типы ввода HTML: Лучшие практики и советы
Типы ввода HTML: Лучшие практики и советы
HTML, или HyperText Markup Language , является стандартным языком разметки, используемым для создания веб-страниц. Типы ввода HTML - это различные...
Аутсорсинг разработки PHP для индивидуальных веб-решений
Аутсорсинг разработки PHP для индивидуальных веб-решений
Услуги PHP-разработки могут быть экономически эффективным решением для компаний, которые ищут высококачественные услуги веб-разработки по доступным...
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
Слишком много useState? Давайте useReducer!
Слишком много useState? Давайте useReducer!
Современный фронтенд похож на старую добрую веб-разработку, но с одной загвоздкой: страница в браузере так же сложна, как и бэкенд.
Узнайте, как использовать теги &lt;ul&gt; и &lt;li&gt; для создания неупорядоченных списков в HTML
Узнайте, как использовать теги <ul> и <li> для создания неупорядоченных списков в HTML
HTML предоставляет множество тегов для структурирования и организации содержимого веб-страницы. Одним из наиболее часто используемых тегов для...
2
1
59
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Применение 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.

NathanOliver 16.02.2023 16:16
Ответ принят как подходящий

Ваш код не компилируется, потому что, поскольку 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.

Pepijn Kramer 16.02.2023 16:30

Спасибо, хороший момент, добавил это к моему ответу.

Chronial 16.02.2023 18:03

Другие вопросы по теме

Где лучше хранить random_device/mt19937?
Есть ли существенная разница между использованием встроенного генератора случайных чисел и использованием криптографического генератора случайных чисел?
Вставить по порядку ряд битов в байт (u_int8_t)
С++: нужен ли виртуальный деструктор для объектов, выделенных в стеке?
Имеет ли GCC11 регрессию, в которой он неправильно принимает указатель на массив абстрактного класса
Явное создание объектов с помощью тривиального конструктора по умолчанию с использованием нового размещения в C++17.
Каков наиболее ресурсоэффективный способ проверить, содержат ли два списка std::list одинаковые уникальные элементы?
С++: получение случайных символов в качестве вывода, не знаю, почему
Unordered_map из собственного типа путем перегрузки оператора() не работает
Измерение вертикального расстояния бинаризованного изображения (Open CV) C++