Подтвердить что ты не робот

Умножение каждого элемента std:: array во время компиляции

Я хотел бы преобразовать std::array в другой std::array, умножая каждый его элемент на определенное число.

То, что у меня прямо сейчас, очевидно, не работает:

#include <array>
#include <iostream>
#include <utility>

template <class T, size_t... Is, size_t N>
constexpr std::array<T, N> multiply(std::array<T, N> const &src,
                                  std::index_sequence<Is...>) {
    return std::array<T, N>{{src[Is]...}}; // How can I multiply each of src elements?
}

int main(int argc, char *argv[]) {
    constexpr std::array<int, 3> arr = {1, 2, 3};
    constexpr auto t = multiply(arr, std::make_index_sequence<3>{});
    for (auto &el : t) std::cout << el << std::endl;
    return 0;
}

Мой вопрос: как я могу перебирать каждый элемент во время компиляции или как я могу применить ту же функцию (в моем случае: умножить на 2) во время компиляции?

4b9b3361

Ответ 1

Вы можете сделать это следующим образом:

template<typename T>
constexpr T mult(T const &a, T const &b) { return a * b; }

template <class T, size_t... Is, size_t N>
constexpr std::array<T, N> multiply(std::array<T, N> const &src, 
                                    std::index_sequence<Is...>) {
  return std::array<T, N>{{mult(src[Is], src[Is])...}}; 
}

Live Demo

Или, если вы хотите умножить на число, вы можете изменить на:

template<typename T>
constexpr T mult(T const &a, T const &b) { return a * b; }

template <class T, size_t... Is, size_t N>
constexpr std::array<T, N> multiply(std::array<T, N> const &src, 
                                    std::index_sequence<Is...>, T const &mul) {
  return std::array<T, N>{{mult(src[Is], mul)...}}; 
}

Live Demo

Как описано в cppreference:

Образец, за которым следует многоточие, в котором имя хотя бы одного пакета параметров появляется хотя бы один раз, разворачивается в ноль или больше экземпляров экземпляра с разделителями-запятыми, где имя пакета параметров заменяется каждым типов из упаковки, по порядку. Расширения пакета могут возникать только в контексте расширения пакета. Это по существу следующие:

  • исправлена ​​инициализация
  • списки инициализаторов
  • агрегатные инициализации
  • вызовы функций
  • инициализации массива

Edit:

Как T.C. в комментариях вы также можете сделать это так же просто, как:

template <class T, size_t... Is, size_t N>
constexpr std::array<T, N> multiply(std::array<T, N> const &src, std::index_sequence<Is...>, T const &mul) {
  return std::array<T, N>{{(src[Is] * mul)...}}; 
}

Live Demo