Форум программистов, компьютерный форум, киберфорум
Наши страницы
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг 4.75/4: Рейтинг темы: голосов - 4, средняя оценка - 4.75
daslex
1291 / 535 / 177
Регистрация: 02.08.2011
Сообщений: 2,756
#1

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

14.05.2016, 16:15. Просмотров 782. Ответов 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
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
14.05.2016, 16:15
Ответы с готовыми решениями:

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

Двумерный массив std::array. Размеры массива шаблоном
#include &lt;array&gt; #include &lt;iostream&gt; using std::array; using std::cout; ...

Ошибка error: invalid types 'int[int]' for array subscript
Дана строка,содержащая английский текст.Найти количество слов,начинающихся с...

Работа с массивом - Invalid types 'int[int]' for array subscript
Добрый день. Данный код выдает ошибку invalid types 'int' for array subscript в...

Error: invalid types 'int[int]' for array subscript
Написал программу список студентов через классы, но на вводе и выводе выдаёт...

36
Evg
Эксперт CАвтор FAQ
19117 / 6958 / 522
Регистрация: 30.03.2009
Сообщений: 19,586
Записей в блоге: 30
14.05.2016, 16:27 #2
const означает не "константа", а "немодифицируемый (неизменный)"
1
daslex
1291 / 535 / 177
Регистрация: 02.08.2011
Сообщений: 2,756
14.05.2016, 17:19  [ТС] #3
Я предпочту увидеть ответ на заданный вопрос. Пример не компилируется, почему?

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

В вашем случае ROW инициализировано при помощи вызова constexpr метода std::array<>::size() через ссылку. Методы, вызванные через ссылку, не порождают Целочисленного Константного Выражения, даже если эти методы являются constexpr.
1
daslex
1291 / 535 / 177
Регистрация: 02.08.2011
Сообщений: 2,756
14.05.2016, 19:52  [ТС] #5
В моём случае: то, что я в ROW пихаю, неизвестно на этапе компиляции;
Вот и всё.
0
TheCalligrapher
С чаем беда...
Эксперт CЭксперт С++
4385 / 2360 / 655
Регистрация: 18.10.2014
Сообщений: 4,002
14.05.2016, 20:19 #6
Цитата Сообщение от daslex Посмотреть сообщение
В моём случае: то, что я в ROW пихаю, неизвестно на этапе компиляции;
Ну это было бы слишком просто. Это вы фактически перефразировали сообщение об ошибке.

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

http://coliru.stacked-crooked.com/a/0fd08c4ad15dc04f

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

http://coliru.stacked-crooked.com/a/fbec803a33d6f578

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

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

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

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

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

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

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

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

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

Вопрос в данном случае только в том, относится ли данный случай к набору таких контекстов.
2
Evg
Эксперт CАвтор FAQ
19117 / 6958 / 522
Регистрация: 30.03.2009
Сообщений: 19,586
Записей в блоге: 30
14.05.2016, 21:31 #9
Сдаётся мне, если есть два массива

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

Добавлено через 4 минуты
Коли о ссылках рассуждать, то я бы и о && не хотел забывать. Там тоже как с &.
0
TheCalligrapher
С чаем беда...
Эксперт CЭксперт С++
4385 / 2360 / 655
Регистрация: 18.10.2014
Сообщений: 4,002
14.05.2016, 22:06 #11
Цитата Сообщение от 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
19117 / 6958 / 522
Регистрация: 30.03.2009
Сообщений: 19,586
Записей в блоге: 30
14.05.2016, 22:38 #12
Чота под вечер я тупить начал
0
daslex
1291 / 535 / 177
Регистрация: 02.08.2011
Сообщений: 2,756
14.05.2016, 23:03  [ТС] #13
Итак, обсуждаем теперь

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
rikimaru2013
C++ Game Dev
2471 / 1140 / 348
Регистрация: 30.11.2013
Сообщений: 3,709
18.05.2016, 01:37 #14
daslex, я не спец как вот hoggy может вам ответить , но вроде бы ответ очевиден - ссылка это абстрактная сущность времени выполнении: для взятия размера нужен объект (дяда с адрессом, который оживает только вовремя выполнения)
0
daslex
1291 / 535 / 177
Регистрация: 02.08.2011
Сообщений: 2,756
18.05.2016, 01:43  [ТС] #15
А без ссылки не абстрактная сущность времени выполнения?
0
hoggy
Заблокирован
18.05.2016, 02:09 #16
Цитата Сообщение от daslex Посмотреть сообщение
const int ROW = arr.size();
* * array<T,ROW> temp; *//<-- Где я что-то не понял?
error C2971: std::array: параметр шаблона "_Size": ROW: локальная переменная не может использоваться в качестве аргумента, не являющегося типом
Цитата Сообщение от rikimaru2013 Посмотреть сообщение
ссылка это абстрактная сущность времени выполнении
1.
ссылки - псевдонимы имен объектов.
а компиляторы замечательно умеют различать объекты
по их именам.

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

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

проблема с компиляторами студии: они до сих пор его не осилили.
0
TheCalligrapher
С чаем беда...
Эксперт CЭксперт С++
4385 / 2360 / 655
Регистрация: 18.10.2014
Сообщений: 4,002
18.05.2016, 02:18 #17
Цитата Сообщение от hoggy Посмотреть сообщение
код валидный, и успешно собирается компиляторами,
которые поддерживают constexpr.
Как уже говорилось выше, код НЕ собирается clang - ошибка в обоих функциях одна и та же

Код
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
Заблокирован
18.05.2016, 02:45 #18
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
Как уже говорилось выше, код НЕ собирается clang - ошибка в обоих функциях одна и та же
значит он так же не осилил constexpr

Добавлено через 3 минуты
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
Clang, разумеется, поддерживает constexpr, однако не считает arr.size() константным выражением, пока вызов делается через ссылку.
я понял.
0
TheCalligrapher
С чаем беда...
Эксперт CЭксперт С++
4385 / 2360 / 655
Регистрация: 18.10.2014
Сообщений: 4,002
18.05.2016, 03:15 #19
Цитата Сообщение от 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
daslex
1291 / 535 / 177
Регистрация: 02.08.2011
Сообщений: 2,756
24.05.2016, 21:16  [ТС] #20
Я тут немного подумал, так как словечки выше какие-то заморские, непонятные, и вот что решил:
В параметрах функции не может быть 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
24.05.2016, 21:16
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
24.05.2016, 21:16

Error: invalid types 'int[int]' for array subscript
#include &lt;iostream&gt; using namespace std; int main() { setlocale(0,&quot; &quot;);...

Ошибка: invalid types ‘int[int]’ for array subscript
Всем доброго дня, после компиляции выводится ошибка, которая меня вводит в...

Invalid types 'int[int]' for array subscript
Добрый день! Не компилится код. Выдается ошибка invalid types 'int' for array...


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru