У меня есть constexpr std::array<int, N> v1{0}, v2{0};
, который ведет себя как большие целые числа. Итак, я пишу multiply
функцию, чтобы найти произведение чисел.
#include <array>
#include <cstdint>
using namespace std;
template <int N>
constexpr array<int, 2 * N> multiply(const array<int, N> &a,
const array<int, N> &b) {
const int as = N, bs = N, rs = as + bs;
array<int, rs> result{0};
__int128_t carry = 0;
auto pr = begin(result);
for (int r = 0, lim = min(rs, as + bs - 1); r < lim; ++r) {
int i = r >= as ? as - 1 : r,
j = r - i,
k = i < bs - j ? i + 1 : bs - j; // min(i+1, bs-j);
auto pa = begin(a) + i;
auto pb = begin(b) + j;
while (k--) {
carry += static_cast<__int128_t>(*(pa--)) * (*(pb++));
}
*(pr++) = static_cast<int64_t>(carry);
}
return result;
}
int main() {
constexpr int N = 20;
constexpr array<int, N> v1{0}, v2{0};
constexpr array<int, 2 *N> result = multiply<N>(v1, v2);
return result[1];
}
Обратите внимание, что функция умножения неверна, чтобы сделать ее минимальной.
Когда я компилирую этот код, используя clang++ -std=c++17 -Wall -O0 example.cc
, я ошибочно получаем:
example.cc:30:32: error: constexpr variable 'result' must be initialized by a constant expression
constexpr array<int, 2 *N> result = multiply<N>(v1, v2);
^ ~~~~~~~~~~~~~~~~~~~
example.cc:20:50: note: cannot refer to element -1 of array of 20 elements in a constant expression
carry += static_cast<__int128_t>(*(pa--)) * (*(pb++));
^
example.cc:30:41: note: in call to 'multiply(v1, v2)'
constexpr array<int, 2 *N> result = multiply<N>(v1, v2);
^
1 error generated.
Но это правильно компилируется с g cc.
Почему я думаю, что ошибка Clang это ошибка:
Чтобы проверить, есть ли доступ за пределами привязки, я включил режим отладки в libstdc ++ и скомпилировал с использованием g++ -std=c++17 -Wall -D_GLIBCXX_DEBUG -g -O0 example.cc
, и не было cra sh, что могло бы произойти, если бы был выход за пределы access.
Также под дезинфицирующим средством (g++ -fsanitize=address,undefined -fno-omit-frame-pointer
) код был успешно выполнен.
Мне любопытно, почему clang утверждает, что он не имеет связанного доступа, хотя эксперименты ясно показывают, что это не так.