Переменные-шаблоны (variable templates)

Вольный перевод гл.5.6.

Да, мы имеем очень похожие термины для очень разных вещей: Переменная-шаблон (variable template) это переменная, которая является шаблоном ("переменная" здесь существительное). Вариативный шаблон (variadic template) - это шаблон с вариативным числом шаблонных параметров ("вариативный" здесь прилагательное).

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

template<typename T>constexpr T pi{3.1415926535897932385};

Как и для всех шаблонов это объявление не может находиться внутри функции или блока видимости.

Чтобы использовать переменную-шаблон, мы должны специфицировать её тип.
Например, ниже используются две различные переменные в области видимости, в которой объявлено  pi<>.

std::cout << pi<double> << ’\n’;
std::cout << pi
<float> << ’\n’;

Можно объявлять переменные-шаблоны, которые используются в различных единицах трансляции:

//== header.hpp:

template<typename T> T val{}; // zero initialized value

//== translation unit 1:

#include "header.hpp"

int main()
{
    val<
long> = 42;
    print();
}


//== translation unit 2:

#include "header.hpp"

void print()
{
    std::cout << val
<long> << ’\n’; // OK: prints 42
}
  

Переменные-шаблоны могут иметь шаблонные аргументы по умолчанию:

template<typename T = long double>constexpr T pi = T{3.1415926535897932385}; 

При использовании надо всегда указывать угловые скобки:

std::cout << pi << ’\n’; //ERROR 

Переменные-шаблоны могут быть параметризированы нетиповыми параметрами, которые также могут быть использованы, чтобы параметризировать инициализатор. Например

template<auto N>
constexpr decltype(N) dval = N; // тип dval зависит от переданной величины

int main()
{
   std::cout << dval<'c'> << '\n'; // N имеет величину ’c’ типа char
}

Переменные-шаблоны для членов данных.

Полезное применение для переменных-шаблонов заключается в определении переменных-членов шаблонного класса. Например, если шаблонный класс определен так:

template<typename T>class MyClass {  public:     static constexpr int max = 1000;
};
  


то вы можете определить

template<typename T>int myMax = MyClass<T>::max; 

поэтому прикладной программист может просто написать

auto i = myMax<std::string>; 

вместо

auto i = MyClass<std::string>::max; 

Это означает, что для класса стандартной библиотеки

namespace std
{                   template<typename T> class numeric_limits {                        public:
                         …

                            static constexpr bool is_signed = false;
                         …
                     };
}
  


вы можете определить

template<typename T>constexpr bool isSigned = std::numeric_limits<T>::is_signed; 

чтобы иметь возможность написать

isSigned<char> 

вместо

std::numeric_limits<char>::is_signed .

 Суффикс характеристик типов _v

Начиная с С++17, стандартная библиотека использует технику переменных-шаблонов для определения коротких имен для всех характеристик типов в STL, которые имеют булевское значение, например, теперь можно писать

std::is_const_v<T> // since C++17

вместо

std::is_const<T>::value //since C++11  


Комментарии

Популярные сообщения из этого блога

Полезные новации С++17. Выражения свертки (Fold expressions)

Перегрузка и специализация шаблонных функций.

Поддержка декомпозиции при объявлении (structural bindings) для классов