Страницы

Поиск по вопросам

суббота, 30 ноября 2019 г.

Шаблоны переменных в C++14

#c++ #шаблоны_с++ #c++14


Изучая новый стандарт C++, натолкнулся на нововведение «шаблоны переменных»

Синтаксис у шаблона следующий:

template < typename T >
constexpr T value = T(1234);


О применении шаблона написано:


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


Не вполне понимаю, как такая переменная будет использоваться в шаблонном алгоритме.
Не могли бы Вы привести несколько примеров использования этого механизма? Также не
понимаю, почему нельзя такое шаблонное constexpr выражение заменить нешаблонным, ведь
значение мы указываем явно, соответственно, и тип можем написать (вывести) явно.
    


Ответы

Ответ 1



В стандарте есть пример: template constexpr T pi = T(3.1415926535897932385L); template T circular_area(T r) { return pi * r * r; } Здесь шаблон переменной позволяет получить константу нужного размера - float/double/etc. Другое популярное применение - это замена is_some::value на is_some_v, например template< class T, class U > inline constexpr bool is_same_v = is_same::value; // C++17

Ответ 2



Тут можно заметить, что при объявлении шаблона переменной тип этой переменной совсем не обязан совпадать с параметром шаблона или вообще быть как-то связан с параметром(-ами) шаблона. Большинство тривиальных примеров шаблонов переменных обычно дают переменной тот же самый тип, что использовался в параметре шаблона, что может создать ложное впечатление, как будто это требуется. На самом деле шаблонная переменная может иметь любой тип. Например, пользуясь примером с площадью окружности, вы можете принять решение использовать "базовое" определение константы PI с конкретным типом double template constexpr double PI = 3.141592653589793; а затем, пользуясь явной специализацией, добавить специализированные определения для отдельных плавающих типов template<> constexpr float PI = 3.1415927; template<> constexpr long double PI = 3.141592653589793238L; После этого можно будет реализовать "единую" шаблонную функцию вычисления площади окружности template T circle_area(T r) { return PI * r * r; } которая будет, например, работать и с целочисленными типами int area = circle_area(10); Для целочисленных типов в качестве константы PI будет браться вариант "по умолчанию" с типом double, а для плавающих типов будут использоваться специализированные значения этой константы. Вариант реализации этой функции из ответа @Abyx, как вы наверное заметили, тоже будет "работать" с целочисленными типами. Но в том варианте константа Пи для целочисленных типов получит целочисленное значение 3, что не всегда желательно. Также можно добавить, что возможность включения статических членов-данных в шаблоны классов существовала в языке С++ с самого начала стандартизованных времен, т.е. в С++98. Это позволяло реализовывать "шаблоны переменных" уже тогда, пользуясь фактически той же самой техникой, которая в С++98 применялась для "шаблонных typedef", т.е. через помещение типов или переменных в "обертку" шаблонного класса. В частности, вышеприведенный пример может быть реализован на классическом С++98 как template struct PI { static const double value; }; template const double PI::value = 3.141592653589793; template <> struct PI { static const float value; }; const float PI::value = 3.1415927; template <> struct PI { static const long double value; }; const long double PI::value = 3.141592653589793238L; template T circle_area(T r) { return PI::value * r * r; } Принимая это во внимание, можно сказать, что шаблонные переменные не являются каким-то фундаментально новым свойством С++14. Они (выражаясь нестрого) являются просто "синтаксическим сахаром", более компактным и элегантным вариантом синтаксиса для записи вышеприведенного С++98 варианта реализации. Ситуация аналогична введенной в С++11 возможность объявления шаблонных typedef (через using), которая тоже может быть названа "синтаксическим сахаром" над хорошо известной С++98 техникой "шаблонного typedef".

Комментариев нет:

Отправить комментарий