Как скомпилировать код на С ++, который использует рекурсивные вариационные шаблоны с помощью icpc17? - PullRequest
0 голосов
/ 18 января 2019

Я хочу скомпилировать версию матричного векторного продукта на основе шаблонов с помощью компилятора icpc 17 (icpc (ICC) 17.0.4 20170411). Код компилируется без проблем как с clang, так и с gcc. Тем не менее, с icpc компиляция кажется зависает (я ждал около часа). Кто-нибудь знает о задокументированной ошибке icpc, с которой я здесь сталкиваюсь, и если да, то есть кто-нибудь, как обойти эту ошибку?

#ifndef UTILS_MATRIX_VECTOR_PRODUCT_HPP
#define UTILS_MATRIX_VECTOR_PRODUCT_HPP

#include <array>
#include <utility>

namespace Utils {

namespace detail {

template <int c, typename T> struct mul {
  constexpr T operator()(const T a) const { return c * a; }
};

template <typename T> struct mul<0, T> {
  constexpr T operator()(const T a) const { return T{}; }
};

template <typename T> struct mul<1, T> {
  constexpr T operator()(const T a) const { return a; }
};

template <int I, typename T, std::size_t N, int c, int... cs>
struct inner_product_template_impl {
  constexpr T operator()(std::array<T, N> const &a) const {
    return mul<c, T>{}(std::get<I>(a)) +
           inner_product_template_impl<I + 1, T, N, cs...>{}(a);
  }
};

template <int I, typename T, std::size_t N, int c>
struct inner_product_template_impl<I, T, N, c> {
  constexpr T operator()(std::array<T, N> const &a) const {
    return mul<c, T>{}(std::get<I>(a));
  }
};

template <typename T, std::size_t N,
          const std::array<std::array<int, N>, N> &matrix,
          std::size_t row_index, std::size_t... column_indices>
constexpr T inner_product_helper(const std::array<T, N> &vec,
                                 std::index_sequence<column_indices...>) {
  return inner_product_template_impl<
      0, T, N, std::get<column_indices>(std::get<row_index>(matrix))...>{}(vec);
}

template <typename T, std::size_t N,
          const std::array<std::array<int, N>, N> &matrix,
          std::size_t row_index>
constexpr T inner_product_template(const std::array<T, N> &vec) {
  return detail::inner_product_helper<T, N, matrix, row_index>(
      vec, std::make_index_sequence<N>{});
}

template <typename T, std::size_t N,
          const std::array<std::array<int, N>, N> &matrix,
          std::size_t... column_indices>
constexpr std::array<T, N>
matrix_vector_product_helper(const std::array<T, N> &vec,
                             std::index_sequence<column_indices...>) {
  return std::array<T, N>{
      {inner_product_template<T, N, matrix, column_indices>(vec)...}};
}

} // namespace detail

template <typename T, std::size_t N,
          const std::array<std::array<int, N>, N> &matrix>
constexpr std::array<T, N> matrix_vector_product(const std::array<T, N> &vec) {
  return detail::matrix_vector_product_helper<T, N, matrix>(
      vec, std::make_index_sequence<N>{});
}

} // namespace Utils

#endif

Для рабочего примера можно использовать следующий исходный файл:

#include <array>
#include <iostream>

#include "matrix_vector_product.hpp"

static constexpr const std::array<std::array<int, 19>, 19>
    matrix =
    {{{{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}},
      {{0, 1, -1, 0, 0, 0, 0, 1, -1, 1, -1, 1, -1, 1, -1, 0, 0, 0, 0}},
      {{0, 0, 0, 1, -1, 0, 0, 1, -1, -1, 1, 0, 0, 0, 0, 1, -1, 1, -1}},
      {{0, 0, 0, 0, 0, 1, -1, 0, 0, 0, 0, 1, -1, -1, 1, 1, -1, -1, 1}},
      {{-1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}},
      {{0, 1, 1, -1, -1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, -1, -1, -1, -1}},
      {{-0, 1, 1, 1, 1, -2, -2, 2, 2, 2, 2, -1, -1, -1, -1, -1, -1, -1, -1}},
      {{0, 0, 0, 0, 0, 0, 0, 1, 1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0}},
      {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, -1, -1, 0, 0, 0, 0}},
      {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, -1, -1}},
      {{0, -2, 2, 0, 0, 0, 0, 1, -1, 1, -1, 1, -1, 1, -1, 0, 0, 0, 0}},
      {{0, 0, 0, -2, 2, 0, 0, 1, -1, -1, 1, 0, 0, 0, 0, 1, -1, 1, -1}},
      {{0, 0, 0, 0, 0, -2, 2, 0, 0, 0, 0, 1, -1, -1, 1, 1, -1, -1, 1}},
      {{0, -0, 0, 0, 0, 0, 0, 1, -1, 1, -1, -1, 1, -1, 1, 0, 0, 0, 0}},
      {{0, 0, 0, -0, 0, 0, 0, 1, -1, -1, 1, 0, 0, 0, 0, -1, 1, -1, 1}},
      {{0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 1, -1, -1, 1, -1, 1, 1, -1}},
      {{1, -2, -2, -2, -2, -2, -2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}},
      {{0, -1, -1, 1, 1, -0, -0, 0, 0, 0, 0, 1, 1, 1, 1, -1, -1, -1, -1}},
      {{0, -1, -1, -1, -1, 2, 2, 2, 2, 2, 2, -1, -1, -1, -1, -1, -1, -1, -1}}}};

int main() {
    std::array<double, 19> vector{{4,3,5,2,3,4,5,6,6,4,24,7,8,2,3,9,2,32,2}};
    auto const result = Utils::matrix_vector_product<double, 19, matrix>(vector);
    for (auto const& res : result) {
        std::cout << res << "\n";
    }
    return 0;
}

Я пытался скомпилировать с

icpc -std=c++14 main.cpp
...