Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.79/34: Рейтинг темы: голосов - 34, средняя оценка - 4.79
1373 / 596 / 199
Регистрация: 02.08.2011
Сообщений: 2,886

Двумерный массив <array>. const int value = array.size(); value не константа?

14.05.2016, 16:15. Показов 6858. Ответов 36
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include <array>
#include <iostream>
 
using std::array;
using std::cout;
 
/*ФУНКЦИЯ ЗАПОЛНЕНИЯ МАССИВА ЗНАЧЕНИЯМИ*/
template <typename T>
void arr_init(T& arr, int count = 0){
    for (auto &i:arr){
        for (auto &j:i){
            j = count++;
        }
    }
}
 
/*ФУНКЦИЯ ВЫВОДА МАССИВА НА ЭКРАН*/
template <typename T>
void arr_show(T& arr){
    for (const auto &i:arr){
        for (const auto &j:i){
            cout << j << '\t';
        }   cout << '\n';
    }
}
 
/*ФУНКЦИЯ ПЕРЕМЕШИВАЕТ СТРОКИ*/
template <typename T>
void shuffle_row(T& arr){
    const int ROW = arr.size();
    array<T,ROW> temp;  //<-- Где я что-то не понял?
}
 
 
int main(){
    array<array<int,9>,10> arr;
 
    arr_init(arr);
    arr_show(arr);
    shuffle_row(arr);
}
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
14.05.2016, 16:15
Ответы с готовыми решениями:

Преобразовать указатель на int array в int array
Через SendMessage передаю указатель на int массив: int m_list; ::SendMessage((HWND)hwnd, MY_LIST, (WPARAM) this, (LPARAM)...

Расстановка девяти чисел (Turbo C) Выводит ошибку using Matrix = std::array<std::array<int, 3>, 3>; и bool NextSet
#include &lt;iostream&gt; #include &lt;array&gt; using Matrix = std::array&lt;std::array&lt;int, 3&gt;, 3&gt;; // взято отсюда:...

Присвоить значения переменных в массив Array (class Array в Turbo C++)
Здравствуйте!!! Изучаю help в Turbo C++ 3.1 дошел до класса Array: main() { //при подключение соответствующих библиотек и...

36
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
14.05.2016, 16:27
const означает не "константа", а "немодифицируемый (неизменный)"
1
1373 / 596 / 199
Регистрация: 02.08.2011
Сообщений: 2,886
14.05.2016, 17:19  [ТС]
Я предпочту увидеть ответ на заданный вопрос. Пример не компилируется, почему?

Добавлено через 30 минут
Всё. Вспомнил. Ответ не нужен.
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12937 / 6804 / 1821
Регистрация: 18.10.2014
Сообщений: 17,217
14.05.2016, 19:33
Цитата Сообщение от daslex Посмотреть сообщение
Пример не компилируется, почему?
Пример не компилируется потому, что в языке С++ целочисленное const значение является Целочисленным Константным Выражением тогда и только тогда, когда его инициализатор является Целочисленным Константным Выражением.

В вашем случае ROW инициализировано при помощи вызова constexpr метода std::array<>::size() через ссылку. Методы, вызванные через ссылку, не порождают Целочисленного Константного Выражения, даже если эти методы являются constexpr.
1
1373 / 596 / 199
Регистрация: 02.08.2011
Сообщений: 2,886
14.05.2016, 19:52  [ТС]
В моём случае: то, что я в ROW пихаю, неизвестно на этапе компиляции;
Вот и всё.
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12937 / 6804 / 1821
Регистрация: 18.10.2014
Сообщений: 17,217
14.05.2016, 20:19
Цитата Сообщение от daslex Посмотреть сообщение
В моём случае: то, что я в ROW пихаю, неизвестно на этапе компиляции;
Ну это было бы слишком просто. Это вы фактически перефразировали сообщение об ошибке.

Сразу надо заметить, что ваш оригинальный код прекрасно компилируется gcc

http://coliru.stacked-crooked.... 4ad15dc04f

А вот clang выдает ошибку

http://coliru.stacked-crooked.... 3a33d6f578

То есть вопрос несколько неоднозначный.

Метод std::array<>::size() является constexpr, причем его результат напрямую определяется шаблонным параметром. Т.е. теоретически это значение прекрасно известно на этапе компиляции и теоретически у компилятора есть все необходимое для того, чтобы вычислить это constexpr именно как constexpr, т.е. именно на этапе компиляции. Что gcc и делает.

Для clang, похоже, преградой тут является именно вызов constexpr метода через ссылку. Если в вашем примере убрать ссылку с объявления параметра, то пример начнет прекрасно компилироваться и в clang.

А вот как правильно - надо разбираться...
2
1373 / 596 / 199
Регистрация: 02.08.2011
Сообщений: 2,886
14.05.2016, 21:11  [ТС]
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
Сразу надо заметить, что ваш оригинальный код прекрасно компилируется gcc
Ну, не эксперт я, я - чайник.

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

В общем, правильно как в clang, а оптимизации эти - это оптимизации.

Добавлено через 3 минуты
Если надо разбираться, я как бы не против.

Добавлено через 41 минуту
Студия так пишет:
Ошибка C2971 std::array: параметр шаблона "_Size": ROW: переменная с нестатической длительностью хранения не может использоваться в качестве аргумента, не являющегося типом
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12937 / 6804 / 1821
Регистрация: 18.10.2014
Сообщений: 17,217
14.05.2016, 21:13
Цитата Сообщение от daslex Посмотреть сообщение
Некоторые компиляторы при оптимизациях иногда умеют вычислять то, что предполагается константой ещё до выполнения. То есть фактически это так и выглядит, что вроде должно быть неизвестно, но как по мановению волшебной палочки почему-то известным становится ещё до компиляции. Как-то так.
Такая логика применима именно и только к оптимизациям - то есть к контекстам, в которых формально безразлично, будет ли значение вычислено на этапе компиляции или на этапе выполнения. Это чисто количественный вопрос, ибо такие контексты не влияют на корректность (то есть компилируемость) программы.

Когда же речь заходит о таких принципиальных качественных вопросах, как формирование Целочисленных Константных Выражений, т.е. решениях, влияющих на компилируемость кода, то тут спецификация языка никакой свободы компиляторам не предоставляет. Контексты, в которых const и constexpr обязаны порождать Целочисленные Константные Выражения (т.е. порождать значения, известные на стадии компиляции), оговорены однозначно.

Вопрос в данном случае только в том, относится ли данный случай к набору таких контекстов.
2
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
14.05.2016, 21:31
Сдаётся мне, если есть два массива

C++
array<int,10> a;
array<int,20> b;
 
shuffle_row(a);
shuffle_row(b);
то инстанциация шаблоной функции shuffle_row становится невозможной, потому что невозможно будет правильно задать шаблон для массива temp. Т.е. должны будут одновременно существовать две реализации shuffle_row<int> с различными типами temp. Поэтому по хорошему такой код компилятору следует запрещать
1
1373 / 596 / 199
Регистрация: 02.08.2011
Сообщений: 2,886
14.05.2016, 21:47  [ТС]
Цитата Сообщение от Evg Посмотреть сообщение
то инстанциация шаблоной функции shuffle_row становится невозможной
Ну gcc считает возможной, я на сайте том же проверил, на который тут сослано.
Хотя по логике возможным быть не должно.

Добавлено через 4 минуты
Коли о ссылках рассуждать, то я бы и о && не хотел забывать. Там тоже как с &.
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12937 / 6804 / 1821
Регистрация: 18.10.2014
Сообщений: 17,217
14.05.2016, 22:06
Цитата Сообщение от Evg Посмотреть сообщение
то инстанциация шаблоной функции shuffle_row становится невозможной, потому что невозможно будет правильно задать шаблон для массива temp.
В смысле? С точки зрения классической инстанциации shuffle_row<T>, array<int,10> и array<int,20> - это два совершенно разных, совершенно независисмых типа Т. Поэтому в данном примере будет инстанциироваться две отдельных, ничего друг о друге не знающих специализации функции shuffle_row: скажем shuffle_row_std_array_int_10 и shuffle_row_std_array_int_20. В каждой будет свой массив temp и никаких неоднозначностей с его размером не будет.

Цитата Сообщение от Evg Посмотреть сообщение
Т.е. должны будут одновременно существовать две реализации shuffle_row<int> с различными типами temp.
В этом коде нет shuffle_row<int>. В этом коде инстанциируется именно shuffle_row<std::array<...>>, а это совсем другая история.


Цитата Сообщение от Evg Посмотреть сообщение
Поэтому по хорошему такой код компилятору следует запрещать
Это зачем это его запрещать? Это фундаметальная функциональность шаблонов. А уж то, что автор кода применил ее именно так - это вопрос к автору кода.
1
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
14.05.2016, 22:38
Чота под вечер я тупить начал
0
1373 / 596 / 199
Регистрация: 02.08.2011
Сообщений: 2,886
14.05.2016, 23:03  [ТС]
Итак, обсуждаем теперь

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <array>
#include <iostream>
 
using std::array;
using std::cout;
 
 
template <class T>
void foo1(T& arr) {
    constexpr int ROW = arr.size();
}
 
template <class T>
void foo1(T&& arr) {
    constexpr int ROW = arr.size();
}
 
 
int main() {
    array<array<int, 9>, 10> arr = {};
    //foo1(arr);  //<-- Пока не напишу, претензий не имеется
    //foo2(arr);
}
0
2549 / 1208 / 358
Регистрация: 30.11.2013
Сообщений: 3,826
18.05.2016, 01:37
daslex, я не спец как вот hoggy может вам ответить , но вроде бы ответ очевиден - ссылка это абстрактная сущность времени выполнении: для взятия размера нужен объект (дяда с адрессом, который оживает только вовремя выполнения)
0
1373 / 596 / 199
Регистрация: 02.08.2011
Сообщений: 2,886
18.05.2016, 01:43  [ТС]
А без ссылки не абстрактная сущность времени выполнения?
0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
18.05.2016, 02:09
Цитата Сообщение от daslex Посмотреть сообщение
const int ROW = arr.size();
* * array<T,ROW> temp; *//<-- Где я что-то не понял?
error C2971: std::array: параметр шаблона "_Size": ROW: локальная переменная не может использоваться в качестве аргумента, не являющегося типом
Цитата Сообщение от rikimaru2013 Посмотреть сообщение
ссылка это абстрактная сущность времени выполнении
1.
ссылки - псевдонимы имен объектов.
а компиляторы замечательно умеют различать объекты
по их именам.

2.
ссылки могут быть использованы в качестве параметров шаблона.

3.
к конкретно данной ситуации (#13) ссылки не имеют ни малейшего отношения.
код валидный, и успешно собирается компиляторами,
которые поддерживают constexpr.

проблема с компиляторами студии: они до сих пор его не осилили.
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12937 / 6804 / 1821
Регистрация: 18.10.2014
Сообщений: 17,217
18.05.2016, 02:18
Цитата Сообщение от hoggy Посмотреть сообщение
код валидный, и успешно собирается компиляторами,
которые поддерживают constexpr.
Как уже говорилось выше, код НЕ собирается clang - ошибка в обоих функциях одна и та же

Code
1
2
3
4
5
6
7
8
clang -std=c++14 -pedantic-errors main.cpp
 
main.cpp:10:25: error: constexpr variable 'ROW' must be initialized by a constant expression
    constexpr int ROW = arr.size();
                        ^~~~~~~~~~
main.cpp:15:25: error: constexpr variable 'ROW' must be initialized by a constant expression
    constexpr int ROW = arr.size();
                        ^~~~~~~~~~
Clang, разумеется, поддерживает constexpr, однако не считает arr.size() константным выражением, пока вызов делается через ссылку.
0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
18.05.2016, 02:45
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
Как уже говорилось выше, код НЕ собирается clang - ошибка в обоих функциях одна и та же
значит он так же не осилил constexpr

Добавлено через 3 минуты
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
Clang, разумеется, поддерживает constexpr, однако не считает arr.size() константным выражением, пока вызов делается через ссылку.
я понял.
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12937 / 6804 / 1821
Регистрация: 18.10.2014
Сообщений: 17,217
18.05.2016, 03:15
Цитата Сообщение от hoggy Посмотреть сообщение
значит он так же не осилил constexpr
Нет, как раз таки в данном случае похоже, что это именно GCC позволяет себе слишком много и/или пытается бежать впереди паровоза.

Добавлено через 12 минут
А именно, согласно цитате, которую мне подсказали на StackOverflow, core constant expression e не должно содержать вычисления

- an id-expression that refers to a variable or data member of reference type unless the reference has a preceding initialization and either
-- it is initialized with a constant expression or
-- its lifetime began within the evaluation of e;
Именно это требование нарушено в данном случае. Прав именно clang.
1
1373 / 596 / 199
Регистрация: 02.08.2011
Сообщений: 2,886
24.05.2016, 21:16  [ТС]
Я тут немного подумал, так как словечки выше какие-то заморские, непонятные, и вот что решил:
В параметрах функции не может быть constexpr, поэтому оно и не интерпретируется как константа
В случае локальной копии
C++
1
2
3
4
template <class T>
void foo1(T arr) {
    constexpr int ROW = arr.size();
}
Получается что-то вида
C++
1
2
3
4
5
void foo(){
   size_t temp = arr.size(); //данные по arr тут известны и вычисляемо на этапе компиляции
   constexpr int ROW = temp; //constexpr вне параметров функции
   T arr[temp]; //Вне параметров функции, ну а тип Т известен, всё на этапе компиляции
}
А в случаях
C++
1
2
void foo1(T& arr)
void foo1(T&& arr)
Вычисление arr.size(); попадает вовнутрь параметров функции, а не в её тело. Только один нюанс мешает, constexpr в параметры функции всовывать непозволительно

========================
Я может где немного неправильно выразился, но суть должна быть понятна. Если так рассуждать, то как-то легко всё встаёт на свои места и напрашивается вывод на глюк в тексте предупреждения.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
24.05.2016, 21:16
Помогаю со студенческими работами здесь

SIZE of array is not computable
мой код: open (666, file = &quot;debug.txt&quot;) write(666,*) 'begin' DO i=1,size(x) write(666,*) x(i) end do не могу понять в чем...

Array with unknown size
Имеется некий текстовый массив: string arr = new string Допустим, что хотя бы цифру m мы знаем (например 5), но вот цифру n никак,...

Delphi. Двумерный массив. Заполнить массив А следующим образом var A:array [1.10, 1.10] of byte; :
Помогите решить задачу, как заполнить ее в StringGrid var A:array of byte; Заполнить массив А следующим образом: 1 2 … ...

Переписать программу через класс Array (двумерный массив).
Помогите написать вот эту программу через класс Array(двумерный массив) using System; using System.Collections.Generic; using...

Двумерный массив std::array. Размеры массива шаблоном
#include &lt;array&gt; #include &lt;iostream&gt; using std::array; using std::cout; template &lt;typename T, size_t N, size_t M&gt; void...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Работа со звуком через SDL3_mixer
8Observer8 08.02.2026
Содержание блога Пошагово создадим проект для загрузки звукового файла и воспроизведения звука с помощью библиотеки SDL3_mixer. Звук будет воспроизводиться по клику мышки по холсту на Desktop и по. . .
SDL3 для Web (WebAssembly): Основы отладки веб-приложений на SDL3 по USB и Wi-Fi, запущенных в браузере мобильных устройств
8Observer8 07.02.2026
Содержание блога Браузер Chrome имеет средства для отладки мобильных веб-приложений по USB. В этой пошаговой инструкции ограничимся работой с консолью. Вывод в консоль - это часть процесса. . .
SDL3 для Web (WebAssembly): Обработчик клика мыши в браузере ПК и касания экрана в браузере на мобильном устройстве
8Observer8 02.02.2026
Содержание блога Для начала пошагово создадим рабочий пример для подготовки к экспериментам в браузере ПК и в браузере мобильного устройства. Потом напишем обработчик клика мыши и обработчик. . .
Философия технологии
iceja 01.02.2026
На мой взгляд у человека в технических проектах остается роль генерального директора. Все остальное нейронки делают уже лучше человека. Они не могут нести предпринимательские риски, не могут. . .
SDL3 для Web (WebAssembly): Вывод текста со шрифтом TTF с помощью SDL3_ttf
8Observer8 01.02.2026
Содержание блога В этой пошаговой инструкции создадим с нуля веб-приложение, которое выводит текст в окне браузера. Запустим на Android на локальном сервере. Загрузим Release на бесплатный. . .
SDL3 для Web (WebAssembly): Сборка C/C++ проекта из консоли
8Observer8 30.01.2026
Содержание блога Если вы откроете примеры для начинающих на официальном репозитории SDL3 в папке: examples, то вы увидите, что все примеры используют следующие четыре обязательные функции, а. . .
SDL3 для Web (WebAssembly): Установка Emscripten SDK (emsdk) и CMake для сборки C и C++ приложений в Wasm
8Observer8 30.01.2026
Содержание блога Для того чтобы скачать Emscripten SDK (emsdk) необходимо сначало скачать и уставить Git: Install for Windows. Следуйте стандартной процедуре установки Git через установщик. . . .
SDL3 для Android: Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 29.01.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами. Версия v3 была полностью переписана на Си, в. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru