Форум программистов, компьютерный форум, киберфорум
Наши страницы

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
daslex
1290 / 534 / 110
Регистрация: 02.08.2011
Сообщений: 2,756
#1

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

14.05.2016, 16:15. Просмотров 724. Ответов 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>. const int value = array.size(); value не константа? (C++):

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

Двумерный массив std::array. Размеры массива шаблоном - C++
#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...

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

Работа с массивом - Invalid types 'int[int]' for array subscript - C++
Добрый день. Данный код выдает ошибку invalid types 'int' for array subscript в функции в строке cout &lt;&lt;dm; Не понимаю в чем ошибка....

Ошибка: invalid types ‘int[int]’ for array subscript - C++
Всем доброго дня, после компиляции выводится ошибка, которая меня вводит в ступор. #include &quot;blitz.h&quot; double dummy11 = 0.0; Array...

Invalid types `int[int]' for array subscript - C++
Есть структура в которой есть данные. Хочу поменять значение void editz(char db) {readdb(db); int j,a; cout&lt;&lt;&quot;kakoy nomer...

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

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

В вашем случае ROW инициализировано при помощи вызова constexpr метода std::array<>::size() через ссылку. Методы, вызванные через ссылку, не порождают Целочисленного Константного Выражения, даже если эти методы являются constexpr.
1
daslex
1290 / 534 / 110
Регистрация: 02.08.2011
Сообщений: 2,756
14.05.2016, 19:52  [ТС] #5
В моём случае: то, что я в ROW пихаю, неизвестно на этапе компиляции;
Вот и всё.
0
TheCalligrapher
С чаем беда...
Эксперт CЭксперт С++
4276 / 2295 / 567
Регистрация: 18.10.2014
Сообщений: 3,910
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
1290 / 534 / 110
Регистрация: 02.08.2011
Сообщений: 2,756
14.05.2016, 21:11  [ТС] #7
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
Сразу надо заметить, что ваш оригинальный код прекрасно компилируется gcc
Ну, не эксперт я, я - чайник.

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

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

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

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

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

Вопрос в данном случае только в том, относится ли данный случай к набору таких контекстов.
2
Evg
Эксперт CАвтор FAQ
18885 / 6841 / 498
Регистрация: 30.03.2009
Сообщений: 19,265
Записей в блоге: 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
1290 / 534 / 110
Регистрация: 02.08.2011
Сообщений: 2,756
14.05.2016, 21:47  [ТС] #10
Цитата Сообщение от Evg Посмотреть сообщение
то инстанциация шаблоной функции shuffle_row становится невозможной
Ну gcc считает возможной, я на сайте том же проверил, на который тут сослано.
Хотя по логике возможным быть не должно.

Добавлено через 4 минуты
Коли о ссылках рассуждать, то я бы и о && не хотел забывать. Там тоже как с &.
0
TheCalligrapher
С чаем беда...
Эксперт CЭксперт С++
4276 / 2295 / 567
Регистрация: 18.10.2014
Сообщений: 3,910
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
18885 / 6841 / 498
Регистрация: 30.03.2009
Сообщений: 19,265
Записей в блоге: 30
14.05.2016, 22:38 #12
Чота под вечер я тупить начал
0
daslex
1290 / 534 / 110
Регистрация: 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 / 241
Регистрация: 30.11.2013
Сообщений: 3,709
18.05.2016, 01:37 #14
daslex, я не спец как вот hoggy может вам ответить , но вроде бы ответ очевиден - ссылка это абстрактная сущность времени выполнении: для взятия размера нужен объект (дяда с адрессом, который оживает только вовремя выполнения)
0
daslex
1290 / 534 / 110
Регистрация: 02.08.2011
Сообщений: 2,756
18.05.2016, 01:43  [ТС] #15
А без ссылки не абстрактная сущность времени выполнения?
0
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
18.05.2016, 01:43
Привет! Вот еще темы с ответами:

С++:invalid types 'int[int]' for array subscript - C++
Дана целочисленная прямоугольная матрица. Определить количество столбцов, не содержащих ни одного нулевого элемента. С++ ошибка...

Invalid types 'int[int]' for array subscript - C++
Добрый день! Не компилится код. Выдается ошибка invalid types 'int' for array subscript в строке a=abs(a-1); Помогите,...

int const * const foo(const int* param) const - разъясните значение квалификаторов - C++
int const * const foo(const int* param) const -----1------2----------3----------------4 1: ? 2: делает содержимое массива или...

Можно ли обойти ограничение на максимальный размер массива ? error C2148: total size of array must not exceed 0x7fffffff bytes - C++
Ну собственно Visual Studio 2012, платформа x64, при попытке создать массив из 10-и миллиардов элементов unsigned *test = new unsigned; ...


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

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

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