Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.73/11: Рейтинг темы: голосов - 11, средняя оценка - 4.73
738 / 342 / 71
Регистрация: 10.06.2014
Сообщений: 2,358
1

Вычисление размера массива на этапе компиляции

20.03.2017, 16:20. Просмотров 2014. Ответов 11
Метки нет (Все метки)

Нашел код который вычисляет размер массива на этапе компиляции
Но сам код мне не понятен. Объясните плз

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream>
 
template<typename T, std::size_t N>
constexpr std::size_t arraySize (T (&) [N] ) noexcept
{
    return N;
}
 
int main()
{
    int arr[100];
    std::cout << arraySize(arr);
}
http://rextester.com/XLBA70312

То, что передается ссылка на массив это понятно. Не понятно следующее:
1. Здесь явно не задан тип шаблонного аргумента typename T и значения по умолчанию у него тоже нет. Как тогда это работает?
2. Каким образом шаблонного параметру std::size_t N присваивается размер массива?
3. Еще не понятно почему знак ссылки взят в скобки
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
20.03.2017, 16:20
Ответы с готовыми решениями:

Задание размера массива на этапе исполнения
Qt 5.4.1, MinGW 32bit... спокойно кушает такой код: #include &lt;iostream&gt; int main () { int...

Как добавить анонимный тип в объект не на этапе компиляции, а на этапе выполнения программы? Надо для routes.MapRoute
В приложении ASP.NET MVC у меня есть xml файл с маршрутами типа: &lt;route url=&quot;Home/{par1}/{par2}&quot;...

Typedef структуры массива с заполнением ячеек на этапе компиляции
Есть структура следующего вида: typedef union { struct{ unsigned long...

C++14: вычисления на этапе компиляции
Добрый день. Есть такой код:struct Qaz { constexpr Qaz(uint8_t index) : _index(index) {} ...

11
Don't worry, be happy
16921 / 9797 / 1887
Регистрация: 27.09.2012
Сообщений: 24,296
Записей в блоге: 2
20.03.2017, 16:38 2
Цитата Сообщение от sys_beginner Посмотреть сообщение
Как тогда это работает?
Тип выводится исходя из аргумента функции.
Цитата Сообщение от sys_beginner Посмотреть сообщение
Каким образом шаблонного параметру std::size_t N присваивается размер массива?
Исходя из аргумента функции.
Цитата Сообщение от sys_beginner Посмотреть сообщение
Еще не понятно почему знак ссылки взят в скобки
Потому что синтаксис такой. Это ссылка на массив.
В данном случае без имени, потому как всё равно не используется.
1
738 / 342 / 71
Регистрация: 10.06.2014
Сообщений: 2,358
20.03.2017, 16:46  [ТС] 3
Цитата Сообщение от Croessmah Посмотреть сообщение
Тип выводится исходя из аргумента функции.
C++
1
2
3
4
5
6
#include <set>
    
int main()
{
    std::set s = {1,2,3};
}
А почему тут не выводится? тоже ведь шаблон и тип значений так же известен
Тем не менее приходится явно указывать тип
Или это относится только к функциям?

Цитата Сообщение от Croessmah Посмотреть сообщение
Исходя из аргумента функции.
Я просто не могу понять как это работает. Обычно когда пишем arr[N] это обращение к конкретному элементу массива
А в этом случае каким то волшебным образом идет присваивание значения для N
Именно логика присвоения не понятна. Тут же чтение и нет операций записи данных в N
0
techpriest
634 / 213 / 57
Регистрация: 27.02.2014
Сообщений: 1,176
20.03.2017, 17:01 4
1. Компилятор видит, что создаётся экземпляр int arr[100]
2. Компилятор видит, что arr передаётся шаблонной функции arraySize.
3. Компилятор старается подобрать необходимый инстант шаблона функции, который смог бы принять передаваемый аргумент. Для этого ему нужно подобрать шаблонные параметры T и N. В конечном итоге он выводит инстант.

C++
1
2
3
4
constexpr std::size_t arraySize (int (&) [100] ) noexcept
{
    return 100;
}
Это функция, которая генерируется компилятором на основе предоставленного вами шаблона специально для обработки текущего вызова. Ключевым момент является здесь то, что функция
C++
1
2
3
4
constexpr std::size_t arraySize (int (&) [99] ) noexcept
{
    return 99;
}
Не смогла бы принять ваш аргумент.

std::set s = {1,2,3};
К сожалению, правила определяемые стандартом языка разрешают автоматический вывод параметров шаблонных типов далеко не во всех случаях. Для функций автоматический вывод выполняется. Для конструирования объектов - нет...

Добавлено через 3 минуты
Я думаю, вам просто следует почитать о том, как работают шаблоны.
1
738 / 342 / 71
Регистрация: 10.06.2014
Сообщений: 2,358
20.03.2017, 17:01  [ТС] 5
Цитата Сообщение от Mirmik Посмотреть сообщение
1. Компилятор видит, что создаётся экземпляр int arr[100]
2. Компилятор видит, что arr передаётся шаблонной функции arraySize.
Это понятно, просто это уже не похоже на функцию, скорее на какую то магическую запись, которая вычисляет размер массива. Вот с точки зрения функции мне логика не понятна
0
491 / 205 / 69
Регистрация: 27.05.2016
Сообщений: 549
20.03.2017, 17:04 6
Цитата Сообщение от sys_beginner Посмотреть сообщение
А почему тут не выводится? тоже ведь шаблон и тип значений так же известен
Потому что это не функция.

Добавлено через 59 секунд
Цитата Сообщение от sys_beginner Посмотреть сообщение
Или это относится только к функциям?
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
template <typename T, typename U>
void foo(U&)
{
    T t;
};
 
template <typename U>
void bar(U&)
{};
 
int main()
{
    int val = 0;
    foo<double>(val);
    //foo(val); // error
    bar(val);
}
1
Don't worry, be happy
16921 / 9797 / 1887
Регистрация: 27.09.2012
Сообщений: 24,296
Записей в блоге: 2
20.03.2017, 17:05 7
Лучший ответ Сообщение было отмечено Undisputed как решение

Решение

Цитата Сообщение от sys_beginner Посмотреть сообщение
А почему тут не выводится?
Дедукция доступна только для шаблонов функций.
Начиная с C++17 и для шаблонов классов,
но здесь тоже свои заковырки будут.
Цитата Сообщение от sys_beginner Посмотреть сообщение
Обычно когда пишем arr[N] это обращение к конкретному элементу массива
Причем здесь обращение к массиву?
C++
1
2
int arr[10];//Массив arr
int (&ref)[10] = arr;//Ссылка на массив arr
Цитата Сообщение от sys_beginner Посмотреть сообщение
А в этом случае каким то волшебным образом идет присваивание значения N
Вы передаете в функцию arr, тип которого int[100].
C++
1
2
3
4
5
6
template<typename T, std::size_t N>//какие должны быть T и N, чтобы это завелось?
constexpr std::size_t arraySize (T (&) [N] ) noexcept //передаете int[100], значит должно быть
//T = int
//N = 100
//Тогда тип аргумента будет int (&)[100] - ссылка на массив int'ов размером 100,
//и функция успешно заведется
1
techpriest
634 / 213 / 57
Регистрация: 27.02.2014
Сообщений: 1,176
20.03.2017, 17:08 8
sys_beginner А это и есть шаблонная магия... Сейчас мы используем шаблоны вовсе не для того, для чего они изначально создавались. Просто, в какой-то момент оказалось, что механизм автоматического вывода позволяет творить страшные, неестественные вещи... Фактически мы специальными магическими пасами загнали компилятор в условие, когда ему пришлось сгенерировать функцию, возвращающую число сто.
1
Don't worry, be happy
16921 / 9797 / 1887
Регистрация: 27.09.2012
Сообщений: 24,296
Записей в блоге: 2
20.03.2017, 17:12 9
Кстати, в C++17 имеется std::size.
1
738 / 342 / 71
Регистрация: 10.06.2014
Сообщений: 2,358
20.03.2017, 17:16  [ТС] 10
Большое всем спасибо!

Добавлено через 45 секунд
Цитата Сообщение от Croessmah Посмотреть сообщение
Кстати, в C++17 имеется std::size.
То есть та же самая функция только самому писать не нужно
0
Don't worry, be happy
16921 / 9797 / 1887
Регистрация: 27.09.2012
Сообщений: 24,296
Записей в блоге: 2
20.03.2017, 17:18 11
Цитата Сообщение от sys_beginner Посмотреть сообщение
То есть та же самая функция только самому писать не нужно
Она работает не только с массивами, но и с контейнерами или с чем-то у чего есть sometype::size().
Просто для массивов имеется соответствующая специализация.
1
techpriest
634 / 213 / 57
Регистрация: 27.02.2014
Сообщений: 1,176
20.03.2017, 17:31 12
Еще не понятно почему знак ссылки взят в скобки.
Синтаксис ссылок такой же, как у указателей... Просто так записывается ссылка на массив...

C++
1
2
3
4
5
6
7
int main()
{
    int arr[100];
    int(&b)[100] = arr; //correct. b is referense of arr.
    
    int& c[100]; //error. array of refernces.
}
Выглядит, как писал один оч известный человек, как наркотический бред, но оно так есть...
1
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
20.03.2017, 17:31

Заказываю контрольные, курсовые, дипломные и любые другие студенческие работы здесь.

ошибка на этапе компиляции
в чём может быть проблема?

Ошибка на этапе компиляции
Добрый вечер. Ребят помогите, не могу понять в чем дело. Есть программа в которой описан 1 класс...

Загрузка изображений на этапе компиляции
Нужно загрузить на этапе компиляции 15 изображений. Делаю это так: var Img1:Class; var...

Чтение файла на этапе компиляции
Можно ли считать файл настроек на этапе компиляции? Нужно что бы выбросить код который в рантайме...


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

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

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