#c #iterator #c 17 #constexpr #dereference
#c #итератор #c 17 #constexpr #разыменование
Вопрос:
При сборке с использованием C 17 / C 20 x64 gcc / clang приведенный ниже фрагмент выдает ошибку компиляции, тогда как отмена ссылки на итератор напрямую через *std::max_element(std::begin(arr), std::end(arr))
работает нормально. Есть идеи относительно того, почему? Я также наблюдал аналогичное поведение с другими стандартными алгоритмами, которые стали constexpr начиная с C 20, например std::upper_bound
int main()
{
constexpr std::array<int,5> arr = {1,2,3,4,5};
constexpr auto it = std::max_element(std::begin(arr), std::end(arr));
}
source>:11:73: error: '(((std::array<int, 5>::const_pointer)(amp; arr.std::array<int, 5>::_M_elems)) 16)' is not a constant expression
11 | constexpr auto it = std::max_element(std::begin(arr), std::end(arr));
|
Комментарии:
1. Итак, проблема, похоже, заключается в том, что if
std::begin
/std::end
areconstexpr
, подается с помощью aconstexpr std::array
иstd::max_element
isconstexpr
, почему вывод не может быть слишкомstd::max_element
?constexpr
2. Особенно учитывая
*std:max_element
, что выводconstexpr
Ответ №1:
it
должен хранить указатель на элемент arr
.
Поскольку arr
это не static
так, он находится в стеке, поэтому его адрес не может быть определен во время компиляции.
Это будет работать, если вы сделаете arr
static
.
Комментарии:
1. Интересно, учитывая
*std::max_element
работы, предположительно, он рассматривает получение итератора и отмену ссылки на него как единое монолитное выражение, которое само по себе может быть constexpr.2. @user3882729 Я не уверен, что я бы так сказал.
std::max_element
Вызов — это то, что может быть оценено во время компиляции «само по себе». Но значение, полученное в результате этой оценки, подлежит дальнейшим проверкам при попытке использовать его для инициализацииconstexpr
переменной. Итератор, который имеетamp;arr
«in», не передается, еслиarr
не являетсяstatic
, но разыменованное значение является атомарным и проходит. Итератор «естьconstexpr
» в том смысле, что он разрешен как промежуточное звено вconstexpr
вычислениях, но не как результат.