2. На Основе Книги Мейерса «Эффективный И Современный C++» — Подробности Вывода Типов Шаблонов Для Массивов.



Добрый день, дорогой читатель! Эта статья — вторая в серии обзорных статей, которые я буду писать, читая бестселлер Скотта Мейерса «Эффективный и современный C++».

Каждая из этих статей будет соответствовать отдельному каталогу в проект, специально созданный на github.com с живыми примерами использования того, что мы читаем сегодня.

Эта статья дополняет правила вывода типов из предыдущей статьи и рассматривает отдельные аспекты вывода типа шаблона для аргументов массива и функции.

Определение типа шаблона для массива Компилятор C++ имеет такое свойство, что объявленный массив всегда при передаче функции шаблона с объявленным параметром не как ссылка всегда преобразуется в указатель на сохраненный тип и обратно; если параметр объявлен как ссылка, то такое преобразование не выполняется.



Функции шаблона:

Для начала приведу код шаблонных функций, выводящих заветные типы, а затем сам процесс вывода:
  
  
  
  
  
  
  
   

template<typename T> void paramDeductInfo(T param, const char *initType) { std::cout << initType << " -> (T param) -> " << type_id_with_cvr<T>().

pretty_name() << std::endl; }; template<typename T> void refParamDeductInfo(T &param, const char *initType) { std::cout << initType << " -> (T &param) -> " << type_id_with_cvr<T>().

pretty_name() << std::endl; };



Тип вывода:



cli::printCaption("TYPE DEDUCTION FOR ARRAY OF CHAR"); char charSeq[] = "Hi everyone!"; paramDeductInfo(charSeq, "char []"); refParamDeductInfo(charSeq, "char []"); cli::printCaption("TYPE DEDUCTION FOR ARRAY OF INT"); int intSeq[] = {1, 2, 3}; paramDeductInfo(intSeq, "int []"); refParamDeductInfo(intSeq, "int []"); cli::printCaption("TYPE DEDUCTION FOR ARRAY OF CLASS A"); class A { } const classASeq[] = {A(), A(), A()}; paramDeductInfo(classASeq, "class A[]"); refParamDeductInfo(classASeq, "class A[]");

Следующий псевдокод отражает консольный вывод этих инструкций:

************************************************************************************************************************ TYPE DEDUCTION FOR ARRAY OF CHAR ************************************************************************************************************************ char [] -> (T param) -> char* char [] -> (T &param) -> char [13] ************************************************************************************************************************ TYPE DEDUCTION FOR ARRAY OF INT ************************************************************************************************************************ int [] -> (T param) -> int* int [] -> (T &param) -> int [3] ************************************************************************************************************************ TYPE DEDUCTION FOR ARRAY OF CLASS A ************************************************************************************************************************ class A[] -> (T param) -> main::A const* class A[] -> (T &param) -> main::A const [3]



Пример 1. Анализ длины массива во время компиляции

Более того, предполагаемый тип массива хранит информацию о его размере, которую можно использовать в функции шаблона для управления размером массива во время компиляции или для создания более производительного кода.

Я использовал эту функцию в функции printCaption чтобы ограничить длину заголовка, отображаемого в командной строке во время компиляции.

Это мелочь, но приятно.



namespace cli { template<typename T, std::size_t N> constexpr void printCaption(T (&capValue)[N]) { static_assert(N <= 121, "caption length should be less than 120"); std::cout << std::endl << "*******************************************************************************" << std::endl << capValue << std::endl << "*******************************************************************************" << std::endl << std::endl; }; }

Давайте проверим, не возникнет ли ошибка, если мы введем заголовок, явно не соответствующий требованиям.



cli::printCaption("123456789 123456789 123456789 123456789 123456789 123456789 123456789" "123456789 123456789 123456789 123456789 123456789 !");

И вот, разве это не чудесно?

/.

sources/cli.h:12:3: error: static assertion failed: caption length should be less than 120 static_assert(N <= 121, "caption length should be less than 120"); ^~~~~~~~~~~~~



Пример 2. foreach для массива в памяти

Я думаю, что может оказаться полезным другой подход: если у нас есть размер массива во время компиляции, почему бы не использовать его для организации цикла по такому массиву?

template<typename T, size_t N, typename F> void forEachOnAnArray(T (&inmemArray)[N], F &callback) { for (int i = 0; i < N; ++i) callback(inmemArray[i]); };



Использование этой функции выглядит следующим образом:



auto printInt = [](int value) { std::cout << " " << value; }; forEachOnAnArray(intSeq, printInt);

В общем, использование этой возможности ни в коем случае не ограничивается извлечением размера массива.



Вывод типа для функции

Говоря о выводе типа функции, Мейерс краток.

Он точно упоминает, что они приводятся к указателю так же, как это делается для массивов, за исключением случаев, когда параметр шаблонной функции, по которому должен быть выведен тип нашей функции, не объявлен как ссылка.

Вероятно, ему следовало бы рассказать о каких-то обертках шаблонных функций, но я думаю, что это просто выходит за рамки вопроса эффективного и современного C++.

Мы, мой дорогой читатель, обязательно вернёмся к этому вопросу!

Спасибо и хорошего дня!!

Теги: #c++11 #c++14 #c++17 #C++ #C++ #Профессиональная литература
Вместе с данным постом часто просматривают:

Автор Статьи


Зарегистрирован: 2019-12-10 15:07:06
Баллов опыта: 0
Всего постов на сайте: 0
Всего комментарий на сайте: 0
Dima Manisha

Dima Manisha

Эксперт Wmlog. Профессиональный веб-мастер, SEO-специалист, дизайнер, маркетолог и интернет-предприниматель.